Skip to content

Commit 9766ec8

Browse files
committed
Review feedback:
- Add doc warning about KEK - Add ACERT tests - Fix cert size check
1 parent 5f5c1c6 commit 9766ec8

3 files changed

Lines changed: 206 additions & 2 deletions

File tree

docs/draft/wrapped-certs.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ wh_Client_KeyCache(client,
3535
kek, sizeof(kek), &kekId);
3636
```
3737
38+
> **Note:** This is an example only. In production, the KEK is normally
39+
> provisioned and protected by target-specific hardware and should never be
40+
> hardcoded.
41+
3842
The KEK is now sitting in the server's `localCache` (or `globalCache` if marked
3943
global), indexed by `kekId`.
4044

src/wh_client_cert.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -966,7 +966,7 @@ int wh_Client_CertWrapRequest(whClientContext* ctx,
966966
uint32_t certSz, whNvmMetadata* meta)
967967
{
968968
if ((ctx == NULL) || (cert == NULL) || (certSz == 0) || (meta == NULL) ||
969-
(certSz > UINT16_MAX)) {
969+
(certSz > WOLFHSM_CFG_MAX_CERT_SIZE)) {
970970
return WH_ERROR_BADARGS;
971971
}
972972

@@ -997,7 +997,7 @@ int wh_Client_CertWrap(whClientContext* ctx, enum wc_CipherType cipherType,
997997

998998
if ((ctx == NULL) || (cert == NULL) || (certSz == 0) || (meta == NULL) ||
999999
(wrappedOut == NULL) || (inout_wrappedSz == NULL) ||
1000-
(certSz > UINT16_MAX)) {
1000+
(certSz > WOLFHSM_CFG_MAX_CERT_SIZE)) {
10011001
return WH_ERROR_BADARGS;
10021002
}
10031003

test/wh_test_cert.c

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,14 @@ static int whTest_CertNonExportable(whClientContext* client);
5454
#ifdef WOLFHSM_CFG_KEYWRAP
5555
static int whTest_CertCacheVerify(whClientContext* client);
5656
static 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)
5861
static 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

754954
static int whTest_CertNonExportable(whClientContext* client)

0 commit comments

Comments
 (0)