From 99ddf65a9642add6fddf75bc6655319fd5328823 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 5 Aug 2019 10:49:15 -0600 Subject: [PATCH 1/5] add decrypt callback to wc_PKCS7_DecodeEnvelopedData --- tests/api.c | 135 +++++++++++++++++++++++++++++++++++++++++- wolfcrypt/src/pkcs7.c | 10 +++- 2 files changed, 142 insertions(+), 3 deletions(-) diff --git a/tests/api.c b/tests/api.c index c677c3502..43f9ca3ae 100644 --- a/tests/api.c +++ b/tests/api.c @@ -16628,6 +16628,108 @@ static void test_wc_PKCS7_VerifySignedData(void) } /* END test_wc_PKCS7_VerifySignedData() */ +#if defined(HAVE_PKCS7) && !defined(NO_AES) && !defined(NO_AES_256) +static const byte defKey[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 +}; +static byte aesHandle[32]; /* simulated hardware key handle */ + +/* return 0 on success */ +static int myDecryptionFunc(PKCS7* pkcs7, int encryptOID, byte* iv, int ivSz, + byte* aad, word32 aadSz, byte* authTag, word32 authTagSz, + byte* in, int inSz, byte* out, void* usrCtx) +{ + int ret; + Aes aes; + + if (usrCtx == NULL) { + /* no simulated handle passed in */ + return -1; + } + + switch (encryptOID) { + case AES256CBCb: + if (ivSz != AES_BLOCK_SIZE) + return BAD_FUNC_ARG; + break; + + default: + WOLFSSL_MSG("Unsupported content cipher type for test"); + return ALGO_ID_E; + }; + + /* simulate using handle to get key */ + ret = wc_AesInit(&aes, HEAP_HINT, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesSetKey(&aes, (byte*)usrCtx, 32, iv, AES_DECRYPTION); + if (ret == 0) + ret = wc_AesCbcDecrypt(&aes, out, in, inSz); + wc_AesFree(&aes); + } + + (void)aad; + (void)aadSz; + (void)authTag; + (void)authTagSz; + (void)pkcs7; + return ret; +} + + +/* returns key size on success */ +static int myCEKwrapFunc(PKCS7* pkcs7, byte* cek, word32 cekSz, byte* keyId, + word32 keyIdSz, byte* orginKey, word32 orginKeySz, + byte* out, word32 outSz, int keyWrapAlgo, int type, int direction) +{ + int ret = -1; + + if (out == NULL) + return BAD_FUNC_ARG; + + if (keyId[0] != 0x00) { + return -1; + } + + if (type != (int)PKCS7_KEKRI) { + return -1; + } + + switch (keyWrapAlgo) { + case AES256_WRAP: + /* simulate setting a handle for later decryption but use key + * as handle in the test case here */ + ret = wc_AesKeyUnWrap(defKey, sizeof(defKey), cek, cekSz, + aesHandle, sizeof(aesHandle), NULL); + if (ret < 0) + return ret; + + ret = wc_PKCS7_SetDecodeEncryptedCtx(pkcs7, (void*)aesHandle); + if (ret < 0) + return ret; + + /* return key size on success */ + return sizeof(defKey); + + default: + WOLFSSL_MSG("Unsupported key wrap algorithm in example"); + return BAD_KEYWRAP_ALG_E; + }; + + (void)cekSz; + (void)cek; + (void)outSz; + (void)keyIdSz; + (void)direction; + (void)orginKey; /* used with KAKRI */ + (void)orginKeySz; + return ret; +} +#endif /* HAVE_PKCS7 && !NO_AES && !NO_AES_256 */ + + /* * Testing wc_PKCS7_EncodeEnvelopedData() */ @@ -16883,10 +16985,39 @@ static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void) AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); pkcs7->privateKey = tmpBytePtr; + wc_PKCS7_Free(pkcs7); + +#if !defined(NO_AES) && !defined(NO_AES_256) + /* test of decrypt callback with KEKRI enveloped data */ + { + int envelopedSz; + const byte keyId[] = { 0x00 }; + + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + pkcs7->content = (byte*)input; + pkcs7->contentSz = (word32)(sizeof(input)/sizeof(char)); + pkcs7->contentOID = DATA; + pkcs7->encryptOID = AES256CBCb; + AssertIntGT(wc_PKCS7_AddRecipient_KEKRI(pkcs7, AES256_WRAP, + (byte*)defKey, sizeof(defKey), (byte*)keyId, + sizeof(keyId), NULL, NULL, 0, NULL, 0, 0), 0); + AssertIntEQ(wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID), 0); + AssertIntGT((envelopedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, output, + (word32)sizeof(output))), 0); + wc_PKCS7_Free(pkcs7); + + /* decode envelopedData */ + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_SetWrapCEKCb(pkcs7, myCEKwrapFunc), 0); + AssertIntEQ(wc_PKCS7_SetDecodeEncryptedCb(pkcs7, myDecryptionFunc), 0); + AssertIntGT((decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, output, + envelopedSz, decoded, sizeof(decoded))), 0); + wc_PKCS7_Free(pkcs7); + } +#endif /* !NO_AES && !NO_AES_256 */ + printf(resultFmt, passed); - - wc_PKCS7_Free(pkcs7); #ifndef NO_RSA if (rsaCert) { XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index b5cc3fae6..21e504e8d 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -9955,10 +9955,18 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, } /* decrypt encryptedContent */ - ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, + if (pkcs7->decryptionCb != NULL) { + ret = pkcs7->decryptionCb(pkcs7, encOID, tmpIv, expBlockSz, + NULL, 0, NULL, 0, encryptedContent, + encryptedContentSz, encryptedContent, + pkcs7->decryptionCtx); + } + else { + ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, tmpIv, expBlockSz, NULL, 0, NULL, 0, encryptedContent, encryptedContentSz, encryptedContent); + } if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); break; From 6054a851ce4d71c28eaec0bbdd1697e58f7d9969 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Fri, 9 Aug 2019 17:38:30 -0600 Subject: [PATCH 2/5] move decrypt content callback function to more generic spot --- wolfcrypt/src/pkcs7.c | 78 +++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 44 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 21e504e8d..5c3289a4b 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -6330,11 +6330,11 @@ static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, } -/* decrypt content using encryptOID algo */ -static int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz, - byte* iv, int ivSz, byte* aad, word32 aadSz, - byte* authTag, word32 authTagSz, byte* in, - int inSz, byte* out) +/* decrypt content using encryptOID algo + * returns 0 on success */ +static int wc_PKCS7_DecryptContent(PKCS7* pkcs7, int encryptOID, byte* key, + int keySz, byte* iv, int ivSz, byte* aad, word32 aadSz, byte* authTag, + word32 authTagSz, byte* in, int inSz, byte* out) { int ret; #ifndef NO_AES @@ -6345,7 +6345,16 @@ static int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz, Des3 des3; #endif - if (key == NULL || iv == NULL || in == NULL || out == NULL) + if (iv == NULL || in == NULL || out == NULL) + return BAD_FUNC_ARG; + + if (pkcs7->decryptionCb != NULL) { + return pkcs7->decryptionCb(pkcs7, encryptOID, iv, ivSz, + aad, aadSz, authTag, authTagSz, in, + inSz, out, pkcs7->decryptionCtx); + } + + if (key == NULL) return BAD_FUNC_ARG; switch (encryptOID) { @@ -6852,23 +6861,22 @@ static int wc_PKCS7_PwriKek_KeyUnWrap(PKCS7* pkcs7, const byte* kek, tmpIv = lastBlock - blockSz; /* decrypt last block */ - ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, tmpIv, blockSz, - NULL, 0, NULL, 0, lastBlock, blockSz, - outTmp + inSz - blockSz); + ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, tmpIv, + blockSz, NULL, 0, NULL, 0, lastBlock, blockSz, + outTmp + inSz - blockSz); if (ret == 0) { /* using last decrypted block as IV, decrypt [0 ... n-1] blocks */ lastBlock = outTmp + inSz - blockSz; - ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, lastBlock, - blockSz, NULL, 0, NULL, 0, (byte*)in, - inSz - blockSz, outTmp); + ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, + lastBlock, blockSz, NULL, 0, NULL, 0, (byte*)in, inSz - blockSz, + outTmp); } if (ret == 0) { /* decrypt using original kek and iv */ - ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, (byte*)iv, - ivSz, NULL, 0, NULL, 0, outTmp, inSz, - outTmp); + ret = wc_PKCS7_DecryptContent(pkcs7, algID, (byte*)kek, kekSz, + (byte*)iv, ivSz, NULL, 0, NULL, 0, outTmp, inSz, outTmp); } if (ret != 0) { @@ -9955,18 +9963,9 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, } /* decrypt encryptedContent */ - if (pkcs7->decryptionCb != NULL) { - ret = pkcs7->decryptionCb(pkcs7, encOID, tmpIv, expBlockSz, - NULL, 0, NULL, 0, encryptedContent, - encryptedContentSz, encryptedContent, - pkcs7->decryptionCtx); - } - else { - ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, - tmpIv, expBlockSz, NULL, 0, NULL, 0, - encryptedContent, encryptedContentSz, - encryptedContent); - } + ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey, + blockKeySz, tmpIv, expBlockSz, NULL, 0, NULL, 0, + encryptedContent, encryptedContentSz, encryptedContent); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); break; @@ -11046,11 +11045,10 @@ authenv_atrbend: #endif /* decrypt encryptedContent */ - ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, - nonce, nonceSz, encodedAttribs, - encodedAttribSz, authTag, authTagSz, - encryptedContent, encryptedContentSz, - encryptedContent); + ret = wc_PKCS7_DecryptContent(pkcs7, encOID, decryptedKey, + blockKeySz, nonce, nonceSz, encodedAttribs, encodedAttribSz, + authTag, authTagSz, encryptedContent, encryptedContentSz, + encryptedContent); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; @@ -11707,18 +11705,10 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, /* decrypt encryptedContent */ if (ret == 0) { - if (pkcs7->decryptionCb != NULL) { - ret = pkcs7->decryptionCb(pkcs7, encOID, tmpIv, expBlockSz, - NULL, 0, NULL, 0, encryptedContent, - encryptedContentSz, encryptedContent, - pkcs7->decryptionCtx); - } - else { - ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey, - pkcs7->encryptionKeySz, tmpIv, expBlockSz, - NULL, 0, NULL, 0, encryptedContent, - encryptedContentSz, encryptedContent); - } + ret = wc_PKCS7_DecryptContent(pkcs7, encOID, + pkcs7->encryptionKey, pkcs7->encryptionKeySz, tmpIv, + expBlockSz, NULL, 0, NULL, 0, encryptedContent, + encryptedContentSz, encryptedContent); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); } From f4d9991e3af4d67268f007dcb5335f482885ec58 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 12 Aug 2019 15:34:20 -0600 Subject: [PATCH 3/5] remove restriction on key wrap type with callback --- wolfcrypt/src/pkcs7.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 5c3289a4b..723f53699 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -9036,11 +9036,18 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, break; #endif default: + WOLFSSL_MSG("AES key wrap algorithm unsupported"); + if (pkcs7->wrapCEKCb) { + WOLFSSL_MSG("Direction not set!"); + break; /* if unwrapping callback is set then do not + * force restriction of supported wrap + * algorithms */ + } + wc_PKCS7_KariFree(kari); #ifdef WOLFSSL_SMALL_STACK XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #endif - WOLFSSL_MSG("AES key wrap algorithm unsupported"); return BAD_KEYWRAP_ALG_E; } From 883d5778a319023600a2fdcfe3b4a2053f497880 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 12 Aug 2019 16:41:35 -0600 Subject: [PATCH 4/5] handle optional parameters with KARI ECC key --- wolfcrypt/src/pkcs7.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 723f53699..6933205f7 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -8054,7 +8054,8 @@ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, byte* pkiMsg, word32 pkiMsgSz, word32* idx) { int ret, length; - word32 keyOID; + word32 keyOID, oidSum = 0; + int curve_id = ECC_CURVE_DEF; if (kari == NULL || pkiMsg == NULL || idx == NULL) return BAD_FUNC_ARG; @@ -8086,6 +8087,15 @@ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, if (keyOID != ECDSAk) return ASN_PARSE_E; + /* optional algorithm parameters */ + ret = GetObjectId(pkiMsg, idx, &oidSum, oidIgnoreType, pkiMsgSz); + if (ret == 0) { + /* get curve id */ + curve_id = wc_ecc_get_oid(oidSum, NULL, 0); + if (curve_id < 0) + return ECC_CURVE_OID_E; + } + /* remove ECPoint BIT STRING */ if ((pkiMsgSz > (*idx + 1)) && (pkiMsg[(*idx)++] != ASN_BIT_STRING)) return ASN_PARSE_E; @@ -8104,7 +8114,8 @@ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, kari->senderKeyInit = 1; /* length-1 for unused bits counter */ - ret = wc_ecc_import_x963(pkiMsg + (*idx), length - 1, kari->senderKey); + ret = wc_ecc_import_x963_ex(pkiMsg + (*idx), length - 1, kari->senderKey, + curve_id); if (ret != 0) { ret = wc_EccPublicKeyDecode(pkiMsg, idx, kari->senderKey, *idx + length - 1); if (ret != 0) From 20d9d5b0da1838e1ed34d38ce5d5ef701717c2ab Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 12 Aug 2019 17:37:09 -0600 Subject: [PATCH 5/5] account for KARI bundle without CERT when callback is set --- wolfcrypt/src/pkcs7.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 6933205f7..3ea6421bf 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -9110,6 +9110,14 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, decryptedKey, *decryptedKeySz, keyWrapOID, (int)PKCS7_KARI, direction); XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + + if (keySz > 0) { + /* If unwrapping was successful then consider recipient + * found. Checking for NULL singleCert to confirm previous + * SID check was not done */ + if (pkcs7->singleCert == NULL) + *recipFound = 1; + } } else { /* create KEK */