@@ -353,6 +353,99 @@ int test_wc_curve25519_shared_secret_ex(void)
353353 return EXPECT_RESULT ();
354354} /* END test_wc_curve25519_shared_secret_ex */
355355
356+ /*
357+ * Known-answer tests for wc_curve25519_shared_secret_ex.
358+ *
359+ * Both vectors share one private scalar and produce a shared secret that is a
360+ * small canonical value (9 and 16, little-endian). Because the result is close
361+ * to a multiple of the field prime, these exercise the final modular reduction
362+ * of the X25519 computation: a result that was only reduced mod 2^256 (or left
363+ * in [p, 2^255)) instead of fully reduced mod 2^255-19 would not match.
364+ * All values are 32-byte little-endian encodings per RFC 7748.
365+ */
366+ int test_wc_curve25519_shared_secret_ex_kat (void )
367+ {
368+ EXPECT_DECLS ;
369+ #if defined(HAVE_CURVE25519 ) && defined(HAVE_CURVE25519_KEY_IMPORT )
370+ /* Private scalar shared by both vectors. */
371+ static const byte kPriv [CURVE25519_KEYSIZE ] = {
372+ 0x60 , 0xa3 , 0xa4 , 0xf1 , 0x30 , 0xb9 , 0x8a , 0x5b ,
373+ 0xe4 , 0xb1 , 0xce , 0xdb , 0x7c , 0xb8 , 0x55 , 0x84 ,
374+ 0xa3 , 0x52 , 0x0e , 0x14 , 0x2d , 0x47 , 0x4d , 0xc9 ,
375+ 0xcc , 0xb9 , 0x09 , 0xa0 , 0x73 , 0xa9 , 0x76 , 0x7f
376+ };
377+ /* Vector 1 public value, expected shared secret == 9. */
378+ static const byte kPub1 [CURVE25519_KEYSIZE ] = {
379+ 0x3b , 0x18 , 0xdf , 0x1e , 0x50 , 0xb8 , 0x99 , 0xeb ,
380+ 0xd5 , 0x88 , 0xc3 , 0x16 , 0x1c , 0xbd , 0x3b , 0xf9 ,
381+ 0x8e , 0xbc , 0xc2 , 0xc1 , 0xf7 , 0xdf , 0x53 , 0xb8 ,
382+ 0x11 , 0xbd , 0x0e , 0x91 , 0xb4 , 0xd5 , 0x15 , 0x3d
383+ };
384+ static const byte kExpected1 [CURVE25519_KEYSIZE ] = {
385+ 0x09 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
386+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
387+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
388+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
389+ };
390+ /* Vector 2 public value, expected shared secret == 16. */
391+ static const byte kPub2 [CURVE25519_KEYSIZE ] = {
392+ 0xca , 0xb6 , 0xf9 , 0xe7 , 0xd8 , 0xce , 0x00 , 0xdf ,
393+ 0xce , 0xa9 , 0xbb , 0xd8 , 0xf0 , 0x69 , 0xef , 0x7f ,
394+ 0xb2 , 0xac , 0x50 , 0x4a , 0xbf , 0x83 , 0xb8 , 0x7d ,
395+ 0xb6 , 0x01 , 0xb5 , 0xae , 0x0a , 0x7f , 0x76 , 0x15
396+ };
397+ static const byte kExpected2 [CURVE25519_KEYSIZE ] = {
398+ 0x10 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
399+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
400+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
401+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
402+ };
403+ /* Table-driven so both vectors run through the identical code path. */
404+ struct {
405+ const byte * pub ;
406+ const byte * expected ;
407+ } vec [2 ];
408+ int i ;
409+ curve25519_key private_key ;
410+ curve25519_key public_key ;
411+ WC_RNG rng ;
412+ byte out [CURVE25519_KEYSIZE ];
413+ word32 outLen ;
414+
415+ vec [0 ].pub = kPub1 ; vec [0 ].expected = kExpected1 ;
416+ vec [1 ].pub = kPub2 ; vec [1 ].expected = kExpected2 ;
417+
418+ XMEMSET (& rng , 0 , sizeof (WC_RNG ));
419+ ExpectIntEQ (wc_InitRng (& rng ), 0 );
420+
421+ for (i = 0 ; i < 2 ; i ++ ) {
422+ XMEMSET (& private_key , 0 , sizeof (private_key ));
423+ XMEMSET (& public_key , 0 , sizeof (public_key ));
424+ ExpectIntEQ (wc_curve25519_init (& private_key ), 0 );
425+ ExpectIntEQ (wc_curve25519_init (& public_key ), 0 );
426+ #ifdef WOLFSSL_CURVE25519_BLINDING
427+ ExpectIntEQ (wc_curve25519_set_rng (& private_key , & rng ), 0 );
428+ #endif
429+ ExpectIntEQ (wc_curve25519_import_private_ex (kPriv , sizeof (kPriv ),
430+ & private_key , EC25519_LITTLE_ENDIAN ), 0 );
431+ ExpectIntEQ (wc_curve25519_import_public_ex (vec [i ].pub ,
432+ CURVE25519_KEYSIZE , & public_key , EC25519_LITTLE_ENDIAN ), 0 );
433+
434+ outLen = sizeof (out );
435+ ExpectIntEQ (wc_curve25519_shared_secret_ex (& private_key , & public_key ,
436+ out , & outLen , EC25519_LITTLE_ENDIAN ), 0 );
437+ ExpectIntEQ (outLen , CURVE25519_KEYSIZE );
438+ ExpectIntEQ (XMEMCMP (out , vec [i ].expected , CURVE25519_KEYSIZE ), 0 );
439+
440+ wc_curve25519_free (& private_key );
441+ wc_curve25519_free (& public_key );
442+ }
443+
444+ DoExpectIntEQ (wc_FreeRng (& rng ), 0 );
445+ #endif
446+ return EXPECT_RESULT ();
447+ } /* END test_wc_curve25519_shared_secret_ex_kat */
448+
356449/*
357450 * Testing wc_curve25519_make_pub
358451 */
0 commit comments