diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 729c17f091..f50c9436be 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -12009,6 +12009,9 @@ static int wc_PKCS7_DecryptPwri(wc_PKCS7* pkcs7, byte* in, word32 inSz, int ret = 0, length, saltSz, iterations, blockSz, kekKeySz; int hashOID = WC_SHA; /* default to SHA1 */ + int keyLen = 0; + int keyLenPresent = 0; + word32 pbkdf2End = 0; word32 kdfAlgoId, pwriEncAlgoId, keyEncAlgoId, cekSz; byte* pkiMsg = in; word32 pkiMsgSz = inSz; @@ -12055,6 +12058,7 @@ static int wc_PKCS7_DecryptPwri(wc_PKCS7* pkcs7, byte* in, word32 inSz, /* get KDF params SEQ */ if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; + pbkdf2End = *idx + (word32)length; /* get KDF salt OCTET STRING */ if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) @@ -12080,6 +12084,44 @@ static int wc_PKCS7_DecryptPwri(wc_PKCS7* pkcs7, byte* in, word32 inSz, return ASN_PARSE_E; } + /* optional keyLength - validated below once kekKeySz is known */ + if (*idx < pbkdf2End && pkiMsg[*idx] == ASN_INTEGER) { + if (GetShortInt(pkiMsg, idx, &keyLen, pbkdf2End) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + keyLenPresent = 1; + } + + /* optional prf; default hmacWithSHA1 keeps hashOID at WC_SHA */ + if (*idx < pbkdf2End && + pkiMsg[*idx] == (ASN_SEQUENCE | ASN_CONSTRUCTED)) { + word32 prfOid = 0; + if (GetAlgoId(pkiMsg, idx, &prfOid, oidHmacType, + pbkdf2End) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + switch ((int)prfOid) { + #ifdef WOLFSSL_SHA224 + case HMAC_SHA224_OID: hashOID = WC_SHA224; break; + #endif + #ifndef NO_SHA256 + case HMAC_SHA256_OID: hashOID = WC_SHA256; break; + #endif + #ifdef WOLFSSL_SHA384 + case HMAC_SHA384_OID: hashOID = WC_SHA384; break; + #endif + #ifdef WOLFSSL_SHA512 + case HMAC_SHA512_OID: hashOID = WC_SHA512; break; + #endif + default: + /* unknown id (incl. explicit hmacWithSHA1) - keep + * default WC_SHA; MAC unwrap fails if mismatched */ + break; + } + } + /* get KeyEncAlgoId SEQ */ if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) { XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -12112,6 +12154,13 @@ static int wc_PKCS7_DecryptPwri(wc_PKCS7* pkcs7, byte* in, word32 inSz, return kekKeySz; } + /* RFC 8018: when present, PBKDF2 keyLength must equal the + * derived key length expected by the encryption algorithm */ + if (keyLenPresent && keyLen != kekKeySz) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ if (GetASNTag(pkiMsg, idx, &tag, pkiMsgSz) < 0) { XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7);