diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 0c4e159d9..ef09404d3 100755 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -3513,27 +3513,18 @@ static int wc_PKCS7_KariGetKeyEncryptionAlgorithmId(WC_PKCS7_KARI* kari, } -/* remove ASN.1 RecipientEncryptedKeys, return 0 on success, < 0 on error */ -static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, +/* remove ASN.1 SubjectKeyIdentifier, return 0 on success, < 0 on error + * if subject key ID matches, recipFound is set to 1 */ +static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari, byte* pkiMsg, word32 pkiMsgSz, word32* idx, - int* recipFound, byte* encryptedKey, - int* encryptedKeySz) + int* recipFound) { int length; byte subjKeyId[KEYID_SIZE]; - if (kari == NULL || pkiMsg == NULL || idx == NULL || - recipFound == NULL || encryptedKey == NULL) + if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL) return BAD_FUNC_ARG; - /* remove RecipientEncryptedKeys */ - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* remove RecipientEncryptedKeys */ - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - /* remove RecipientKeyIdentifier IMPLICIT [0] */ if ( (pkiMsgSz > (*idx + 1)) && (pkiMsg[(*idx)++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) { @@ -3564,6 +3555,137 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, *recipFound = 1; } + return 0; +} + + +/* remove ASN.1 IssuerAndSerialNumber, return 0 on success, < 0 on error + * if issuer and serial number match, recipFound is set to 1 */ +static int wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI* kari, + byte* pkiMsg, word32 pkiMsgSz, word32* idx, + int* recipFound) +{ + int length, ret; + byte issuerHash[KEYID_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + mp_int* serial; + mp_int* recipSerial; +#else + mp_int stack_serial; + mp_int* serial = &stack_serial; + + mp_int stack_recipSerial; + mp_int* recipSerial = &stack_recipSerial; +#endif + + /* remove IssuerAndSerialNumber */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* if we found correct recipient, issuer hashes will match */ + if (XMEMCMP(issuerHash, kari->decoded->issuerHash, KEYID_SIZE) == 0) { + *recipFound = 1; + } + +#ifdef WOLFSSL_SMALL_STACK + serial = (mp_int*)XMALLOC(sizeof(mp_int), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (serial == NULL) + return MEMORY_E; + + recipSerial = (mp_int*)XMALLOC(sizeof(mp_int), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (recipSerial == NULL) { + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + if (GetInt(serial, pkiMsg, idx, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + ret = mp_read_unsigned_bin(recipSerial, kari->decoded->serial, + kari->decoded->serialSz); + if (ret != MP_OKAY) { + mp_clear(serial); + WOLFSSL_MSG("Failed to parse CMS recipient serial number"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (mp_cmp(recipSerial, serial) != MP_EQ) { + mp_clear(serial); + mp_clear(recipSerial); + WOLFSSL_MSG("CMS serial number does not match recipient"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PKCS7_RECIP_E; + } + + mp_clear(serial); + mp_clear(recipSerial); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + + +/* remove ASN.1 RecipientEncryptedKeys, return 0 on success, < 0 on error */ +static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, + byte* pkiMsg, word32 pkiMsgSz, word32* idx, + int* recipFound, byte* encryptedKey, + int* encryptedKeySz) +{ + int length; + int ret = 0; + + if (kari == NULL || pkiMsg == NULL || idx == NULL || + recipFound == NULL || encryptedKey == NULL) + return BAD_FUNC_ARG; + + /* remove RecipientEncryptedKeys */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* remove RecipientEncryptedKeys */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* KeyAgreeRecipientIdentifier is CHOICE of IssuerAndSerialNumber + * or [0] IMMPLICIT RecipientKeyIdentifier */ + if ( (pkiMsgSz > (*idx + 1)) && + (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) { + + /* try to get RecipientKeyIdentifier */ + ret = wc_PKCS7_KariGetSubjectKeyIdentifier(kari, pkiMsg, pkiMsgSz, + idx, recipFound); + } else { + /* try to get IssuerAndSerialNumber */ + ret = wc_PKCS7_KariGetIssuerAndSerialNumber(kari, pkiMsg, pkiMsgSz, + idx, recipFound); + } + + /* if we don't have either option, malformed CMS */ + if (ret != 0) + return ret; + /* remove EncryptedKey */ if ( (pkiMsgSz > (*idx + 1)) && (pkiMsg[(*idx)++] != ASN_OCTET_STRING) )