Skip to content
4 changes: 2 additions & 2 deletions include/wolfcose/wolfcose.h
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ typedef struct WOLFCOSE_KEY {
* Used for key distribution (wrap, ECDH, direct).
*/
typedef struct WOLFCOSE_RECIPIENT {
int32_t algId; /**< Key distribution algorithm; direct mode requires explicit WOLFCOSE_ALG_DIRECT (-6) on encrypt (-3..-31, -6) */
int32_t algId; /**< Key distribution algorithm; direct mode requires explicit WOLFCOSE_ALG_DIRECT (-6) on both encrypt and MAC create (-3..-31, -6) */
WOLFCOSE_KEY* key; /**< Caller-owned key (KEK for wrap, recipient pubkey for ECDH) */
const uint8_t* kid; /**< Key ID for recipient lookup */
size_t kidLen; /**< Key ID length */
Expand Down Expand Up @@ -713,7 +713,7 @@ WOLFCOSE_API int wc_CoseSign1_Sign(WOLFCOSE_KEY* key, int32_t alg,
* \return WOLFCOSE_SUCCESS or negative error code.
* WOLFCOSE_E_DETACHED_PAYLOAD if payload is nil and detachedPayload is NULL.
*/
WOLFCOSE_API int wc_CoseSign1_Verify(WOLFCOSE_KEY* key,
WOLFCOSE_API int wc_CoseSign1_Verify(const WOLFCOSE_KEY* key,
const uint8_t* in, size_t inSz,
const uint8_t* detachedPayload, size_t detachedLen,
const uint8_t* extAad, size_t extAadLen,
Expand Down
70 changes: 47 additions & 23 deletions src/wolfcose.c
Original file line number Diff line number Diff line change
Expand Up @@ -3345,6 +3345,10 @@ static int wolfCose_DecodeEphemeralKey(WOLFCOSE_CBOR_CTX* ctx,
else if ((ret == WOLFCOSE_SUCCESS) && (label == -1)) {
/* crv */
ret = wc_CBOR_DecodeInt(ctx, &intVal);
if ((ret == WOLFCOSE_SUCCESS) &&
(wolfCose_InInt32Range(intVal) == 0)) {
ret = WOLFCOSE_E_COSE_BAD_HDR;
}
if (ret == WOLFCOSE_SUCCESS) {
*crv = (int)intVal;
haveCrv = 1;
Expand Down Expand Up @@ -3875,7 +3879,7 @@ int wc_CoseSign1_Sign(WOLFCOSE_KEY* key, int32_t alg,
#endif /* WOLFCOSE_SIGN1_SIGN */

#if defined(WOLFCOSE_SIGN1_VERIFY)
int wc_CoseSign1_Verify(WOLFCOSE_KEY* key,
int wc_CoseSign1_Verify(const WOLFCOSE_KEY* key,
const uint8_t* in, size_t inSz,
const uint8_t* detachedPayload, size_t detachedLen,
const uint8_t* extAad, size_t extAadLen,
Expand Down Expand Up @@ -7724,8 +7728,6 @@ int wc_CoseMac_Create(const WOLFCOSE_RECIPIENT* recipients,
WOLFCOSE_CBOR_CTX ctx;
uint8_t protectedBuf[WOLFCOSE_PROTECTED_HDR_MAX];
size_t protectedLen = 0;
uint8_t recipientProtectedBuf[WOLFCOSE_PROTECTED_HDR_MAX];
size_t recipientProtectedLen = 0;
size_t macStructLen = 0;
uint8_t macTag[WC_MAX_DIGEST_SIZE];
size_t macTagLen = 0;
Expand Down Expand Up @@ -7801,6 +7803,15 @@ int wc_CoseMac_Create(const WOLFCOSE_RECIPIENT* recipients,
}
}

/* COSE_Mac here is direct-keyed only: require an explicit
* WOLFCOSE_ALG_DIRECT so a zero-initialized (WOLFCOSE_ALG_UNSET) or a
* key-distribution algId cannot silently select the direct construction. */
for (i = 0; (ret == WOLFCOSE_SUCCESS) && (i < recipientCount); i++) {
if (recipients[i].algId != WOLFCOSE_ALG_DIRECT) {
ret = WOLFCOSE_E_COSE_BAD_ALG;
}
}

/* Get tag size for algorithm */
if (ret == WOLFCOSE_SUCCESS) {
ret = wolfCose_MacTagSize(macAlgId, &macTagLen);
Expand Down Expand Up @@ -7937,28 +7948,15 @@ int wc_CoseMac_Create(const WOLFCOSE_RECIPIENT* recipients,

/* Encode each recipient */
for (i = 0; (ret == WOLFCOSE_SUCCESS) && (i < recipientCount); i++) {
/* Encode recipient protected header. RFC 9053 Section 6.1: the direct
* key algorithm uses a zero-length protected header, so treat an
* explicit WOLFCOSE_ALG_DIRECT the same as the unset direct case. */
if ((recipients[i].algId != WOLFCOSE_ALG_UNSET) &&
(recipients[i].algId != WOLFCOSE_ALG_DIRECT)) {
ret = wolfCose_EncodeProtectedHdr(recipients[i].algId,
recipientProtectedBuf, sizeof(recipientProtectedBuf),
&recipientProtectedLen);
}
else {
recipientProtectedLen = 0;
}
/* Start recipient array [protected, unprotected, ciphertext]. The loop
* condition guarantees ret == WOLFCOSE_SUCCESS on entry. */
ret = wc_CBOR_EncodeArrayStart(&ctx, 3u);

/* Start recipient array [protected, unprotected, ciphertext] */
/* [0] protected header bstr. Every recipient was validated to
* WOLFCOSE_ALG_DIRECT above, which uses a zero-length protected
* header (RFC 9053 Section 6.1). */
if (ret == WOLFCOSE_SUCCESS) {
ret = wc_CBOR_EncodeArrayStart(&ctx, 3u);
}

/* [0] protected header bstr */
if (ret == WOLFCOSE_SUCCESS) {
ret = wc_CBOR_EncodeBstr(&ctx, recipientProtectedBuf,
recipientProtectedLen);
ret = wc_CBOR_EncodeBstr(&ctx, NULL, 0);
}

/* [1] unprotected header map (with kid if present) */
Expand Down Expand Up @@ -8031,6 +8029,7 @@ int wc_CoseMac_Verify(const WOLFCOSE_RECIPIENT* recipient,
size_t recipientsCount = 0;
size_t i;
int32_t alg = 0;
int32_t recipientAlgId = WOLFCOSE_ALG_UNSET;
size_t macStructLen = 0;
size_t expectedTagLen = 0;
uint8_t computedTag[WC_MAX_DIGEST_SIZE];
Expand Down Expand Up @@ -8181,6 +8180,9 @@ int wc_CoseMac_Verify(const WOLFCOSE_RECIPIENT* recipient,
if (ret == WOLFCOSE_SUCCESS) {
ret = wolfCose_DecodeUnprotectedHdr(&ctx, &recipHdr, &recipState);
}
if (ret == WOLFCOSE_SUCCESS) {
recipientAlgId = recipHdr.alg;
}
/* ciphertext: bstr (wrapped key) or nil (direct). */
if (ret == WOLFCOSE_SUCCESS) {
ret = wolfCose_CBOR_DecodeHead(&ctx, &item);
Expand Down Expand Up @@ -8219,6 +8221,28 @@ int wc_CoseMac_Verify(const WOLFCOSE_RECIPIENT* recipient,
ret = WOLFCOSE_E_COSE_BAD_ALG;
}

/* COSE_Mac is direct-keyed here: the only supported recipient modes are an
* absent (UNSET) or explicit WOLFCOSE_ALG_DIRECT alg. A recipient that
* advertises a key-distribution mode is not silently accepted. */
if ((ret == WOLFCOSE_SUCCESS) &&
(recipientAlgId != WOLFCOSE_ALG_UNSET) &&
(recipientAlgId != WOLFCOSE_ALG_DIRECT)) {
ret = WOLFCOSE_E_UNSUPPORTED;
}

/* Enforce the caller's recipient->algId policy when set, normalizing an
* absent recipient alg to direct (matches wc_CoseEncrypt_Decrypt). */
if ((ret == WOLFCOSE_SUCCESS) &&
(recipient->algId != WOLFCOSE_ALG_UNSET)) {
int32_t gotAlg = recipientAlgId;
if (gotAlg == WOLFCOSE_ALG_UNSET) {
gotAlg = WOLFCOSE_ALG_DIRECT;
}
if (recipient->algId != gotAlg) {
ret = WOLFCOSE_E_COSE_BAD_ALG;
}
}

/* Get expected tag size */
if (ret == WOLFCOSE_SUCCESS) {
ret = wolfCose_MacTagSize(alg, &expectedTagLen);
Expand Down
3 changes: 2 additions & 1 deletion tests/test_cbor.c
Original file line number Diff line number Diff line change
Expand Up @@ -945,7 +945,8 @@ static void test_cbor_boundary_roundtrip(void)
};
static const struct { int64_t val; size_t len; } ivec[] = {
{-1, 1u}, {-24, 1u}, {-25, 2u}, {-256, 2u}, {-257, 3u},
{-65536, 3u}, {-65537, 5u}
{-65536, 3u}, {-65537, 5u},
{-4294967296LL, 5u}, {-4294967297LL, 9u}, {INT64_MIN, 9u}
};
uint8_t buf[16];
WOLFCOSE_CBOR_CTX ctx;
Expand Down
Loading
Loading