add PKCS7/CMS decode support for KARI with IssuerAndSerialNumber

This commit is contained in:
Chris Conlon 2017-06-16 15:16:32 -06:00
parent e6f0ee84ec
commit 816b0b058c

View File

@ -3513,27 +3513,18 @@ static int wc_PKCS7_KariGetKeyEncryptionAlgorithmId(WC_PKCS7_KARI* kari,
} }
/* remove ASN.1 RecipientEncryptedKeys, return 0 on success, < 0 on error */ /* remove ASN.1 SubjectKeyIdentifier, return 0 on success, < 0 on error
static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, * 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, byte* pkiMsg, word32 pkiMsgSz, word32* idx,
int* recipFound, byte* encryptedKey, int* recipFound)
int* encryptedKeySz)
{ {
int length; int length;
byte subjKeyId[KEYID_SIZE]; byte subjKeyId[KEYID_SIZE];
if (kari == NULL || pkiMsg == NULL || idx == NULL || if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL)
recipFound == NULL || encryptedKey == NULL)
return BAD_FUNC_ARG; 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] */ /* remove RecipientKeyIdentifier IMPLICIT [0] */
if ( (pkiMsgSz > (*idx + 1)) && if ( (pkiMsgSz > (*idx + 1)) &&
(pkiMsg[(*idx)++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) { (pkiMsg[(*idx)++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) {
@ -3564,6 +3555,137 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari,
*recipFound = 1; *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 */ /* remove EncryptedKey */
if ( (pkiMsgSz > (*idx + 1)) && if ( (pkiMsgSz > (*idx + 1)) &&
(pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) (pkiMsg[(*idx)++] != ASN_OCTET_STRING) )