forked from wolfSSL/wolfssl
fix setting and checking CMS EnvelopedData version
This commit is contained in:
committed by
David Garske
parent
b0e4cb3572
commit
b4d02d6d99
@@ -663,6 +663,7 @@ typedef struct Pkcs7EncodedRecip {
|
|||||||
byte recip[MAX_RECIP_SZ];
|
byte recip[MAX_RECIP_SZ];
|
||||||
word32 recipSz;
|
word32 recipSz;
|
||||||
int recipType;
|
int recipType;
|
||||||
|
int recipVersion;
|
||||||
Pkcs7EncodedRecip* next;
|
Pkcs7EncodedRecip* next;
|
||||||
} Pkcs7EncodedRecip;
|
} Pkcs7EncodedRecip;
|
||||||
|
|
||||||
@@ -735,6 +736,51 @@ static void wc_PKCS7_FreeEncodedRecipientSet(PKCS7* pkcs7)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* search through RecipientInfo list for specific type.
|
||||||
|
* return 1 if ANY recipient of type specified is present, otherwise
|
||||||
|
* return 0 */
|
||||||
|
static int wc_PKCS7_RecipientListIncludesType(PKCS7* pkcs7, int type)
|
||||||
|
{
|
||||||
|
Pkcs7EncodedRecip* tmp = NULL;
|
||||||
|
|
||||||
|
if (pkcs7 == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
tmp = pkcs7->recipList;
|
||||||
|
|
||||||
|
while (tmp != NULL) {
|
||||||
|
if (tmp->recipType == type)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* searches through RecipientInfo list, returns 1 if all structure
|
||||||
|
* versions are set to 0, otherwise returns 0 */
|
||||||
|
static int wc_PKCS7_RecipientListVersionsAllZero(PKCS7* pkcs7)
|
||||||
|
{
|
||||||
|
Pkcs7EncodedRecip* tmp = NULL;
|
||||||
|
|
||||||
|
if (pkcs7 == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
tmp = pkcs7->recipList;
|
||||||
|
|
||||||
|
while (tmp != NULL) {
|
||||||
|
if (tmp->recipVersion != 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Init PKCS7 struct with recipient cert, decode into DecodedCert
|
/* Init PKCS7 struct with recipient cert, decode into DecodedCert
|
||||||
* NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */
|
* NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */
|
||||||
int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz)
|
int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz)
|
||||||
@@ -3829,6 +3875,12 @@ static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* only supports ECDSA for now */
|
||||||
|
if (kari->decoded->keyOID != ECDSAk) {
|
||||||
|
WOLFSSL_MSG("CMS KARI only supports ECDSA key types");
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
/* make sure subject key id was read from cert */
|
/* make sure subject key id was read from cert */
|
||||||
if (kari->decoded->extSubjKeyIdSet == 0) {
|
if (kari->decoded->extSubjKeyIdSet == 0) {
|
||||||
WOLFSSL_MSG("Failed to read subject key ID from recipient cert");
|
WOLFSSL_MSG("Failed to read subject key ID from recipient cert");
|
||||||
@@ -4142,6 +4194,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
|
|||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int keySz, direction = 0;
|
int keySz, direction = 0;
|
||||||
|
int blockKeySz = 0;
|
||||||
|
|
||||||
/* ASN.1 layout */
|
/* ASN.1 layout */
|
||||||
int totalSz = 0;
|
int totalSz = 0;
|
||||||
@@ -4204,14 +4257,24 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
|
|||||||
}
|
}
|
||||||
XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip));
|
XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip));
|
||||||
|
|
||||||
/* only supports ECDSA for now */
|
/* get key size for content-encryption key based on algorithm */
|
||||||
if (pkcs7->publicKeyOID != ECDSAk) {
|
blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID);
|
||||||
WOLFSSL_MSG("CMS KARI only supports ECDSA key types");
|
if (blockKeySz < 0) {
|
||||||
#ifdef WOLFSSL_SMALL_STACK
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
#endif
|
#endif
|
||||||
XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||||
return BAD_FUNC_ARG;
|
return blockKeySz;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* generate random content encryption key, if needed */
|
||||||
|
ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz);
|
||||||
|
if (ret < 0) {
|
||||||
|
#ifdef WOLFSSL_SMALL_STACK
|
||||||
|
XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
#endif
|
||||||
|
XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* set direction based on keyWrapAlgo */
|
/* set direction based on keyWrapAlgo */
|
||||||
@@ -4375,6 +4438,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
|
|||||||
/* version, always 3 */
|
/* version, always 3 */
|
||||||
verSz = SetMyVersion(3, ver, 0);
|
verSz = SetMyVersion(3, ver, 0);
|
||||||
totalSz += verSz;
|
totalSz += verSz;
|
||||||
|
recip->recipVersion = 3;
|
||||||
|
|
||||||
/* outer IMPLICIT [1] kari */
|
/* outer IMPLICIT [1] kari */
|
||||||
kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq);
|
kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq);
|
||||||
@@ -4608,6 +4672,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz,
|
|||||||
|
|
||||||
/* version, must be 0 for IssuerAndSerialNumber */
|
/* version, must be 0 for IssuerAndSerialNumber */
|
||||||
verSz = SetMyVersion(0, ver, 0);
|
verSz = SetMyVersion(0, ver, 0);
|
||||||
|
recip->recipVersion = 0;
|
||||||
|
|
||||||
/* IssuerAndSerialNumber */
|
/* IssuerAndSerialNumber */
|
||||||
if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) {
|
if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) {
|
||||||
@@ -4647,6 +4712,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz,
|
|||||||
|
|
||||||
/* version, must be 2 for SubjectKeyIdentifier */
|
/* version, must be 2 for SubjectKeyIdentifier */
|
||||||
verSz = SetMyVersion(2, ver, 0);
|
verSz = SetMyVersion(2, ver, 0);
|
||||||
|
recip->recipVersion = 2;
|
||||||
|
|
||||||
issuerSKIDSz = SetOctetString(KEYID_SIZE, issuerSKID);
|
issuerSKIDSz = SetOctetString(KEYID_SIZE, issuerSKID);
|
||||||
issuerSKIDSeqSz = SetExplicit(0, issuerSKIDSz + KEYID_SIZE,
|
issuerSKIDSeqSz = SetExplicit(0, issuerSKIDSz + KEYID_SIZE,
|
||||||
@@ -5327,6 +5393,7 @@ int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb,
|
|||||||
/* store recipient size */
|
/* store recipient size */
|
||||||
recip->recipSz = idx;
|
recip->recipSz = idx;
|
||||||
recip->recipType = PKCS7_ORI;
|
recip->recipType = PKCS7_ORI;
|
||||||
|
recip->recipVersion = 4;
|
||||||
|
|
||||||
/* add recipient to recip list */
|
/* add recipient to recip list */
|
||||||
if (pkcs7->recipList == NULL) {
|
if (pkcs7->recipList == NULL) {
|
||||||
@@ -5756,6 +5823,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen,
|
|||||||
/* set PasswordRecipientInfo CMSVersion, MUST be 0 */
|
/* set PasswordRecipientInfo CMSVersion, MUST be 0 */
|
||||||
verSz = SetMyVersion(0, ver, 0);
|
verSz = SetMyVersion(0, ver, 0);
|
||||||
totalSz += verSz;
|
totalSz += verSz;
|
||||||
|
recip->recipVersion = 0;
|
||||||
|
|
||||||
/* set PasswordRecipientInfo SEQ */
|
/* set PasswordRecipientInfo SEQ */
|
||||||
recipSeqSz = SetImplicit(ASN_SEQUENCE, 3, totalSz, recipSeq);
|
recipSeqSz = SetImplicit(ASN_SEQUENCE, 3, totalSz, recipSeq);
|
||||||
@@ -5974,6 +6042,7 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek,
|
|||||||
/* version */
|
/* version */
|
||||||
verSz = SetMyVersion(4, ver, 0);
|
verSz = SetMyVersion(4, ver, 0);
|
||||||
totalSz += verSz;
|
totalSz += verSz;
|
||||||
|
recip->recipVersion = 4;
|
||||||
|
|
||||||
/* KEKRecipientInfo SEQ */
|
/* KEKRecipientInfo SEQ */
|
||||||
recipSeqSz = SetImplicit(ASN_SEQUENCE, 2, totalSz, recipSeq);
|
recipSeqSz = SetImplicit(ASN_SEQUENCE, 2, totalSz, recipSeq);
|
||||||
@@ -6035,6 +6104,47 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wc_PKCS7_GetCMSVersion(PKCS7* pkcs7, int cmsContentType)
|
||||||
|
{
|
||||||
|
int version = -1;
|
||||||
|
|
||||||
|
if (pkcs7 == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
switch (cmsContentType) {
|
||||||
|
case ENVELOPED_DATA:
|
||||||
|
|
||||||
|
/* NOTE: EnvelopedData does not currently support
|
||||||
|
originatorInfo or unprotectedAttributes. When either of these
|
||||||
|
are added, version checking below needs to be updated to match
|
||||||
|
Section 6.1 of RFC 5652 */
|
||||||
|
|
||||||
|
/* if RecipientInfos include pwri or ori, version is 3 */
|
||||||
|
if (wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_PWRI) ||
|
||||||
|
wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_ORI)) {
|
||||||
|
version = 3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if unprotectedAttrs is absent AND all RecipientInfo structs
|
||||||
|
are version 0, version is 0 */
|
||||||
|
if (wc_PKCS7_RecipientListVersionsAllZero(pkcs7)) {
|
||||||
|
version = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* otherwise, version is 2 */
|
||||||
|
version = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* build PKCS#7 envelopedData content type, return enveloped size */
|
/* build PKCS#7 envelopedData content type, return enveloped size */
|
||||||
int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
||||||
{
|
{
|
||||||
@@ -6046,6 +6156,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
byte outerContentType[MAX_ALGO_SZ];
|
byte outerContentType[MAX_ALGO_SZ];
|
||||||
byte outerContent[MAX_SEQ_SZ];
|
byte outerContent[MAX_SEQ_SZ];
|
||||||
|
|
||||||
|
int kariVersion;
|
||||||
int envDataSeqSz, verSz;
|
int envDataSeqSz, verSz;
|
||||||
byte envDataSeq[MAX_SEQ_SZ];
|
byte envDataSeq[MAX_SEQ_SZ];
|
||||||
byte ver[MAX_VERSION_SZ];
|
byte ver[MAX_VERSION_SZ];
|
||||||
@@ -6090,16 +6201,6 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
|
|
||||||
outerContentTypeSz = ret;
|
outerContentTypeSz = ret;
|
||||||
|
|
||||||
/* version, defined as 0 in RFC 2315 */
|
|
||||||
#ifdef HAVE_ECC
|
|
||||||
if (pkcs7->publicKeyOID == ECDSAk) {
|
|
||||||
verSz = SetMyVersion(2, ver, 0);
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
verSz = SetMyVersion(0, ver, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* generate random content encryption key */
|
/* generate random content encryption key */
|
||||||
ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz);
|
ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
@@ -6146,6 +6247,15 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
}
|
}
|
||||||
recipSetSz = SetSet(recipSz, recipSet);
|
recipSetSz = SetSet(recipSz, recipSet);
|
||||||
|
|
||||||
|
/* version, defined in Section 6.1 of RFC 5652 */
|
||||||
|
kariVersion = wc_PKCS7_GetCMSVersion(pkcs7, ENVELOPED_DATA);
|
||||||
|
if (kariVersion < 0) {
|
||||||
|
WOLFSSL_MSG("Failed to set CMS EnvelopedData version");
|
||||||
|
return PKCS7_RECIP_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
verSz = SetMyVersion(kariVersion, ver, 0);
|
||||||
|
|
||||||
ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
|
ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -6477,6 +6587,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz,
|
|||||||
pkcs7->stream->expected = encryptedKeySz;
|
pkcs7->stream->expected = encryptedKeySz;
|
||||||
#endif
|
#endif
|
||||||
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_3);
|
wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_3);
|
||||||
|
FALL_THROUGH;
|
||||||
|
|
||||||
case WC_PKCS7_DECRYPT_KTRI_3:
|
case WC_PKCS7_DECRYPT_KTRI_3:
|
||||||
#ifndef NO_PKCS7_STREAM
|
#ifndef NO_PKCS7_STREAM
|
||||||
@@ -7950,9 +8061,11 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in,
|
|||||||
|
|
||||||
if (type == ENVELOPED_DATA) {
|
if (type == ENVELOPED_DATA) {
|
||||||
/* TODO :: make this more accurate */
|
/* TODO :: make this more accurate */
|
||||||
if ((pkcs7->publicKeyOID == RSAk && version != 0)
|
if ((pkcs7->publicKeyOID == RSAk &&
|
||||||
|
(version != 0 && version != 2))
|
||||||
#ifdef HAVE_ECC
|
#ifdef HAVE_ECC
|
||||||
|| (pkcs7->publicKeyOID == ECDSAk && version != 2)
|
|| (pkcs7->publicKeyOID == ECDSAk &&
|
||||||
|
(version != 0 && version != 2 && version != 3))
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
WOLFSSL_MSG("PKCS#7 envelopedData version incorrect");
|
WOLFSSL_MSG("PKCS#7 envelopedData version incorrect");
|
||||||
|
Reference in New Issue
Block a user