@@ -54,8 +54,14 @@ static int whTest_CertNonExportable(whClientContext* client);
5454#ifdef WOLFHSM_CFG_KEYWRAP
5555static int whTest_CertCacheVerify (whClientContext * client );
5656static int whTest_CertCacheReadTrusted (whClientContext * client );
57+ #if defined(WOLFHSM_CFG_CERTIFICATE_MANAGER_ACERT )
58+ static int whTest_CertCacheVerifyAcert (whClientContext * client );
59+ #endif
5760#if defined(WOLFHSM_CFG_DMA )
5861static int whTest_CertCacheVerifyDma (whClientContext * client );
62+ #if defined(WOLFHSM_CFG_CERTIFICATE_MANAGER_ACERT )
63+ static int whTest_CertCacheVerifyAcertDma (whClientContext * client );
64+ #endif
5965#endif
6066#endif
6167#endif
@@ -331,6 +337,12 @@ int whTest_CertClientAcert(whClientContext* client)
331337 wh_Client_CertEraseTrusted (client , rootCertB_id , & out_rc ));
332338 WH_TEST_ASSERT_RETURN (out_rc == WH_ERROR_OK );
333339
340+ #ifdef WOLFHSM_CFG_KEYWRAP
341+ /* Test cache-based ACERT verification (wrapped cert in cache instead of
342+ * NVM) */
343+ WH_TEST_RETURN_ON_FAIL (whTest_CertCacheVerifyAcert (client ));
344+ #endif
345+
334346 WH_TEST_PRINT (
335347 "Attribute certificate client test completed successfully\n" );
336348
@@ -523,6 +535,12 @@ int whTest_CertClientAcertDma_ClientServerTestInternal(whClientContext* client)
523535 wh_Client_CertEraseTrusted (client , rootCertB_id , & out_rc ));
524536 WH_TEST_ASSERT_RETURN (out_rc == WH_ERROR_OK );
525537
538+ #ifdef WOLFHSM_CFG_KEYWRAP
539+ /* Test DMA cache-based ACERT verification (wrapped cert in cache instead of
540+ * NVM) */
541+ WH_TEST_RETURN_ON_FAIL (whTest_CertCacheVerifyAcertDma (client ));
542+ #endif
543+
526544 WH_TEST_PRINT (
527545 "Attribute certificate client test completed successfully\n" );
528546
@@ -749,6 +767,188 @@ static int whTest_CertCacheReadTrusted(whClientContext* client)
749767 WH_TEST_PRINT ("Cache-based cert ReadTrusted test completed successfully\n" );
750768 return rc ;
751769}
770+
771+ #if defined(WOLFHSM_CFG_CERTIFICATE_MANAGER_ACERT )
772+ /* Test attribute certificate verification using a wrapped/cached root cert
773+ * instead of NVM. This validates the cache-aware path in the VERIFY_ACERT
774+ * handler. */
775+ static int whTest_CertCacheVerifyAcert (whClientContext * client )
776+ {
777+ int rc = WH_ERROR_OK ;
778+ int32_t out_rc = 0 ;
779+ whKeyId kekId = 13 ;
780+ uint8_t wrappedCert [2048 ];
781+ uint16_t wrappedCertSz = sizeof (wrappedCert );
782+ whKeyId cachedCertId = WH_KEYID_ERASED ;
783+
784+ /* AES-256 key for wrapping */
785+ uint8_t kek [] = {0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 ,
786+ 0x09 , 0x0a , 0x0b , 0x0c , 0x0d , 0x0e , 0x0f , 0x10 ,
787+ 0x11 , 0x12 , 0x13 , 0x14 , 0x15 , 0x16 , 0x17 , 0x18 ,
788+ 0x19 , 0x1a , 0x1b , 0x1c , 0x1d , 0x1e , 0x1f , 0x20 };
789+
790+ whNvmMetadata certMeta = {0 };
791+
792+ WH_TEST_PRINT ("Starting cache-based ACERT verification test...\n" );
793+
794+ /* Provision the wrapping key (KEK) on the server */
795+ WH_TEST_RETURN_ON_FAIL (wh_Client_KeyCache (
796+ client , WH_NVM_FLAGS_USAGE_WRAP , NULL , 0 , kek , sizeof (kek ), & kekId ));
797+
798+ /* Wrap the CA cert (ACERT issuer) for client-side storage */
799+ certMeta .id = WH_CLIENT_KEYID_MAKE_WRAPPED_META (client -> comm -> client_id , 8 );
800+ certMeta .flags = WH_NVM_FLAGS_USAGE_ANY ;
801+ certMeta .access = WH_NVM_ACCESS_ANY ;
802+ WH_TEST_RETURN_ON_FAIL (wh_Client_CertWrap (
803+ client , WC_CIPHER_AES_GCM , kekId , caCert_der , caCert_der_len , & certMeta ,
804+ wrappedCert , & wrappedCertSz ));
805+
806+ /* Unwrap and cache the CA cert on the server */
807+ WH_TEST_RETURN_ON_FAIL (wh_Client_CertUnwrapAndCache (
808+ client , WC_CIPHER_AES_GCM , kekId , wrappedCert , wrappedCertSz ,
809+ & cachedCertId ));
810+
811+ /* Verify attribute cert against the cached root cert */
812+ WH_TEST_PRINT ("Verifying ACERT against cached root...\n" );
813+ WH_TEST_RETURN_ON_FAIL (wh_Client_CertVerifyAcert (
814+ client , attrCert_der , attrCert_der_len ,
815+ WH_CLIENT_KEYID_MAKE_WRAPPED (cachedCertId ), & out_rc ));
816+ WH_TEST_ASSERT_RETURN (out_rc == WH_ERROR_OK );
817+
818+ /* Verify that a mismatched root fails */
819+ WH_TEST_PRINT (
820+ "Verifying ACERT against mismatched cached root (should fail)...\n" );
821+ /* Wrap ROOT_B_CERT as a different cached root */
822+ {
823+ uint8_t wrappedCertB [2048 ];
824+ uint16_t wrappedCertBSz = sizeof (wrappedCertB );
825+ whKeyId cachedCertBId = WH_KEYID_ERASED ;
826+ whNvmMetadata certMetaB = {0 };
827+ certMetaB .id =
828+ WH_CLIENT_KEYID_MAKE_WRAPPED_META (client -> comm -> client_id , 9 );
829+ certMetaB .flags = WH_NVM_FLAGS_USAGE_ANY ;
830+ certMetaB .access = WH_NVM_ACCESS_ANY ;
831+
832+ WH_TEST_RETURN_ON_FAIL (wh_Client_CertWrap (
833+ client , WC_CIPHER_AES_GCM , kekId , ROOT_B_CERT , ROOT_B_CERT_len ,
834+ & certMetaB , wrappedCertB , & wrappedCertBSz ));
835+
836+ WH_TEST_RETURN_ON_FAIL (wh_Client_CertUnwrapAndCache (
837+ client , WC_CIPHER_AES_GCM , kekId , wrappedCertB , wrappedCertBSz ,
838+ & cachedCertBId ));
839+
840+ WH_TEST_RETURN_ON_FAIL (wh_Client_CertVerifyAcert (
841+ client , attrCert_der , attrCert_der_len ,
842+ WH_CLIENT_KEYID_MAKE_WRAPPED (cachedCertBId ), & out_rc ));
843+
844+ WH_TEST_ASSERT_RETURN (out_rc == WH_ERROR_CERT_VERIFY );
845+
846+ WH_TEST_RETURN_ON_FAIL (wh_Client_KeyEvict (
847+ client , WH_CLIENT_KEYID_MAKE_WRAPPED (cachedCertBId )));
848+ }
849+
850+ /* Cleanup: evict cached cert and KEK */
851+ WH_TEST_RETURN_ON_FAIL (
852+ wh_Client_KeyEvict (client , WH_CLIENT_KEYID_MAKE_WRAPPED (cachedCertId )));
853+ WH_TEST_RETURN_ON_FAIL (wh_Client_KeyEvict (client , kekId ));
854+
855+ WH_TEST_PRINT (
856+ "Cache-based ACERT verification test completed successfully\n" );
857+ return rc ;
858+ }
859+
860+ #if defined(WOLFHSM_CFG_DMA )
861+ /* Test DMA attribute certificate verification using a wrapped/cached root cert
862+ * instead of NVM. This validates the cache-aware path in the VERIFY_ACERT_DMA
863+ * handler. */
864+ static int whTest_CertCacheVerifyAcertDma (whClientContext * client )
865+ {
866+ int rc = WH_ERROR_OK ;
867+ int32_t out_rc = 0 ;
868+ whKeyId kekId = 14 ;
869+ uint8_t wrappedCert [2048 ];
870+ uint16_t wrappedCertSz = sizeof (wrappedCert );
871+ whKeyId cachedCertId = WH_KEYID_ERASED ;
872+
873+ /* AES-256 key for wrapping */
874+ uint8_t kek [] = {0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 ,
875+ 0x09 , 0x0a , 0x0b , 0x0c , 0x0d , 0x0e , 0x0f , 0x10 ,
876+ 0x11 , 0x12 , 0x13 , 0x14 , 0x15 , 0x16 , 0x17 , 0x18 ,
877+ 0x19 , 0x1a , 0x1b , 0x1c , 0x1d , 0x1e , 0x1f , 0x20 };
878+
879+ whNvmMetadata certMeta = {0 };
880+
881+ WH_TEST_PRINT ("Starting DMA cache-based ACERT verification test...\n" );
882+
883+ /* Provision the wrapping key (KEK) on the server */
884+ WH_TEST_RETURN_ON_FAIL (wh_Client_KeyCache (
885+ client , WH_NVM_FLAGS_USAGE_WRAP , NULL , 0 , kek , sizeof (kek ), & kekId ));
886+
887+ /* Wrap the CA cert (ACERT issuer) for client-side storage */
888+ certMeta .id =
889+ WH_CLIENT_KEYID_MAKE_WRAPPED_META (client -> comm -> client_id , 10 );
890+ certMeta .flags = WH_NVM_FLAGS_USAGE_ANY ;
891+ certMeta .access = WH_NVM_ACCESS_ANY ;
892+ WH_TEST_RETURN_ON_FAIL (wh_Client_CertWrap (
893+ client , WC_CIPHER_AES_GCM , kekId , caCert_der , caCert_der_len , & certMeta ,
894+ wrappedCert , & wrappedCertSz ));
895+
896+ /* Unwrap and cache the CA cert on the server */
897+ WH_TEST_RETURN_ON_FAIL (wh_Client_CertUnwrapAndCache (
898+ client , WC_CIPHER_AES_GCM , kekId , wrappedCert , wrappedCertSz ,
899+ & cachedCertId ));
900+
901+ /* DMA Verify attribute cert against the cached root cert */
902+ WH_TEST_PRINT ("DMA verifying ACERT against cached root...\n" );
903+ WH_TEST_RETURN_ON_FAIL (wh_Client_CertVerifyAcertDma (
904+ client , attrCert_der , attrCert_der_len ,
905+ WH_CLIENT_KEYID_MAKE_WRAPPED (cachedCertId ), & out_rc ));
906+ WH_TEST_ASSERT_RETURN (out_rc == WH_ERROR_OK );
907+
908+ /* Verify that a mismatched root fails */
909+ WH_TEST_PRINT ("DMA verifying ACERT against mismatched cached root (should "
910+ "fail)...\n" );
911+ {
912+ uint8_t wrappedCertB [2048 ];
913+ uint16_t wrappedCertBSz = sizeof (wrappedCertB );
914+ whKeyId cachedCertBId = WH_KEYID_ERASED ;
915+ whNvmMetadata certMetaB = {0 };
916+ certMetaB .id =
917+ WH_CLIENT_KEYID_MAKE_WRAPPED_META (client -> comm -> client_id , 11 );
918+ certMetaB .flags = WH_NVM_FLAGS_USAGE_ANY ;
919+ certMetaB .access = WH_NVM_ACCESS_ANY ;
920+
921+ WH_TEST_RETURN_ON_FAIL (wh_Client_CertWrap (
922+ client , WC_CIPHER_AES_GCM , kekId , ROOT_B_CERT , ROOT_B_CERT_len ,
923+ & certMetaB , wrappedCertB , & wrappedCertBSz ));
924+
925+ WH_TEST_RETURN_ON_FAIL (wh_Client_CertUnwrapAndCache (
926+ client , WC_CIPHER_AES_GCM , kekId , wrappedCertB , wrappedCertBSz ,
927+ & cachedCertBId ));
928+
929+ WH_TEST_RETURN_ON_FAIL (wh_Client_CertVerifyAcertDma (
930+ client , attrCert_der , attrCert_der_len ,
931+ WH_CLIENT_KEYID_MAKE_WRAPPED (cachedCertBId ), & out_rc ));
932+
933+ WH_TEST_ASSERT_RETURN (out_rc == WH_ERROR_CERT_VERIFY );
934+
935+ WH_TEST_RETURN_ON_FAIL (wh_Client_KeyEvict (
936+ client , WH_CLIENT_KEYID_MAKE_WRAPPED (cachedCertBId )));
937+ }
938+
939+ /* Cleanup: evict cached cert and KEK */
940+ WH_TEST_RETURN_ON_FAIL (
941+ wh_Client_KeyEvict (client , WH_CLIENT_KEYID_MAKE_WRAPPED (cachedCertId )));
942+ WH_TEST_RETURN_ON_FAIL (wh_Client_KeyEvict (client , kekId ));
943+
944+ WH_TEST_PRINT (
945+ "DMA cache-based ACERT verification test completed successfully\n" );
946+ return rc ;
947+ }
948+ #endif /* WOLFHSM_CFG_DMA */
949+
950+ #endif /* WOLFHSM_CFG_CERTIFICATE_MANAGER_ACERT */
951+
752952#endif /* WOLFHSM_CFG_KEYWRAP */
753953
754954static int whTest_CertNonExportable (whClientContext * client )
0 commit comments