@@ -398,6 +398,99 @@ int test_wc_curve25519_shared_secret_zero_check(void)
398398 return EXPECT_RESULT ();
399399} /* END test_wc_curve25519_shared_secret_zero_check */
400400
401+ /*
402+ * Known-answer tests for wc_curve25519_shared_secret_ex.
403+ *
404+ * Both vectors share one private scalar and produce a shared secret that is a
405+ * small canonical value (9 and 16, little-endian). Because the result is close
406+ * to a multiple of the field prime, these exercise the final modular reduction
407+ * of the X25519 computation: a result that was only reduced mod 2^256 (or left
408+ * in [p, 2^255)) instead of fully reduced mod 2^255-19 would not match.
409+ * All values are 32-byte little-endian encodings per RFC 7748.
410+ */
411+ int test_wc_curve25519_shared_secret_ex_kat (void )
412+ {
413+ EXPECT_DECLS ;
414+ #if defined(HAVE_CURVE25519 ) && defined(HAVE_CURVE25519_KEY_IMPORT )
415+ /* Private scalar shared by both vectors. */
416+ static const byte kPriv [CURVE25519_KEYSIZE ] = {
417+ 0x60 , 0xa3 , 0xa4 , 0xf1 , 0x30 , 0xb9 , 0x8a , 0x5b ,
418+ 0xe4 , 0xb1 , 0xce , 0xdb , 0x7c , 0xb8 , 0x55 , 0x84 ,
419+ 0xa3 , 0x52 , 0x0e , 0x14 , 0x2d , 0x47 , 0x4d , 0xc9 ,
420+ 0xcc , 0xb9 , 0x09 , 0xa0 , 0x73 , 0xa9 , 0x76 , 0x7f
421+ };
422+ /* Vector 1 public value, expected shared secret == 9. */
423+ static const byte kPub1 [CURVE25519_KEYSIZE ] = {
424+ 0x3b , 0x18 , 0xdf , 0x1e , 0x50 , 0xb8 , 0x99 , 0xeb ,
425+ 0xd5 , 0x88 , 0xc3 , 0x16 , 0x1c , 0xbd , 0x3b , 0xf9 ,
426+ 0x8e , 0xbc , 0xc2 , 0xc1 , 0xf7 , 0xdf , 0x53 , 0xb8 ,
427+ 0x11 , 0xbd , 0x0e , 0x91 , 0xb4 , 0xd5 , 0x15 , 0x3d
428+ };
429+ static const byte kExpected1 [CURVE25519_KEYSIZE ] = {
430+ 0x09 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
431+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
432+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
433+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
434+ };
435+ /* Vector 2 public value, expected shared secret == 16. */
436+ static const byte kPub2 [CURVE25519_KEYSIZE ] = {
437+ 0xca , 0xb6 , 0xf9 , 0xe7 , 0xd8 , 0xce , 0x00 , 0xdf ,
438+ 0xce , 0xa9 , 0xbb , 0xd8 , 0xf0 , 0x69 , 0xef , 0x7f ,
439+ 0xb2 , 0xac , 0x50 , 0x4a , 0xbf , 0x83 , 0xb8 , 0x7d ,
440+ 0xb6 , 0x01 , 0xb5 , 0xae , 0x0a , 0x7f , 0x76 , 0x15
441+ };
442+ static const byte kExpected2 [CURVE25519_KEYSIZE ] = {
443+ 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
444+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
445+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
446+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
447+ };
448+ /* Table-driven so both vectors run through the identical code path. */
449+ struct {
450+ const byte * pub ;
451+ const byte * expected ;
452+ } vec [2 ];
453+ curve25519_key private_key ;
454+ curve25519_key public_key ;
455+ WC_RNG rng ;
456+ byte out [CURVE25519_KEYSIZE ];
457+ word32 outLen ;
458+ int i ;
459+
460+ vec [0 ].pub = kPub1 ; vec [0 ].expected = kExpected1 ;
461+ vec [1 ].pub = kPub2 ; vec [1 ].expected = kExpected2 ;
462+
463+ XMEMSET (& rng , 0 , sizeof (WC_RNG ));
464+ ExpectIntEQ (wc_InitRng (& rng ), 0 );
465+
466+ for (i = 0 ; i < 2 ; i ++ ) {
467+ XMEMSET (& private_key , 0 , sizeof (private_key ));
468+ XMEMSET (& public_key , 0 , sizeof (public_key ));
469+ ExpectIntEQ (wc_curve25519_init (& private_key ), 0 );
470+ ExpectIntEQ (wc_curve25519_init (& public_key ), 0 );
471+ #ifdef WOLFSSL_CURVE25519_BLINDING
472+ ExpectIntEQ (wc_curve25519_set_rng (& private_key , & rng ), 0 );
473+ #endif
474+ ExpectIntEQ (wc_curve25519_import_private_ex (kPriv , sizeof (kPriv ),
475+ & private_key , EC25519_LITTLE_ENDIAN ), 0 );
476+ ExpectIntEQ (wc_curve25519_import_public_ex (vec [i ].pub ,
477+ CURVE25519_KEYSIZE , & public_key , EC25519_LITTLE_ENDIAN ), 0 );
478+
479+ outLen = sizeof (out );
480+ ExpectIntEQ (wc_curve25519_shared_secret_ex (& private_key , & public_key ,
481+ out , & outLen , EC25519_LITTLE_ENDIAN ), 0 );
482+ ExpectIntEQ (outLen , CURVE25519_KEYSIZE );
483+ ExpectIntEQ (XMEMCMP (out , vec [i ].expected , CURVE25519_KEYSIZE ), 0 );
484+
485+ wc_curve25519_free (& private_key );
486+ wc_curve25519_free (& public_key );
487+ }
488+
489+ DoExpectIntEQ (wc_FreeRng (& rng ), 0 );
490+ #endif
491+ return EXPECT_RESULT ();
492+ } /* END test_wc_curve25519_shared_secret_ex_kat */
493+
401494/*
402495 * Testing wc_curve25519_make_pub
403496 */
0 commit comments