Skip to content

Commit 784cf00

Browse files
committed
add key usage policy support to CMAC
1 parent 683a3eb commit 784cf00

File tree

2 files changed

+165
-6
lines changed

2 files changed

+165
-6
lines changed

src/wh_server_crypto.c

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2499,9 +2499,24 @@ static int _HandleCmac(whServerContext* ctx, uint16_t magic, uint16_t seq,
24992499
len = sizeof(ctx->crypto->algoCtx.cmac);
25002500
keyId = wh_KeyId_TranslateFromClient(
25012501
WH_KEYTYPE_CRYPTO, ctx->comm->client_id, req.keyId);
2502-
ret = wh_Server_KeystoreReadKey(
2503-
ctx, keyId, NULL, (uint8_t*)ctx->crypto->algoCtx.cmac,
2504-
(uint32_t*)&len);
2502+
2503+
/* Validate key usage policy - CMAC accepts sign or verify */
2504+
if (!WH_KEYID_ISERASED(keyId)) {
2505+
ret = wh_Server_KeystoreFindEnforceKeyUsage(
2506+
ctx, keyId, WH_NVM_FLAGS_USAGE_SIGN);
2507+
if (ret == WH_ERROR_USAGE) {
2508+
/* Sign not allowed, try verify */
2509+
ret = wh_Server_KeystoreFindEnforceKeyUsage(
2510+
ctx, keyId, WH_NVM_FLAGS_USAGE_VERIFY);
2511+
}
2512+
if (ret != WH_ERROR_OK) {
2513+
return ret;
2514+
}
2515+
}
2516+
2517+
ret = wh_Server_KeystoreReadKey(
2518+
ctx, keyId, meta, (uint8_t*)ctx->crypto->algoCtx.cmac,
2519+
(uint32_t*)&len);
25052520
if (ret == WH_ERROR_OK) {
25062521
/* if the key size is a multiple of aes, init the key and
25072522
* overwrite the existing key on exit */
@@ -2612,12 +2627,22 @@ static int _HandleCmac(whServerContext* ctx, uint16_t magic, uint16_t seq,
26122627
if (moveToBigCache == 1) {
26132628
ret = wh_Server_KeystoreEvictKey(ctx, keyId);
26142629
}
2615-
if (ret == 0) {
2630+
if (ret == WH_ERROR_OK) {
26162631
meta->id = keyId;
26172632
meta->len = sizeof(ctx->crypto->algoCtx.cmac);
2618-
ret = wh_Server_KeystoreCacheKey(
2633+
/* Nonzero key size means the client provided the key and
2634+
* wasn't able to provide flags, therefore we tag the key as
2635+
* useable for sign/verify operations. If the client instead
2636+
* wants to refer to the key by ID, meta->flags should
2637+
* already hold the flags set on the original AES key from
2638+
* the earlier read operation */
2639+
if (req.keySz != 0) {
2640+
meta->flags =
2641+
WH_NVM_FLAGS_USAGE_SIGN | WH_NVM_FLAGS_USAGE_VERIFY;
2642+
}
2643+
ret = wh_Server_KeystoreCacheKey(
26192644
ctx, meta, (uint8_t*)ctx->crypto->algoCtx.cmac);
2620-
if (ret == 0) {
2645+
if (ret == WH_ERROR_OK) {
26212646
res.keyId = wh_KeyId_TranslateToClient(keyId);
26222647
res.outSz = 0;
26232648
}
@@ -4692,6 +4717,22 @@ static int _HandleCmacDma(whServerContext* ctx, uint16_t magic, uint16_t seq,
46924717
keyId = wh_KeyId_TranslateFromClient(
46934718
WH_KEYTYPE_CRYPTO, ctx->comm->client_id,
46944719
clientKeyId);
4720+
4721+
/* Validate key usage policy - CMAC accepts sign or
4722+
* verify */
4723+
if (!WH_KEYID_ISERASED(keyId)) {
4724+
ret = wh_Server_KeystoreFindEnforceKeyUsage(
4725+
ctx, keyId, WH_NVM_FLAGS_USAGE_SIGN);
4726+
if (ret == WH_ERROR_USAGE) {
4727+
/* Sign not allowed, try verify */
4728+
ret = wh_Server_KeystoreFindEnforceKeyUsage(
4729+
ctx, keyId, WH_NVM_FLAGS_USAGE_VERIFY);
4730+
}
4731+
if (ret != WH_ERROR_OK) {
4732+
return ret;
4733+
}
4734+
}
4735+
46954736
keyLen = sizeof(tmpKey);
46964737

46974738
/* Load key from cache */
@@ -4756,6 +4797,22 @@ static int _HandleCmacDma(whServerContext* ctx, uint16_t magic, uint16_t seq,
47564797
/* Get key ID from CMAC context */
47574798
keyId = wh_KeyId_TranslateFromClient(
47584799
WH_KEYTYPE_CRYPTO, ctx->comm->client_id, nvmId);
4800+
4801+
/* Validate key usage policy - CMAC accepts sign or
4802+
* verify */
4803+
if (!WH_KEYID_ISERASED(keyId)) {
4804+
ret = wh_Server_KeystoreFindEnforceKeyUsage(
4805+
ctx, keyId, WH_NVM_FLAGS_USAGE_SIGN);
4806+
if (ret == WH_ERROR_USAGE) {
4807+
/* Sign not allowed, try verify */
4808+
ret = wh_Server_KeystoreFindEnforceKeyUsage(
4809+
ctx, keyId, WH_NVM_FLAGS_USAGE_VERIFY);
4810+
}
4811+
if (ret != WH_ERROR_OK) {
4812+
return ret;
4813+
}
4814+
}
4815+
47594816
keyLen = sizeof(tmpKey);
47604817

47614818
/* Load key from cache */

test/wh_test_crypto.c

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4029,6 +4029,108 @@ int whTest_CryptoKeyUsagePolicies(whClientContext* client, WC_RNG* rng)
40294029
return ret;
40304030
#endif /* HAVE_HKDF */
40314031

4032+
#if defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT)
4033+
/* CMAC Generate without SIGN flag */
4034+
printf(" Testing CMAC generate without SIGN flag...\n");
4035+
{
4036+
Cmac cmac;
4037+
whKeyId keyId = WH_KEYID_ERASED;
4038+
uint8_t message[64];
4039+
uint8_t tag[AES_BLOCK_SIZE];
4040+
word32 tagLen = sizeof(tag);
4041+
4042+
/* Generate random message */
4043+
ret = wc_RNG_GenerateBlock(rng, message, sizeof(message));
4044+
if (ret == 0) {
4045+
/* Cache AES key without SIGN flag */
4046+
ret = wh_Client_KeyCache(
4047+
client, WH_NVM_FLAGS_NONE, (uint8_t*)"cmac-no-sign",
4048+
strlen("cmac-no-sign"), key, AES_128_KEY_SIZE, &keyId);
4049+
}
4050+
4051+
if (ret == 0) {
4052+
/* Initialize CMAC with HSM device ID */
4053+
ret = wc_InitCmac_ex(&cmac, NULL, 0, WC_CMAC_AES, NULL, NULL,
4054+
WH_DEV_ID);
4055+
if (ret == 0) {
4056+
/* Associate cached key */
4057+
ret = wh_Client_CmacSetKeyId(&cmac, keyId);
4058+
if (ret == 0) {
4059+
/* Try to generate CMAC - should fail */
4060+
ret = wc_AesCmacGenerate_ex(&cmac, tag, &tagLen, message,
4061+
sizeof(message), NULL, 0, NULL,
4062+
WH_DEV_ID);
4063+
if (ret == WH_ERROR_USAGE) {
4064+
printf(" PASS: Correctly denied CMAC generate\n");
4065+
ret = 0; /* Test passed */
4066+
}
4067+
else {
4068+
WH_ERROR_PRINT(
4069+
" FAIL: Expected WH_ERROR_USAGE, got %d\n", ret);
4070+
ret = WH_ERROR_ABORTED;
4071+
}
4072+
}
4073+
wc_CmacFree(&cmac);
4074+
}
4075+
wh_Client_KeyEvict(client, keyId);
4076+
}
4077+
}
4078+
if (ret != 0)
4079+
return ret;
4080+
4081+
/* CMAC Verify without VERIFY flag */
4082+
printf(" Testing CMAC verify without VERIFY flag...\n");
4083+
{
4084+
Cmac cmac;
4085+
whKeyId keyId = WH_KEYID_ERASED;
4086+
uint8_t message[64];
4087+
uint8_t tag[AES_BLOCK_SIZE];
4088+
word32 tagLen = sizeof(tag);
4089+
4090+
/* Generate random message and tag */
4091+
ret = wc_RNG_GenerateBlock(rng, message, sizeof(message));
4092+
if (ret == 0) {
4093+
ret = wc_RNG_GenerateBlock(rng, tag, sizeof(tag));
4094+
}
4095+
4096+
if (ret == 0) {
4097+
/* Cache AES key without VERIFY flag */
4098+
ret = wh_Client_KeyCache(
4099+
client, WH_NVM_FLAGS_NONE, (uint8_t*)"cmac-no-verify",
4100+
strlen("cmac-no-verify"), key, AES_128_KEY_SIZE, &keyId);
4101+
}
4102+
4103+
if (ret == 0) {
4104+
/* Initialize CMAC with HSM device ID */
4105+
ret = wc_InitCmac_ex(&cmac, NULL, 0, WC_CMAC_AES, NULL, NULL,
4106+
WH_DEV_ID);
4107+
if (ret == 0) {
4108+
/* Associate cached key */
4109+
ret = wh_Client_CmacSetKeyId(&cmac, keyId);
4110+
if (ret == 0) {
4111+
/* Try to verify CMAC - should fail */
4112+
ret = wc_AesCmacVerify_ex(&cmac, tag, tagLen, message,
4113+
sizeof(message), NULL, 0, NULL,
4114+
WH_DEV_ID);
4115+
if (ret == WH_ERROR_USAGE) {
4116+
printf(" PASS: Correctly denied CMAC verify\n");
4117+
ret = 0; /* Test passed */
4118+
}
4119+
else {
4120+
WH_ERROR_PRINT(
4121+
" FAIL: Expected WH_ERROR_USAGE, got %d\n", ret);
4122+
ret = WH_ERROR_ABORTED;
4123+
}
4124+
}
4125+
wc_CmacFree(&cmac);
4126+
}
4127+
wh_Client_KeyEvict(client, keyId);
4128+
}
4129+
}
4130+
if (ret != 0)
4131+
return ret;
4132+
#endif /* WOLFSSL_CMAC && !NO_AES && WOLFSSL_AES_DIRECT */
4133+
40324134
#ifdef WOLFHSM_CFG_KEYWRAP
40334135
/* Key wrap without WRAP flag */
40344136
printf(" Testing key wrap without WRAP flag...\n");

0 commit comments

Comments
 (0)