Skip to content

Commit aa52e32

Browse files
authored
Merge pull request #474 from yosuke-wolfssl/fix/cmac
Bound CMAC response payloads against the received frame
2 parents 3fc35a1 + bcc7d3d commit aa52e32

1 file changed

Lines changed: 66 additions & 15 deletions

File tree

src/wh_client_crypto.c

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5761,9 +5761,17 @@ int wh_Client_CmacGenerateResponse(whClientContext* ctx, Cmac* cmac,
57615761
ret = _getCryptoResponse(dataPtr, WC_ALGO_TYPE_CMAC, (uint8_t**)&res);
57625762
/* wolfCrypt allows positive error codes on success */
57635763
if (ret >= 0) {
5764-
/* Restore state from response (server has finalized; buffer/digest
5765-
* carry the post-finalization state). */
5766-
ret = wh_Crypto_CmacAesRestoreStateFromMsg(cmac, &res->resumeState);
5764+
const uint32_t hdr_sz =
5765+
sizeof(whMessageCrypto_GenericResponseHeader) + sizeof(*res);
5766+
/* The MAC bytes the response claims must be in the received frame */
5767+
if (res_len < hdr_sz || res->outSz > (res_len - hdr_sz)) {
5768+
ret = WH_ERROR_ABORTED;
5769+
}
5770+
if (ret >= 0) {
5771+
/* Restore state from response (server has finalized; buffer/digest
5772+
* carry the post-finalization state). */
5773+
ret = wh_Crypto_CmacAesRestoreStateFromMsg(cmac, &res->resumeState);
5774+
}
57675775
if (ret >= 0) {
57685776
ret = _CmacValidateTagLen(*outMacLen);
57695777
}
@@ -5882,10 +5890,17 @@ int wh_Client_CmacUpdateResponse(whClientContext* ctx, Cmac* cmac)
58825890

58835891
ret = _getCryptoResponse(dataPtr, WC_ALGO_TYPE_CMAC, (uint8_t**)&res);
58845892
if (ret >= 0) {
5885-
/* Restore full state from server. The server may leave a partial
5886-
* (or whole) block in its buffer after wc_CmacUpdate (CMAC's last
5887-
* block has special handling), so we round-trip the whole state. */
5888-
ret = wh_Crypto_CmacAesRestoreStateFromMsg(cmac, &res->resumeState);
5893+
/* No trailing payload on update, but the state must be in the frame */
5894+
if (res_len < sizeof(whMessageCrypto_GenericResponseHeader) +
5895+
sizeof(*res)) {
5896+
ret = WH_ERROR_ABORTED;
5897+
}
5898+
if (ret >= 0) {
5899+
/* Restore full state from server. The server may leave a partial
5900+
* (or whole) block in its buffer after wc_CmacUpdate (CMAC's last
5901+
* block has special handling), so we round-trip the whole state. */
5902+
ret = wh_Crypto_CmacAesRestoreStateFromMsg(cmac, &res->resumeState);
5903+
}
58895904
}
58905905
return ret;
58915906
}
@@ -5973,9 +5988,17 @@ int wh_Client_CmacFinalResponse(whClientContext* ctx, Cmac* cmac,
59735988

59745989
ret = _getCryptoResponse(dataPtr, WC_ALGO_TYPE_CMAC, (uint8_t**)&res);
59755990
if (ret >= 0) {
5976-
/* Restore final state from response (server's bufferSz is 0 after
5977-
* Final). */
5978-
ret = wh_Crypto_CmacAesRestoreStateFromMsg(cmac, &res->resumeState);
5991+
const uint32_t hdr_sz =
5992+
sizeof(whMessageCrypto_GenericResponseHeader) + sizeof(*res);
5993+
/* The MAC bytes the response claims must be in the received frame */
5994+
if (res_len < hdr_sz || res->outSz > (res_len - hdr_sz)) {
5995+
ret = WH_ERROR_ABORTED;
5996+
}
5997+
if (ret >= 0) {
5998+
/* Restore final state from response (server's bufferSz is 0 after
5999+
* Final). */
6000+
ret = wh_Crypto_CmacAesRestoreStateFromMsg(cmac, &res->resumeState);
6001+
}
59796002
if (ret >= 0) {
59806003
ret = _CmacValidateTagLen(*outMacLen);
59816004
}
@@ -6215,7 +6238,18 @@ int wh_Client_CmacGenerateDmaResponse(whClientContext* ctx, Cmac* cmac,
62156238
if (ret == WH_ERROR_OK) {
62166239
ret = _getCryptoResponse(dataPtr, WC_ALGO_TYPE_CMAC, (uint8_t**)&res);
62176240
if (ret >= 0) {
6218-
ret = wh_Crypto_CmacAesRestoreStateFromMsg(cmac, &res->resumeState);
6241+
const uint32_t hdr_sz =
6242+
sizeof(whMessageCrypto_GenericResponseHeader) + sizeof(*res);
6243+
/* The MAC bytes the response claims must be in the received
6244+
* frame. A failed server request replies with the generic header
6245+
* only, so this bound stays inside the success branch. */
6246+
if (respSz < hdr_sz || res->outSz > (respSz - hdr_sz)) {
6247+
ret = WH_ERROR_ABORTED;
6248+
}
6249+
if (ret >= 0) {
6250+
ret = wh_Crypto_CmacAesRestoreStateFromMsg(cmac,
6251+
&res->resumeState);
6252+
}
62196253
if (ret >= 0) {
62206254
ret = _CmacValidateTagLen(*outMacLen);
62216255
}
@@ -6361,9 +6395,18 @@ int wh_Client_CmacDmaUpdateResponse(whClientContext* ctx, Cmac* cmac)
63616395
if (ret == WH_ERROR_OK) {
63626396
ret = _getCryptoResponse(dataPtr, WC_ALGO_TYPE_CMAC, (uint8_t**)&res);
63636397
if (ret >= 0) {
6364-
/* Restore full state from server (includes any partial/whole
6365-
* block left in the server's wc_CmacUpdate buffer). */
6366-
ret = wh_Crypto_CmacAesRestoreStateFromMsg(cmac, &res->resumeState);
6398+
/* No trailing payload on update, but the state must be in the
6399+
* frame */
6400+
if (respSz < sizeof(whMessageCrypto_GenericResponseHeader) +
6401+
sizeof(*res)) {
6402+
ret = WH_ERROR_ABORTED;
6403+
}
6404+
if (ret >= 0) {
6405+
/* Restore full state from server (includes any partial/whole
6406+
* block left in the server's wc_CmacUpdate buffer). */
6407+
ret = wh_Crypto_CmacAesRestoreStateFromMsg(cmac,
6408+
&res->resumeState);
6409+
}
63676410
}
63686411
}
63696412

@@ -6451,7 +6494,15 @@ int wh_Client_CmacDmaFinalResponse(whClientContext* ctx, Cmac* cmac,
64516494

64526495
ret = _getCryptoResponse(dataPtr, WC_ALGO_TYPE_CMAC, (uint8_t**)&res);
64536496
if (ret >= 0) {
6454-
ret = wh_Crypto_CmacAesRestoreStateFromMsg(cmac, &res->resumeState);
6497+
const uint32_t hdr_sz =
6498+
sizeof(whMessageCrypto_GenericResponseHeader) + sizeof(*res);
6499+
/* The MAC bytes the response claims must be in the received frame */
6500+
if (respSz < hdr_sz || res->outSz > (respSz - hdr_sz)) {
6501+
ret = WH_ERROR_ABORTED;
6502+
}
6503+
if (ret >= 0) {
6504+
ret = wh_Crypto_CmacAesRestoreStateFromMsg(cmac, &res->resumeState);
6505+
}
64556506
if (ret >= 0) {
64566507
ret = _CmacValidateTagLen(*outMacLen);
64576508
}

0 commit comments

Comments
 (0)