@@ -310,89 +310,331 @@ 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 ;
316- ecc_key eccPrivate [1 ];
317- ecc_key eccPublic [1 ];
314+ ecc_key bonnieKey [1 ];
315+ ecc_key clydeKey [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-
324- ret = wc_ecc_init_ex (eccPrivate , NULL , devId );
322+ whKeyId keyIdPrivate = WH_KEYID_ERASED ;
323+ whKeyId checkKeyId = WH_KEYID_ERASED ;
324+ whNvmFlags flags = WH_NVM_FLAGS_USAGE_SIGN | WH_NVM_FLAGS_USAGE_VERIFY |
325+ WH_NVM_FLAGS_USAGE_DERIVE ;
326+ uint8_t labelPrivate [WH_NVM_LABEL_LEN ] = "ECC Private Key" ;
327+
328+ /* Test Case 1: Using ephemeral key (normal wolfCrypt flow) */
329+ ret = wc_ecc_init_ex (bonnieKey , NULL , devId );
325330 if (ret != 0 ) {
326331 WH_ERROR_PRINT ("Failed to wc_ecc_init_ex %d\n" , ret );
327332 } else {
328- ret = wc_ecc_init_ex (eccPublic , NULL , devId );
333+ ret = wc_ecc_init_ex (clydeKey , NULL , devId );
329334 if (ret != 0 ) {
330335 WH_ERROR_PRINT ("Failed to wc_ecc_init_ex %d\n" , ret );
331336 } else {
332- ret = wc_ecc_make_key (rng , TEST_ECC_KEYSIZE , eccPrivate );
337+ ret = wc_ecc_make_key (rng , TEST_ECC_KEYSIZE , bonnieKey );
333338 if (ret != 0 ) {
334339 WH_ERROR_PRINT ("Failed to wc_ecc_make_key %d\n" , ret );
335340 } else {
336- ret = wc_ecc_make_key (rng , TEST_ECC_KEYSIZE , eccPublic );
341+ ret = wc_ecc_make_key (rng , TEST_ECC_KEYSIZE , clydeKey );
337342 if (ret != 0 ) {
338343 WH_ERROR_PRINT ("Failed to wc_ecc_make_key %d\n" , ret );
339344 } else {
340345 word32 secLen = TEST_ECC_KEYSIZE ;
341- ret = wc_ecc_shared_secret (eccPrivate , eccPublic ,
342- (byte * )shared_ab , & secLen );
346+ ret = wc_ecc_shared_secret (bonnieKey , clydeKey ,
347+ (byte * )shared_ab , & secLen );
343348 if (ret != 0 ) {
344349 WH_ERROR_PRINT ("Failed to compute secret %d\n" , ret );
345350 } else {
346- ret = wc_ecc_shared_secret (eccPublic , eccPrivate ,
347- (byte * )shared_ba , & secLen );
351+ ret = wc_ecc_shared_secret (clydeKey , bonnieKey ,
352+ (byte * )shared_ba , & secLen );
348353 if (ret != 0 ) {
349354 WH_ERROR_PRINT ("Failed to compute secret %d\n" ,
350355 ret );
351356 } else {
352357 if (memcmp (shared_ab , shared_ba , secLen ) == 0 ) {
353- WH_TEST_PRINT ("ECDH SUCCESS\n" );
358+ WH_TEST_PRINT ("ECC ephemeral ECDH SUCCESS\n" );
354359 }
355360 else {
356- WH_ERROR_PRINT ("ECDH FAILED TO MATCH\n" );
361+ WH_ERROR_PRINT (
362+ "ECC ephemeral ECDH FAILED TO MATCH\n" );
363+ ret = -1 ;
357364 }
358365 }
359366 }
360367 if (ret == 0 ) {
361- /*Use the shared secret as a random hash */
368+ /* Use the shared secret as a random hash */
362369 memcpy (hash , shared_ba , sizeof (hash ));
363370 word32 sigLen = sizeof (sig );
364371 ret = wc_ecc_sign_hash ((void * )hash , sizeof (hash ),
365372 (void * )sig , & sigLen , rng ,
366- eccPrivate );
373+ bonnieKey );
367374 if (ret != 0 ) {
368375 WH_ERROR_PRINT ("Failed to wc_ecc_sign_hash %d\n" ,
369376 ret );
370377 } else {
371378 int res = 0 ;
372379 ret = wc_ecc_verify_hash ((void * )sig , sigLen ,
373380 (void * )hash , sizeof (hash ),
374- & res , eccPrivate );
381+ & res , bonnieKey );
375382 if (ret != 0 ) {
376383 WH_ERROR_PRINT ("Failed to wc_ecc_verify_hash"
377384 " %d\n" ,
378385 ret );
379386 }
380387 else {
381388 if (res == 1 ) {
382- WH_TEST_PRINT ("ECC SIGN/VERIFY SUCCESS\n" );
389+ WH_TEST_PRINT (
390+ "ECC ephemeral SIGN/VERIFY SUCCESS\n" );
383391 }
384392 else {
385- WH_ERROR_PRINT ("ECC SIGN/VERIFY FAIL\n" );
393+ WH_ERROR_PRINT (
394+ "ECC ephemeral SIGN/VERIFY FAIL\n" );
386395 ret = -1 ;
387396 }
388397 }
389398 }
390399 }
391400 }
392401 }
393- wc_ecc_free (eccPublic );
402+ wc_ecc_free (clydeKey );
403+ }
404+ wc_ecc_free (bonnieKey );
405+ }
406+
407+ /* Test Case 2: Using client export key */
408+ if (ret == 0 ) {
409+ memset (shared_ab , 0 , sizeof (shared_ab ));
410+ memset (shared_ba , 0 , sizeof (shared_ba ));
411+ memset (sig , 0 , sizeof (sig ));
412+
413+ ret = wc_ecc_init_ex (bonnieKey , NULL , WH_DEV_ID );
414+ if (ret != 0 ) {
415+ WH_ERROR_PRINT ("Failed to wc_ecc_init_ex for export key %d\n" , ret );
416+ }
417+ else {
418+ ret = wc_ecc_init_ex (clydeKey , NULL , WH_DEV_ID );
419+ if (ret != 0 ) {
420+ WH_ERROR_PRINT ("Failed to wc_ecc_init_ex for export key %d\n" ,
421+ ret );
422+ }
423+ else {
424+ /* Server creates keys and exports them to client */
425+ ret = wh_Client_EccMakeExportKey (ctx , TEST_ECC_KEYSIZE ,
426+ TEST_ECC_CURVE_ID , bonnieKey );
427+ if (ret != 0 ) {
428+ WH_ERROR_PRINT ("Failed to wh_Client_EccMakeExportKey %d\n" ,
429+ ret );
430+ }
431+ if (ret == 0 ) {
432+ ret = wh_Client_EccMakeExportKey (
433+ ctx , TEST_ECC_KEYSIZE , TEST_ECC_CURVE_ID , clydeKey );
434+ if (ret != 0 ) {
435+ WH_ERROR_PRINT (
436+ "Failed to wh_Client_EccMakeExportKey %d\n" , ret );
437+ }
438+ }
439+ /* Test ECDH with exported keys */
440+ if (ret == 0 ) {
441+ word32 secLen = TEST_ECC_KEYSIZE ;
442+ ret = wc_ecc_shared_secret (bonnieKey , clydeKey ,
443+ (byte * )shared_ab , & secLen );
444+ if (ret != 0 ) {
445+ WH_ERROR_PRINT (
446+ "Failed to compute export key secret %d\n" , ret );
447+ }
448+ }
449+ if (ret == 0 ) {
450+ word32 secLen = TEST_ECC_KEYSIZE ;
451+ ret = wc_ecc_shared_secret (clydeKey , bonnieKey ,
452+ (byte * )shared_ba , & secLen );
453+ if (ret != 0 ) {
454+ WH_ERROR_PRINT (
455+ "Failed to compute export key secret %d\n" , ret );
456+ }
457+ }
458+ if (ret == 0 ) {
459+ if (memcmp (shared_ab , shared_ba , TEST_ECC_KEYSIZE ) != 0 ) {
460+ WH_ERROR_PRINT ("ECC export key ECDH FAILED TO MATCH\n" );
461+ ret = -1 ;
462+ }
463+ else {
464+ WH_TEST_PRINT ("ECC export key ECDH SUCCESS\n" );
465+ }
466+ }
467+ /* Test ECDSA sign/verify with exported keys */
468+ if (ret == 0 ) {
469+ memcpy (hash , shared_ba , sizeof (hash ));
470+ word32 sigLen = sizeof (sig );
471+ ret = wc_ecc_sign_hash ((void * )hash , sizeof (hash ),
472+ (void * )sig , & sigLen , rng , bonnieKey );
473+ if (ret != 0 ) {
474+ WH_ERROR_PRINT ("Failed to sign with export key %d\n" ,
475+ ret );
476+ }
477+ else {
478+ int res = 0 ;
479+ ret =
480+ wc_ecc_verify_hash ((void * )sig , sigLen , (void * )hash ,
481+ sizeof (hash ), & res , bonnieKey );
482+ if (ret != 0 ) {
483+ WH_ERROR_PRINT (
484+ "Failed to verify with export key %d\n" , ret );
485+ }
486+ else if (res != 1 ) {
487+ WH_ERROR_PRINT ("ECC export key SIGN/VERIFY FAIL\n" );
488+ ret = -1 ;
489+ }
490+ else {
491+ WH_TEST_PRINT (
492+ "ECC export key SIGN/VERIFY SUCCESS\n" );
493+ }
494+ }
495+ }
496+ wc_ecc_free (clydeKey );
497+ }
498+ wc_ecc_free (bonnieKey );
499+ }
500+ }
501+
502+ /* Test Case 3: Using keyCache key (key stays on server)
503+ * Use only ONE cached key to avoid key cache space issues.
504+ * For ECDH, use an ephemeral peer key. */
505+ if (ret == 0 ) {
506+ memset (shared_ab , 0 , sizeof (shared_ab ));
507+ memset (shared_ba , 0 , sizeof (shared_ba ));
508+ memset (sig , 0 , sizeof (sig ));
509+ keyIdPrivate = WH_KEYID_ERASED ;
510+
511+ /* Server creates and caches one key */
512+ ret = wh_Client_EccMakeCacheKey (ctx , TEST_ECC_KEYSIZE ,
513+ TEST_ECC_CURVE_ID , & keyIdPrivate , flags ,
514+ sizeof (labelPrivate ), labelPrivate );
515+ if (ret != 0 ) {
516+ WH_ERROR_PRINT ("Failed to wh_Client_EccMakeCacheKey %d\n" , ret );
517+ }
518+ if (ret == 0 ) {
519+ /* Init the cached key struct and associate with server key ID */
520+ ret = wc_ecc_init_ex (bonnieKey , NULL , WH_DEV_ID );
521+ if (ret != 0 ) {
522+ WH_ERROR_PRINT ("Failed to wc_ecc_init_ex for cache key %d\n" ,
523+ ret );
524+ }
525+ else {
526+ ret = wh_Client_EccSetKeyId (bonnieKey , keyIdPrivate );
527+ if (ret != 0 ) {
528+ WH_ERROR_PRINT ("Failed to wh_Client_EccSetKeyId %d\n" , ret );
529+ }
530+ /* Verify key ID was set correctly */
531+ if (ret == 0 ) {
532+ ret = wh_Client_EccGetKeyId (bonnieKey , & checkKeyId );
533+ if (ret != 0 ) {
534+ WH_ERROR_PRINT ("Failed to wh_Client_EccGetKeyId %d\n" ,
535+ ret );
536+ }
537+ else if (checkKeyId != keyIdPrivate ) {
538+ WH_ERROR_PRINT (
539+ "ECC key ID mismatch: got %u, expected %u\n" ,
540+ checkKeyId , keyIdPrivate );
541+ ret = -1 ;
542+ }
543+ }
544+ /* Set curve parameters (required since key data isn't exported)
545+ */
546+ if (ret == 0 ) {
547+ ret = wc_ecc_set_curve (bonnieKey , TEST_ECC_KEYSIZE ,
548+ TEST_ECC_CURVE_ID );
549+ if (ret != 0 ) {
550+ WH_ERROR_PRINT ("Failed to wc_ecc_set_curve %d\n" , ret );
551+ }
552+ }
553+ /* Create ephemeral peer key for ECDH test */
554+ if (ret == 0 ) {
555+ ret = wc_ecc_init_ex (clydeKey , NULL , WH_DEV_ID );
556+ if (ret != 0 ) {
557+ WH_ERROR_PRINT (
558+ "Failed to wc_ecc_init_ex for peer key %d\n" , ret );
559+ }
560+ else {
561+ ret = wc_ecc_make_key (rng , TEST_ECC_KEYSIZE , clydeKey );
562+ if (ret != 0 ) {
563+ WH_ERROR_PRINT (
564+ "Failed to wc_ecc_make_key for peer %d\n" , ret );
565+ }
566+ /* Test ECDH: cached key with ephemeral peer */
567+ if (ret == 0 ) {
568+ word32 secLen = TEST_ECC_KEYSIZE ;
569+ ret = wc_ecc_shared_secret (
570+ bonnieKey , clydeKey , (byte * )shared_ab , & secLen );
571+ if (ret != 0 ) {
572+ WH_ERROR_PRINT (
573+ "Failed to compute cache key secret %d\n" ,
574+ ret );
575+ }
576+ }
577+ if (ret == 0 ) {
578+ word32 secLen = TEST_ECC_KEYSIZE ;
579+ ret = wc_ecc_shared_secret (
580+ clydeKey , bonnieKey , (byte * )shared_ba , & secLen );
581+ if (ret != 0 ) {
582+ WH_ERROR_PRINT (
583+ "Failed to compute peer secret %d\n" , ret );
584+ }
585+ }
586+ if (ret == 0 ) {
587+ if (memcmp (shared_ab , shared_ba ,
588+ TEST_ECC_KEYSIZE ) != 0 ) {
589+ WH_ERROR_PRINT (
590+ "ECC cache key ECDH FAILED TO MATCH\n" );
591+ ret = -1 ;
592+ }
593+ else {
594+ WH_TEST_PRINT ("ECC cache key ECDH SUCCESS\n" );
595+ }
596+ }
597+ wc_ecc_free (clydeKey );
598+ }
599+ }
600+ /* Test ECDSA sign/verify with cached key */
601+ if (ret == 0 ) {
602+ memcpy (hash , shared_ba , sizeof (hash ));
603+ word32 sigLen = sizeof (sig );
604+ ret = wc_ecc_sign_hash ((void * )hash , sizeof (hash ),
605+ (void * )sig , & sigLen , rng , bonnieKey );
606+ if (ret != 0 ) {
607+ WH_ERROR_PRINT ("Failed to sign with cache key %d\n" ,
608+ ret );
609+ }
610+ else {
611+ int res = 0 ;
612+ ret =
613+ wc_ecc_verify_hash ((void * )sig , sigLen , (void * )hash ,
614+ sizeof (hash ), & res , bonnieKey );
615+ if (ret != 0 ) {
616+ WH_ERROR_PRINT (
617+ "Failed to verify with cache key %d\n" , ret );
618+ }
619+ else if (res != 1 ) {
620+ WH_ERROR_PRINT ("ECC cache key SIGN/VERIFY FAIL\n" );
621+ ret = -1 ;
622+ }
623+ else {
624+ WH_TEST_PRINT (
625+ "ECC cache key SIGN/VERIFY SUCCESS\n" );
626+ }
627+ }
628+ }
629+ wc_ecc_free (bonnieKey );
630+ }
394631 }
395- wc_ecc_free (eccPrivate );
632+ /* Evict server key regardless of test success */
633+ (void )wh_Client_KeyEvict (ctx , keyIdPrivate );
634+ }
635+
636+ if (ret == 0 ) {
637+ WH_TEST_PRINT ("ECC SUCCESS\n" );
396638 }
397639 return ret ;
398640}
0 commit comments