From a2ccec4a3eb22f5659e95b3ff9aad3b42c583a5e Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Tue, 8 Sep 2026 16:42:14 -0700 Subject: [PATCH 01/10] F-13016 - Scrub AES state after callback cleanup --- src/wolfcose_encrypt.c | 2 ++ src/wolfcose_encrypt0.c | 2 ++ src/wolfcose_mac0.c | 1 + 3 files changed, 5 insertions(+) diff --git a/src/wolfcose_encrypt.c b/src/wolfcose_encrypt.c index f2c02e70..36cadb5d 100644 --- a/src/wolfcose_encrypt.c +++ b/src/wolfcose_encrypt.c @@ -649,6 +649,7 @@ int wc_CoseEncrypt_Encrypt(const WOLFCOSE_RECIPIENT* recipients, #if defined(WOLFCOSE_HAVE_AESGCM) || defined(WOLFCOSE_HAVE_AESCCM) if (aesInited != 0) { (void)wc_AesFree(&aes); + (void)wolfCose_ForceZero(&aes, sizeof(aes)); } #endif #if defined(WOLFCOSE_KEY_WRAP) @@ -1262,6 +1263,7 @@ int wc_CoseEncrypt_Decrypt(const WOLFCOSE_RECIPIENT* recipient, #if defined(WOLFCOSE_HAVE_AESGCM) || defined(WOLFCOSE_HAVE_AESCCM) if (aesInited != 0) { (void)wc_AesFree(&aes); + (void)wolfCose_ForceZero(&aes, sizeof(aes)); } #endif #if defined(WOLFCOSE_KEY_WRAP) diff --git a/src/wolfcose_encrypt0.c b/src/wolfcose_encrypt0.c index dd440676..f275c1ed 100644 --- a/src/wolfcose_encrypt0.c +++ b/src/wolfcose_encrypt0.c @@ -416,6 +416,7 @@ int wc_CoseEncrypt0_Encrypt(const WOLFCOSE_KEY* key, int32_t alg, #if defined(WOLFCOSE_HAVE_AESGCM) || defined(WOLFCOSE_HAVE_AESCCM) if (aesInited != 0) { (void)wc_AesFree(&aes); + (void)wolfCose_ForceZero(&aes, sizeof(aes)); } #endif if (scratch != NULL) { @@ -726,6 +727,7 @@ int wc_CoseEncrypt0_Decrypt(const WOLFCOSE_KEY* key, #if defined(WOLFCOSE_HAVE_AESGCM) || defined(WOLFCOSE_HAVE_AESCCM) if (aesInited != 0) { (void)wc_AesFree(&aes); + (void)wolfCose_ForceZero(&aes, sizeof(aes)); } #endif if (scratch != NULL) { diff --git a/src/wolfcose_mac0.c b/src/wolfcose_mac0.c index 780f19dc..9b9e0332 100644 --- a/src/wolfcose_mac0.c +++ b/src/wolfcose_mac0.c @@ -257,6 +257,7 @@ int wolfCose_AesCbcMac(const uint8_t* key, size_t keyLen, /* Cleanup: always executed */ if (aesInited != 0) { (void)wc_AesFree(&aes); + (void)wolfCose_ForceZero(&aes, sizeof(aes)); } (void)wolfCose_ForceZero(inBlock, sizeof(inBlock)); (void)wolfCose_ForceZero(outBlock, sizeof(outBlock)); From d1ecd5fc9d73cb8b7997718932ea7d1393c723b5 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 9 Sep 2026 09:15:53 -0700 Subject: [PATCH 02/10] F-11108 - Remove unreachable recipient check --- src/wolfcose_mac.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/wolfcose_mac.c b/src/wolfcose_mac.c index e476036d..47d7d629 100644 --- a/src/wolfcose_mac.c +++ b/src/wolfcose_mac.c @@ -624,17 +624,10 @@ int wc_CoseMac_Verify(const WOLFCOSE_RECIPIENT* recipient, ret = WOLFCOSE_E_COSE_BAD_ALG; } - /* COSE_Mac is direct-keyed here and the recipient algorithm is mandatory. */ - if (ret == WOLFCOSE_SUCCESS) { - if (recipientAlgId == WOLFCOSE_ALG_UNSET) { - ret = WOLFCOSE_E_COSE_BAD_ALG; - } - else if (recipientAlgId != WOLFCOSE_ALG_DIRECT) { - ret = WOLFCOSE_E_UNSUPPORTED; - } - else { - /* No action required */ - } + /* COSE_Mac is direct-keyed here. */ + if ((ret == WOLFCOSE_SUCCESS) && + (recipientAlgId != WOLFCOSE_ALG_DIRECT)) { + ret = WOLFCOSE_E_UNSUPPORTED; } if (ret == WOLFCOSE_SUCCESS) { if ((recipientValueIsNull == 0) && (recipientValueLen != 0u)) { From efa772745ed92a78e7c29b8e450a3c2343368232 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 9 Sep 2026 09:32:54 -0700 Subject: [PATCH 03/10] F-12138 - Reject inconsistent detached length --- src/wolfcose_encrypt.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wolfcose_encrypt.c b/src/wolfcose_encrypt.c index 36cadb5d..7409da10 100644 --- a/src/wolfcose_encrypt.c +++ b/src/wolfcose_encrypt.c @@ -152,6 +152,10 @@ int wc_CoseEncrypt_Encrypt(const WOLFCOSE_RECIPIENT* recipients, (iv == NULL) || (ivLen == 0u)) { ret = WOLFCOSE_E_INVALID_ARG; } + if ((ret == WOLFCOSE_SUCCESS) && (detachedPayload == NULL) && + (detachedLen != 0u)) { + ret = WOLFCOSE_E_INVALID_ARG; + } #ifdef WOLFCOSE_CHECK_WORD32_LEN if ((ret == WOLFCOSE_SUCCESS) && From 678f6704535ff9b3fa7e618eacfd77c39c8da1c8 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 9 Sep 2026 09:37:33 -0700 Subject: [PATCH 04/10] F-12210 - Reject unprocessed critical content type --- src/wolfcose_hdr.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/wolfcose_hdr.c b/src/wolfcose_hdr.c index 93d32272..1efac61e 100644 --- a/src/wolfcose_hdr.c +++ b/src/wolfcose_hdr.c @@ -246,6 +246,8 @@ int wolfCose_DecodeProtectedHdr(const uint8_t* data, size_t dataLen, ret = WOLFCOSE_SUCCESS; } else { + uint8_t contentTypeUnderstood = 0u; + wolfCose_HdrStateInit(hdrState); ctx.cbuf = data; ctx.bufSz = dataLen; @@ -336,6 +338,7 @@ int wolfCose_DecodeProtectedHdr(const uint8_t* data, size_t dataLen, } if (ret == WOLFCOSE_SUCCESS) { hdr->contentType = (int32_t)contentTypeVal; + contentTypeUnderstood = 1u; } } } @@ -385,6 +388,11 @@ int wolfCose_DecodeProtectedHdr(const uint8_t* data, size_t dataLen, ((critLabels & ~hdrState->labelBits) != 0u)) { ret = WOLFCOSE_E_COSE_BAD_HDR; } + if ((ret == WOLFCOSE_SUCCESS) && + ((critLabels & wolfCose_LabelBit(WOLFCOSE_HDR_CONTENT_TYPE)) != + 0u) && (contentTypeUnderstood == 0u)) { + ret = WOLFCOSE_E_COSE_BAD_HDR; + } /* IV and Partial IV are mutually exclusive. */ if ((ret == WOLFCOSE_SUCCESS) && From c629cd652bcdb0e430743b81ea9f7d570af0bbb1 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 9 Sep 2026 09:38:45 -0700 Subject: [PATCH 05/10] F-12936 - Reject ECDSA signing without ASN --- include/wolfcose/settings.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/wolfcose/settings.h b/include/wolfcose/settings.h index 9a078184..ee30f6db 100644 --- a/include/wolfcose/settings.h +++ b/include/wolfcose/settings.h @@ -440,6 +440,14 @@ extern "C" { #error "wolfCOSE RSA-PSS key validation requires WOLFSSL_EXPORT_INT" #endif +/* The local ECDSA signing path converts a wolfCrypt DER signature to the + * fixed-width COSE representation. NO_ASN is supported for verification + * builds only. */ +#if defined(NO_ASN) && defined(WOLFCOSE_HAVE_ECDSA) && \ + (defined(WOLFCOSE_SIGN1_SIGN) || defined(WOLFCOSE_SIGN_SIGN)) + #error "wolfCOSE ECDSA signing requires ASN support" +#endif + /* Optional RFC 6979 deterministic ECDSA signing. */ #if defined(WOLFCOSE_ENABLE_DETERMINISTIC_ECDSA) && \ defined(WOLFCOSE_HAVE_ECDSA) && \ From a4d25ab73a6de76592186c0ae4564ac8e73bd076 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 9 Sep 2026 09:39:26 -0700 Subject: [PATCH 06/10] F-12937 - Reject invalid protected header pointer --- src/wolfcose_hdr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/wolfcose_hdr.c b/src/wolfcose_hdr.c index 1efac61e..95694a22 100644 --- a/src/wolfcose_hdr.c +++ b/src/wolfcose_hdr.c @@ -240,7 +240,10 @@ int wolfCose_DecodeProtectedHdr(const uint8_t* data, size_t dataLen, if ((hdr == NULL) || (hdrState == NULL)) { ret = WOLFCOSE_E_INVALID_ARG; } - else if ((data == NULL) || (dataLen == 0u)) { + else if ((data == NULL) && (dataLen != 0u)) { + ret = WOLFCOSE_E_INVALID_ARG; + } + else if (dataLen == 0u) { /* Empty protected header is valid */ wolfCose_HdrStateInit(hdrState); ret = WOLFCOSE_SUCCESS; From 8536b1f07122b998fa2e710d62c245bca62c791b Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Wed, 9 Sep 2026 15:34:01 -0700 Subject: [PATCH 07/10] Preserve missing recipient algorithm error --- src/wolfcose_mac.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/wolfcose_mac.c b/src/wolfcose_mac.c index 47d7d629..f3fca239 100644 --- a/src/wolfcose_mac.c +++ b/src/wolfcose_mac.c @@ -625,9 +625,16 @@ int wc_CoseMac_Verify(const WOLFCOSE_RECIPIENT* recipient, } /* COSE_Mac is direct-keyed here. */ - if ((ret == WOLFCOSE_SUCCESS) && - (recipientAlgId != WOLFCOSE_ALG_DIRECT)) { - ret = WOLFCOSE_E_UNSUPPORTED; + if (ret == WOLFCOSE_SUCCESS) { + if (recipientAlgId == WOLFCOSE_ALG_UNSET) { + ret = WOLFCOSE_E_COSE_BAD_ALG; + } + else if (recipientAlgId != WOLFCOSE_ALG_DIRECT) { + ret = WOLFCOSE_E_UNSUPPORTED; + } + else { + /* No action required */ + } } if (ret == WOLFCOSE_SUCCESS) { if ((recipientValueIsNull == 0) && (recipientValueLen != 0u)) { From 3056fe2a72c13310353beb67b3af5329277e38b1 Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Thu, 10 Sep 2026 09:26:56 -0700 Subject: [PATCH 08/10] Cover critical text content type rejection --- tests/test_cose.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/test_cose.c b/tests/test_cose.c index 2a4743d0..6faa5148 100644 --- a/tests/test_cose.c +++ b/tests/test_cose.c @@ -18098,6 +18098,10 @@ static void test_cose_protected_hdr_crit(void) uint8_t critMissing[] = {0xA2u, 0x01u, 0x26u, 0x02u, 0x81u, 0x05u}; /* {1: -7, 2: []} : crit is an empty array -> RFC 9052 rejects */ uint8_t critEmpty[] = {0xA2u, 0x01u, 0x26u, 0x02u, 0x80u}; + /* {2: [3], 3: "x"} : critical tstr content type is not understood */ + uint8_t critTstrContentType[] = { + 0xA2u, 0x02u, 0x81u, 0x03u, 0x03u, 0x61u, 'x' + }; TEST_LOG(" [Protected Header: crit]\n"); XMEMSET(&hdr, 0, sizeof(hdr)); @@ -18123,6 +18127,12 @@ static void test_cose_protected_hdr_crit(void) &hdrState); TEST_ASSERT(ret == WOLFCOSE_E_COSE_BAD_HDR, "DecodeProtectedHdr crit empty array"); + + XMEMSET(&hdr, 0, sizeof(hdr)); + ret = wolfCose_DecodeProtectedHdr(critTstrContentType, + sizeof(critTstrContentType), &hdr, &hdrState); + TEST_ASSERT(ret == WOLFCOSE_E_COSE_BAD_HDR, + "DecodeProtectedHdr rejects critical tstr content-type"); } static void test_cose_cross_bucket_dup(void) From 185b548882f251464ba4ab5971cef9569755b3cf Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Mon, 14 Sep 2026 09:37:56 -0700 Subject: [PATCH 09/10] F-11108 - Remove unreachable recipient check --- src/wolfcose_mac.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/wolfcose_mac.c b/src/wolfcose_mac.c index f3fca239..47d7d629 100644 --- a/src/wolfcose_mac.c +++ b/src/wolfcose_mac.c @@ -625,16 +625,9 @@ int wc_CoseMac_Verify(const WOLFCOSE_RECIPIENT* recipient, } /* COSE_Mac is direct-keyed here. */ - if (ret == WOLFCOSE_SUCCESS) { - if (recipientAlgId == WOLFCOSE_ALG_UNSET) { - ret = WOLFCOSE_E_COSE_BAD_ALG; - } - else if (recipientAlgId != WOLFCOSE_ALG_DIRECT) { - ret = WOLFCOSE_E_UNSUPPORTED; - } - else { - /* No action required */ - } + if ((ret == WOLFCOSE_SUCCESS) && + (recipientAlgId != WOLFCOSE_ALG_DIRECT)) { + ret = WOLFCOSE_E_UNSUPPORTED; } if (ret == WOLFCOSE_SUCCESS) { if ((recipientValueIsNull == 0) && (recipientValueLen != 0u)) { From 334ff27209bbe0b4e704ea9e45873c94620b47ed Mon Sep 17 00:00:00 2001 From: Aidan Garske Date: Mon, 14 Sep 2026 09:47:00 -0700 Subject: [PATCH 10/10] Guard COSE label bit shift count --- src/wolfcose_hdr.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/wolfcose_hdr.c b/src/wolfcose_hdr.c index 83f95300..e7f1e006 100644 --- a/src/wolfcose_hdr.c +++ b/src/wolfcose_hdr.c @@ -61,19 +61,20 @@ int wolfCose_InInt32Range(int64_t val) static uint32_t wolfCose_LabelBit(int64_t label) { uint32_t bit; - uint32_t shift; - int64_t shift64; + uint32_t shift = 32u; if ((label >= 1) && (label <= 16)) { - shift64 = label; - shift64--; - shift = (uint32_t)shift64; - bit = ((uint32_t)1u) << shift; + shift = (uint32_t)label; + shift--; } else if ((label <= -1) && (label >= -16)) { - shift64 = -label; - shift = (uint32_t)shift64; + shift = (uint32_t)(-label); shift += 15u; + } + else { + /* No tracked bit. */ + } + if (shift < 32u) { bit = ((uint32_t)1u) << shift; } else {