@@ -310,17 +310,24 @@ static int whTest_CryptoRsa(whClientContext* ctx, int devId, WC_RNG* rng)
310310#ifdef HAVE_ECC
311311static int whTest_CryptoEcc (whClientContext * ctx , int devId , WC_RNG * rng )
312312{
313- (void )ctx ;
314-
315313 int ret = WH_ERROR_OK ;
316314 ecc_key eccPrivate [1 ];
317315 ecc_key eccPublic [1 ];
318316#define TEST_ECC_KEYSIZE 32
317+ #define TEST_ECC_CURVE_ID ECC_SECP256R1
319318 uint8_t shared_ab [TEST_ECC_KEYSIZE ] = {0 };
320319 uint8_t shared_ba [TEST_ECC_KEYSIZE ] = {0 };
321320 uint8_t hash [TEST_ECC_KEYSIZE ] = {0 };
322321 uint8_t sig [ECC_MAX_SIG_SIZE ] = {0 };
323-
322+ whKeyId keyIdPrivate = WH_KEYID_ERASED ;
323+ whKeyId keyIdPublic = WH_KEYID_ERASED ;
324+ whKeyId checkKeyId = WH_KEYID_ERASED ;
325+ whNvmFlags flags = WH_NVM_FLAGS_USAGE_SIGN | WH_NVM_FLAGS_USAGE_VERIFY |
326+ WH_NVM_FLAGS_USAGE_DERIVE ;
327+ uint8_t labelPrivate [WH_NVM_LABEL_LEN ] = "ECC Private Key" ;
328+ uint8_t labelPublic [WH_NVM_LABEL_LEN ] = "ECC Public Key" ;
329+
330+ /* Test Case 1: Using ephemeral key (normal wolfCrypt flow) */
324331 ret = wc_ecc_init_ex (eccPrivate , NULL , devId );
325332 if (ret != 0 ) {
326333 WH_ERROR_PRINT ("Failed to wc_ecc_init_ex %d\n" , ret );
@@ -350,15 +357,16 @@ static int whTest_CryptoEcc(whClientContext* ctx, int devId, WC_RNG* rng)
350357 ret );
351358 } else {
352359 if (memcmp (shared_ab , shared_ba , secLen ) == 0 ) {
353- WH_TEST_PRINT ("ECDH SUCCESS\n" );
360+ WH_TEST_PRINT ("ECC ephemeral ECDH SUCCESS\n" );
354361 }
355362 else {
356- WH_ERROR_PRINT ("ECDH FAILED TO MATCH\n" );
363+ WH_ERROR_PRINT ("ECC ephemeral ECDH FAILED TO MATCH\n" );
364+ ret = -1 ;
357365 }
358366 }
359367 }
360368 if (ret == 0 ) {
361- /*Use the shared secret as a random hash */
369+ /* Use the shared secret as a random hash */
362370 memcpy (hash , shared_ba , sizeof (hash ));
363371 word32 sigLen = sizeof (sig );
364372 ret = wc_ecc_sign_hash ((void * )hash , sizeof (hash ),
@@ -379,10 +387,10 @@ static int whTest_CryptoEcc(whClientContext* ctx, int devId, WC_RNG* rng)
379387 }
380388 else {
381389 if (res == 1 ) {
382- WH_TEST_PRINT ("ECC SIGN/VERIFY SUCCESS\n" );
390+ WH_TEST_PRINT ("ECC ephemeral SIGN/VERIFY SUCCESS\n" );
383391 }
384392 else {
385- WH_ERROR_PRINT ("ECC SIGN/VERIFY FAIL\n" );
393+ WH_ERROR_PRINT ("ECC ephemeral SIGN/VERIFY FAIL\n" );
386394 ret = -1 ;
387395 }
388396 }
@@ -394,6 +402,229 @@ static int whTest_CryptoEcc(whClientContext* ctx, int devId, WC_RNG* rng)
394402 }
395403 wc_ecc_free (eccPrivate );
396404 }
405+
406+ /* Test Case 2: Using client export key */
407+ if (ret == 0 ) {
408+ memset (shared_ab , 0 , sizeof (shared_ab ));
409+ memset (shared_ba , 0 , sizeof (shared_ba ));
410+ memset (sig , 0 , sizeof (sig ));
411+
412+ ret = wc_ecc_init_ex (eccPrivate , NULL , WH_DEV_ID );
413+ if (ret != 0 ) {
414+ WH_ERROR_PRINT ("Failed to wc_ecc_init_ex for export key %d\n" , ret );
415+ } else {
416+ ret = wc_ecc_init_ex (eccPublic , NULL , WH_DEV_ID );
417+ if (ret != 0 ) {
418+ WH_ERROR_PRINT ("Failed to wc_ecc_init_ex for export key %d\n" , ret );
419+ } else {
420+ /* Server creates keys and exports them to client */
421+ ret = wh_Client_EccMakeExportKey (ctx , TEST_ECC_KEYSIZE ,
422+ TEST_ECC_CURVE_ID , eccPrivate );
423+ if (ret != 0 ) {
424+ WH_ERROR_PRINT ("Failed to wh_Client_EccMakeExportKey %d\n" , ret );
425+ }
426+ if (ret == 0 ) {
427+ ret = wh_Client_EccMakeExportKey (ctx , TEST_ECC_KEYSIZE ,
428+ TEST_ECC_CURVE_ID , eccPublic );
429+ if (ret != 0 ) {
430+ WH_ERROR_PRINT ("Failed to wh_Client_EccMakeExportKey %d\n" , ret );
431+ }
432+ }
433+ /* Test ECDH with exported keys */
434+ if (ret == 0 ) {
435+ word32 secLen = TEST_ECC_KEYSIZE ;
436+ ret = wc_ecc_shared_secret (eccPrivate , eccPublic ,
437+ (byte * )shared_ab , & secLen );
438+ if (ret != 0 ) {
439+ WH_ERROR_PRINT ("Failed to compute export key secret %d\n" , ret );
440+ }
441+ }
442+ if (ret == 0 ) {
443+ word32 secLen = TEST_ECC_KEYSIZE ;
444+ ret = wc_ecc_shared_secret (eccPublic , eccPrivate ,
445+ (byte * )shared_ba , & secLen );
446+ if (ret != 0 ) {
447+ WH_ERROR_PRINT ("Failed to compute export key secret %d\n" , ret );
448+ }
449+ }
450+ if (ret == 0 ) {
451+ if (memcmp (shared_ab , shared_ba , TEST_ECC_KEYSIZE ) != 0 ) {
452+ WH_ERROR_PRINT ("ECC export key ECDH FAILED TO MATCH\n" );
453+ ret = -1 ;
454+ } else {
455+ WH_TEST_PRINT ("ECC export key ECDH SUCCESS\n" );
456+ }
457+ }
458+ /* Test ECDSA sign/verify with exported keys */
459+ if (ret == 0 ) {
460+ memcpy (hash , shared_ba , sizeof (hash ));
461+ word32 sigLen = sizeof (sig );
462+ ret = wc_ecc_sign_hash ((void * )hash , sizeof (hash ),
463+ (void * )sig , & sigLen , rng ,
464+ eccPrivate );
465+ if (ret != 0 ) {
466+ WH_ERROR_PRINT ("Failed to sign with export key %d\n" , ret );
467+ } else {
468+ int res = 0 ;
469+ ret = wc_ecc_verify_hash ((void * )sig , sigLen ,
470+ (void * )hash , sizeof (hash ),
471+ & res , eccPrivate );
472+ if (ret != 0 ) {
473+ WH_ERROR_PRINT ("Failed to verify with export key %d\n" , ret );
474+ } else if (res != 1 ) {
475+ WH_ERROR_PRINT ("ECC export key SIGN/VERIFY FAIL\n" );
476+ ret = -1 ;
477+ } else {
478+ WH_TEST_PRINT ("ECC export key SIGN/VERIFY SUCCESS\n" );
479+ }
480+ }
481+ }
482+ wc_ecc_free (eccPublic );
483+ }
484+ wc_ecc_free (eccPrivate );
485+ }
486+ }
487+
488+ /* Test Case 3: Using keyCache key (key stays on server) */
489+ if (ret == 0 ) {
490+ memset (shared_ab , 0 , sizeof (shared_ab ));
491+ memset (shared_ba , 0 , sizeof (shared_ba ));
492+ memset (sig , 0 , sizeof (sig ));
493+ keyIdPrivate = WH_KEYID_ERASED ;
494+ keyIdPublic = WH_KEYID_ERASED ;
495+
496+ /* Server creates and caches keys */
497+ ret = wh_Client_EccMakeCacheKey (ctx , TEST_ECC_KEYSIZE , TEST_ECC_CURVE_ID ,
498+ & keyIdPrivate , flags , sizeof (labelPrivate ), labelPrivate );
499+ if (ret != 0 ) {
500+ WH_ERROR_PRINT ("Failed to wh_Client_EccMakeCacheKey %d\n" , ret );
501+ }
502+ if (ret == 0 ) {
503+ ret = wh_Client_EccMakeCacheKey (ctx , TEST_ECC_KEYSIZE , TEST_ECC_CURVE_ID ,
504+ & keyIdPublic , flags , sizeof (labelPublic ), labelPublic );
505+ if (ret != 0 ) {
506+ WH_ERROR_PRINT ("Failed to wh_Client_EccMakeCacheKey %d\n" , ret );
507+ }
508+ }
509+ if (ret == 0 ) {
510+ ret = wc_ecc_init_ex (eccPrivate , NULL , WH_DEV_ID );
511+ if (ret != 0 ) {
512+ WH_ERROR_PRINT ("Failed to wc_ecc_init_ex for cache key %d\n" , ret );
513+ }
514+ }
515+ if (ret == 0 ) {
516+ ret = wc_ecc_init_ex (eccPublic , NULL , WH_DEV_ID );
517+ if (ret != 0 ) {
518+ WH_ERROR_PRINT ("Failed to wc_ecc_init_ex for cache key %d\n" , ret );
519+ wc_ecc_free (eccPrivate );
520+ }
521+ }
522+ if (ret == 0 ) {
523+ /* Associate server key IDs with local key structs */
524+ ret = wh_Client_EccSetKeyId (eccPrivate , keyIdPrivate );
525+ if (ret != 0 ) {
526+ WH_ERROR_PRINT ("Failed to wh_Client_EccSetKeyId %d\n" , ret );
527+ }
528+ }
529+ if (ret == 0 ) {
530+ ret = wh_Client_EccSetKeyId (eccPublic , keyIdPublic );
531+ if (ret != 0 ) {
532+ WH_ERROR_PRINT ("Failed to wh_Client_EccSetKeyId %d\n" , ret );
533+ }
534+ }
535+ /* Verify key IDs were set correctly */
536+ if (ret == 0 ) {
537+ ret = wh_Client_EccGetKeyId (eccPrivate , & checkKeyId );
538+ if (ret != 0 ) {
539+ WH_ERROR_PRINT ("Failed to wh_Client_EccGetKeyId %d\n" , ret );
540+ } else if (checkKeyId != keyIdPrivate ) {
541+ WH_ERROR_PRINT ("ECC key ID mismatch: got %u, expected %u\n" ,
542+ checkKeyId , keyIdPrivate );
543+ ret = -1 ;
544+ }
545+ }
546+ if (ret == 0 ) {
547+ ret = wh_Client_EccGetKeyId (eccPublic , & checkKeyId );
548+ if (ret != 0 ) {
549+ WH_ERROR_PRINT ("Failed to wh_Client_EccGetKeyId %d\n" , ret );
550+ } else if (checkKeyId != keyIdPublic ) {
551+ WH_ERROR_PRINT ("ECC key ID mismatch: got %u, expected %u\n" ,
552+ checkKeyId , keyIdPublic );
553+ ret = -1 ;
554+ }
555+ }
556+ /* Set curve parameters (required since key data isn't exported) */
557+ if (ret == 0 ) {
558+ ret = wc_ecc_set_curve (eccPrivate , TEST_ECC_KEYSIZE , TEST_ECC_CURVE_ID );
559+ if (ret != 0 ) {
560+ WH_ERROR_PRINT ("Failed to wc_ecc_set_curve %d\n" , ret );
561+ }
562+ }
563+ if (ret == 0 ) {
564+ ret = wc_ecc_set_curve (eccPublic , TEST_ECC_KEYSIZE , TEST_ECC_CURVE_ID );
565+ if (ret != 0 ) {
566+ WH_ERROR_PRINT ("Failed to wc_ecc_set_curve %d\n" , ret );
567+ }
568+ }
569+ /* Test ECDH with cached keys */
570+ if (ret == 0 ) {
571+ word32 secLen = TEST_ECC_KEYSIZE ;
572+ ret = wc_ecc_shared_secret (eccPrivate , eccPublic ,
573+ (byte * )shared_ab , & secLen );
574+ if (ret != 0 ) {
575+ WH_ERROR_PRINT ("Failed to compute cache key secret %d\n" , ret );
576+ }
577+ }
578+ if (ret == 0 ) {
579+ word32 secLen = TEST_ECC_KEYSIZE ;
580+ ret = wc_ecc_shared_secret (eccPublic , eccPrivate ,
581+ (byte * )shared_ba , & secLen );
582+ if (ret != 0 ) {
583+ WH_ERROR_PRINT ("Failed to compute cache key secret %d\n" , ret );
584+ }
585+ }
586+ if (ret == 0 ) {
587+ if (memcmp (shared_ab , shared_ba , TEST_ECC_KEYSIZE ) != 0 ) {
588+ WH_ERROR_PRINT ("ECC cache key ECDH FAILED TO MATCH\n" );
589+ ret = -1 ;
590+ } else {
591+ WH_TEST_PRINT ("ECC cache key ECDH SUCCESS\n" );
592+ }
593+ }
594+ /* Test ECDSA sign/verify with cached keys */
595+ if (ret == 0 ) {
596+ memcpy (hash , shared_ba , sizeof (hash ));
597+ word32 sigLen = sizeof (sig );
598+ ret = wc_ecc_sign_hash ((void * )hash , sizeof (hash ),
599+ (void * )sig , & sigLen , rng ,
600+ eccPrivate );
601+ if (ret != 0 ) {
602+ WH_ERROR_PRINT ("Failed to sign with cache key %d\n" , ret );
603+ } else {
604+ int res = 0 ;
605+ ret = wc_ecc_verify_hash ((void * )sig , sigLen ,
606+ (void * )hash , sizeof (hash ),
607+ & res , eccPrivate );
608+ if (ret != 0 ) {
609+ WH_ERROR_PRINT ("Failed to verify with cache key %d\n" , ret );
610+ } else if (res != 1 ) {
611+ WH_ERROR_PRINT ("ECC cache key SIGN/VERIFY FAIL\n" );
612+ ret = -1 ;
613+ } else {
614+ WH_TEST_PRINT ("ECC cache key SIGN/VERIFY SUCCESS\n" );
615+ }
616+ }
617+ }
618+ /* Cleanup */
619+ wc_ecc_free (eccPublic );
620+ wc_ecc_free (eccPrivate );
621+ (void )wh_Client_KeyEvict (ctx , keyIdPrivate );
622+ (void )wh_Client_KeyEvict (ctx , keyIdPublic );
623+ }
624+
625+ if (ret == 0 ) {
626+ WH_TEST_PRINT ("ECC SUCCESS\n" );
627+ }
397628 return ret ;
398629}
399630#endif /* HAVE_ECC */
0 commit comments