@@ -576,6 +576,227 @@ static int whTest_SheClientConfigBoundarySecureBoot(whClientConfig* config)
576576}
577577#endif /* WOLFHSM_CFG_TEST_POSIX && WOLFHSM_CFG_ENABLE_CLIENT && \
578578 WOLFHSM_CFG_ENABLE_SERVER */
579+
580+ #if defined(WOLFHSM_CFG_TEST_POSIX ) && \
581+ defined(WOLFHSM_CFG_ENABLE_CLIENT ) && \
582+ defined(WOLFHSM_CFG_ENABLE_SERVER )
583+ /* Test that a key with WH_SHE_FLAG_WRITE_PROTECT cannot be overwritten
584+ * via SHE LoadKey, and that ERC_WRITE_PROTECTED is returned */
585+ static int whTest_SheWriteProtect (whClientConfig * config )
586+ {
587+ int ret = 0 ;
588+ WC_RNG rng [1 ];
589+ Cmac cmac [1 ];
590+ whClientContext client [1 ] = {0 };
591+ uint8_t sheUid [] = {0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
592+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
593+ 0x01 };
594+ uint8_t secretKey [] = {0x2b , 0x7e , 0x15 , 0x16 , 0x28 , 0xae , 0xd2 ,
595+ 0xa6 , 0xab , 0xf7 , 0x15 , 0x88 , 0x09 , 0xcf ,
596+ 0x4f , 0x3c };
597+ uint8_t rawKey [] = {0x0f , 0x0e , 0x0d , 0x0c , 0x0b , 0x0a , 0x09 ,
598+ 0x08 , 0x07 , 0x06 , 0x05 , 0x04 , 0x03 , 0x02 ,
599+ 0x01 , 0x00 };
600+ uint8_t zeros [WH_SHE_BOOT_MAC_PREFIX_LEN ] = {0 };
601+ uint8_t bootMacKey [WH_SHE_KEY_SZ ] = {0 };
602+ uint8_t bootloader [512 ];
603+ uint8_t bootMacDigest [WH_SHE_KEY_SZ ] = {0 };
604+ uint32_t digestSz = sizeof (bootMacDigest );
605+ uint32_t bootloaderSz = sizeof (bootloader );
606+ uint8_t messageOne [WH_SHE_M1_SZ ];
607+ uint8_t messageTwo [WH_SHE_M2_SZ ];
608+ uint8_t messageThree [WH_SHE_M3_SZ ];
609+ uint8_t messageFour [WH_SHE_M4_SZ ];
610+ uint8_t messageFive [WH_SHE_M5_SZ ];
611+ uint32_t outClientId = 0 ;
612+ uint32_t outServerId = 0 ;
613+ const uint32_t WP_TEST_KEY_ID = 4 ;
614+
615+ if (config == NULL ) {
616+ return WH_ERROR_BADARGS ;
617+ }
618+
619+ WH_TEST_RETURN_ON_FAIL (
620+ wh_Client_Init (client , config ));
621+ WH_TEST_RETURN_ON_FAIL (
622+ wh_Client_CommInit (client , & outClientId , & outServerId ));
623+
624+ /* generate boot MAC key and fake bootloader */
625+ if ((ret = wc_InitRng_ex (rng , NULL , WH_DEV_ID )) != 0 ) {
626+ WH_ERROR_PRINT (
627+ "Failed to wc_InitRng_ex %d\n" , ret );
628+ goto exit_wp ;
629+ }
630+ if ((ret = wc_RNG_GenerateBlock (
631+ rng , bootMacKey , sizeof (bootMacKey ))) != 0 ) {
632+ WH_ERROR_PRINT (
633+ "Failed to wc_RNG_GenerateBlock %d\n" , ret );
634+ wc_FreeRng (rng );
635+ goto exit_wp ;
636+ }
637+ if ((ret = wc_RNG_GenerateBlock (
638+ rng , bootloader , sizeof (bootloader ))) != 0 ) {
639+ WH_ERROR_PRINT (
640+ "Failed to wc_RNG_GenerateBlock %d\n" , ret );
641+ wc_FreeRng (rng );
642+ goto exit_wp ;
643+ }
644+ wc_FreeRng (rng );
645+
646+ /* compute boot MAC digest: CMAC(0..0 | size | bootloader) */
647+ if ((ret = wc_InitCmac (cmac , bootMacKey ,
648+ sizeof (bootMacKey ), WC_CMAC_AES , NULL )) != 0 ) {
649+ WH_ERROR_PRINT (
650+ "Failed to wc_InitCmac %d\n" , ret );
651+ goto exit_wp ;
652+ }
653+ if ((ret = wc_CmacUpdate (
654+ cmac , zeros , sizeof (zeros ))) != 0 ) {
655+ WH_ERROR_PRINT (
656+ "Failed to wc_CmacUpdate %d\n" , ret );
657+ goto exit_wp ;
658+ }
659+ if ((ret = wc_CmacUpdate (cmac ,
660+ (uint8_t * )& bootloaderSz ,
661+ sizeof (bootloaderSz ))) != 0 ) {
662+ WH_ERROR_PRINT (
663+ "Failed to wc_CmacUpdate %d\n" , ret );
664+ goto exit_wp ;
665+ }
666+ if ((ret = wc_CmacUpdate (
667+ cmac , bootloader , sizeof (bootloader ))) != 0 ) {
668+ WH_ERROR_PRINT (
669+ "Failed to wc_CmacUpdate %d\n" , ret );
670+ goto exit_wp ;
671+ }
672+ digestSz = AES_BLOCK_SIZE ;
673+ if ((ret = wc_CmacFinal (cmac , bootMacDigest ,
674+ (word32 * )& digestSz )) != 0 ) {
675+ WH_ERROR_PRINT (
676+ "Failed to wc_CmacFinal %d\n" , ret );
677+ goto exit_wp ;
678+ }
679+
680+ /* pre-program boot MAC key and digest for secure boot */
681+ if ((ret = wh_Client_ShePreProgramKey (
682+ client , WH_SHE_BOOT_MAC_KEY_ID , 0 ,
683+ bootMacKey , sizeof (bootMacKey ))) != 0 ) {
684+ WH_ERROR_PRINT (
685+ "Failed to pre-program boot MAC key %d\n" , ret );
686+ goto exit_wp ;
687+ }
688+ if ((ret = wh_Client_ShePreProgramKey (
689+ client , WH_SHE_BOOT_MAC , 0 ,
690+ bootMacDigest , sizeof (bootMacDigest ))) != 0 ) {
691+ WH_ERROR_PRINT (
692+ "Failed to pre-program boot MAC digest %d\n" ,
693+ ret );
694+ goto exit_wp ;
695+ }
696+
697+ /* set the SHE UID */
698+ if ((ret = wh_Client_SheSetUid (
699+ client , sheUid , sizeof (sheUid ))) != 0 ) {
700+ WH_ERROR_PRINT (
701+ "Failed to wh_Client_SheSetUid %d\n" , ret );
702+ goto exit_wp ;
703+ }
704+
705+ /* secure boot must succeed before SHE LoadKey is allowed */
706+ if ((ret = wh_Client_SheSecureBoot (
707+ client , bootloader , bootloaderSz )) != 0 ) {
708+ WH_ERROR_PRINT (
709+ "Failed to wh_Client_SheSecureBoot %d\n" , ret );
710+ goto exit_wp ;
711+ }
712+
713+ /* pre-program the secret key as auth key */
714+ if ((ret = wh_Client_ShePreProgramKey (
715+ client , WH_SHE_SECRET_KEY_ID , 0 ,
716+ secretKey , sizeof (secretKey ))) != 0 ) {
717+ WH_ERROR_PRINT (
718+ "Failed to pre-program secret key %d\n" , ret );
719+ goto exit_wp ;
720+ }
721+
722+ /* pre-program the target key WITH write protect flag */
723+ if ((ret = wh_Client_ShePreProgramKey (
724+ client , WP_TEST_KEY_ID ,
725+ WH_SHE_FLAG_WRITE_PROTECT ,
726+ rawKey , sizeof (rawKey ))) != 0 ) {
727+ WH_ERROR_PRINT (
728+ "Failed to pre-program write-protected key %d\n" ,
729+ ret );
730+ goto exit_wp ;
731+ }
732+
733+ /* generate loadable key messages for the protected slot */
734+ if ((ret = wh_She_GenerateLoadableKey (
735+ WP_TEST_KEY_ID , WH_SHE_SECRET_KEY_ID ,
736+ 1 , 0 , sheUid , rawKey , secretKey ,
737+ messageOne , messageTwo , messageThree ,
738+ messageFour , messageFive )) != 0 ) {
739+ WH_ERROR_PRINT (
740+ "Failed to generate loadable key %d\n" , ret );
741+ goto exit_wp ;
742+ }
743+
744+ /* attempt to load key into the write-protected slot */
745+ ret = wh_Client_SheLoadKey (client , messageOne , messageTwo ,
746+ messageThree , messageFour ,
747+ messageFive );
748+ if (ret != WH_SHE_ERC_WRITE_PROTECTED ) {
749+ WH_ERROR_PRINT (
750+ "Expected WH_SHE_ERC_WRITE_PROTECTED, got %d\n" ,
751+ ret );
752+ ret = WH_ERROR_ABORTED ;
753+ goto exit_wp ;
754+ }
755+
756+ /* load succeeded (returned the expected error) */
757+ ret = 0 ;
758+ WH_TEST_PRINT ("SHE write protect test SUCCESS\n" );
759+
760+ /* destroy test keys to prevent NVM leaks */
761+ if ((ret = _destroySheKey (
762+ client , WH_SHE_BOOT_MAC_KEY_ID )) != 0 ) {
763+ WH_ERROR_PRINT (
764+ "Failed to _destroySheKey, ret=%d\n" , ret );
765+ goto exit_wp ;
766+ }
767+ if ((ret = _destroySheKey (
768+ client , WH_SHE_BOOT_MAC )) != 0 ) {
769+ WH_ERROR_PRINT (
770+ "Failed to _destroySheKey, ret=%d\n" , ret );
771+ goto exit_wp ;
772+ }
773+ if ((ret = _destroySheKey (
774+ client , WH_SHE_SECRET_KEY_ID )) != 0 ) {
775+ WH_ERROR_PRINT (
776+ "Failed to _destroySheKey, ret=%d\n" , ret );
777+ goto exit_wp ;
778+ }
779+ if ((ret = _destroySheKey (client , WP_TEST_KEY_ID )) != 0 ) {
780+ WH_ERROR_PRINT (
781+ "Failed to _destroySheKey, ret=%d\n" , ret );
782+ goto exit_wp ;
783+ }
784+
785+ exit_wp :
786+ WH_TEST_RETURN_ON_FAIL (wh_Client_CommClose (client ));
787+
788+ if (ret == 0 ) {
789+ WH_TEST_RETURN_ON_FAIL (wh_Client_Cleanup (client ));
790+ }
791+ else {
792+ wh_Client_Cleanup (client );
793+ }
794+
795+ return ret ;
796+ }
797+ #endif /* WOLFHSM_CFG_TEST_POSIX && WOLFHSM_CFG_ENABLE_CLIENT && \
798+ WOLFHSM_CFG_ENABLE_SERVER */
799+
579800#endif /* WOLFHSM_CFG_ENABLE_CLIENT */
580801
581802#ifdef WOLFHSM_CFG_ENABLE_SERVER
@@ -1341,6 +1562,9 @@ int whTest_She(void)
13411562 WH_TEST_PRINT ("Testing SHE: (pthread) mem boundary secure boot...\n" );
13421563 WH_TEST_RETURN_ON_FAIL (wh_ClientServer_MemThreadTest (
13431564 whTest_SheClientConfigBoundarySecureBoot ));
1565+ WH_TEST_PRINT ("Testing SHE: (pthread) mem write protect...\n" );
1566+ WH_TEST_RETURN_ON_FAIL (
1567+ wh_ClientServer_MemThreadTest (whTest_SheWriteProtect ));
13441568 return 0 ;
13451569}
13461570#endif
0 commit comments