From 13b30a6a21eee13b7c5399997e1d0dc332432c36 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 14 Sep 2018 15:41:48 -0600 Subject: [PATCH] add CMS EnvelopedData PasswordRecipientInfo support --- .gitignore | 1 + Makefile.am | 1 + wolfcrypt/src/asn.c | 10 + wolfcrypt/src/pkcs7.c | 740 ++++++++++++++++++++++++++++++++++++-- wolfcrypt/test/test.c | 96 ++++- wolfssl/wolfcrypt/asn.h | 14 +- wolfssl/wolfcrypt/pkcs7.h | 10 +- 7 files changed, 823 insertions(+), 49 deletions(-) diff --git a/.gitignore b/.gitignore index 07184013c..8608049b7 100644 --- a/.gitignore +++ b/.gitignore @@ -116,6 +116,7 @@ pkcs7signedData_ECDSA_SHA512.der pkcs7envelopedDataDES3.der pkcs7envelopedDataAES128CBC.der pkcs7envelopedDataAES128CBC_KEKRI.der +pkcs7envelopedDataAES128CBC_PWRI.der pkcs7envelopedDataAES192CBC.der pkcs7envelopedDataAES256CBC.der diff diff --git a/Makefile.am b/Makefile.am index c91d70032..2b7864979 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,6 +57,7 @@ CLEANFILES+= cert.der \ pkcs7envelopedDataDES3.der \ pkcs7envelopedDataAES128CBC.der \ pkcs7envelopedDataAES128CBC_KEKRI.der \ + pkcs7envelopedDataAES128CBC_PWRI.der \ pkcs7envelopedDataAES192CBC.der \ pkcs7envelopedDataAES256CBC.der \ pkcs7signedData_RSA_SHA.der \ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index e6f5323ad..1ab2059d3 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1242,6 +1242,10 @@ static word32 SetBitString16Bit(word16 val, byte* output) #ifdef WOLFSSL_AES_256 static const byte wrapAes256Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 45}; #endif +#ifdef HAVE_PKCS7 +/* From RFC 3211 */ +static const byte wrapPwriKekOid[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3,9}; +#endif /* cmsKeyAgreeType */ #ifndef NO_SHA @@ -1741,6 +1745,12 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(wrapAes256Oid); break; #endif + #ifdef HAVE_PKCS7 + case PWRI_KEK_WRAP: + oid = wrapPwriKekOid; + *oidSz = sizeof(wrapPwriKekOid); + break; + #endif } break; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 932834a23..1836e4ede 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -41,6 +41,9 @@ #ifdef HAVE_LIBZ #include #endif +#ifndef NO_PWDBASED + #include +#endif #ifdef NO_INLINE #include #else @@ -89,6 +92,13 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) 0x01, 0x09, 0x10, 0x01, 0x09 }; #endif +#ifndef NO_PWDBASED + const byte pwriKek[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x03, 0x09 }; + const byte pbkdf2[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x05, 0x0C }; +#endif + int idSz, idx = 0; word32 typeSz = 0; const byte* typeName = 0; @@ -142,6 +152,18 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) typeName = firmwarePkgData; break; +#ifndef NO_PWDBASED + case PWRI_KEK_WRAP: + typeSz = sizeof(pwriKek); + typeName = pwriKek; + break; + + case PBKDF2_OID: + typeSz = sizeof(pbkdf2); + typeName = pbkdf2; + break; +#endif + default: WOLFSSL_MSG("Unknown PKCS#7 Type"); return 0; @@ -351,8 +373,6 @@ static int wc_PKCS7_GetRecipientListSize(PKCS7* pkcs7) tmp = pkcs7->recipList; while (tmp != NULL) { - printf("DEBUG: tmp = %p\n", tmp); - printf("DEBUG: tmp->recipSz = %d\n", tmp->recipSz); totalSz += tmp->recipSz; tmp = tmp->next; } @@ -2859,31 +2879,6 @@ static int PKCS7_GenerateContentEncryptionKey(PKCS7* pkcs7, word32 len) } -#ifdef HAVE_ECC - -/* KARI == KeyAgreeRecipientInfo (key agreement) */ -typedef struct WC_PKCS7_KARI { - DecodedCert* decoded; /* decoded recip cert */ - void* heap; /* user heap, points to PKCS7->heap */ - int devId; /* device ID for HW based private key */ - ecc_key* recipKey; /* recip key (pub | priv) */ - ecc_key* senderKey; /* sender key (pub | priv) */ - byte* senderKeyExport; /* sender ephemeral key DER */ - byte* kek; /* key encryption key */ - byte* ukm; /* OPTIONAL user keying material */ - byte* sharedInfo; /* ECC-CMS-SharedInfo ASN.1 encoded blob */ - word32 senderKeyExportSz; /* size of sender ephemeral key DER */ - word32 kekSz; /* size of key encryption key */ - word32 ukmSz; /* size of user keying material */ - word32 sharedInfoSz; /* size of ECC-CMS-SharedInfo encoded */ - byte ukmOwner; /* do we own ukm buffer? 1:yes, 0:no */ - byte direction; /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */ - byte decodedInit : 1; /* indicates decoded was initialized */ - byte recipKeyInit : 1; /* indicates recipKey was initialized */ - byte senderKeyInit : 1; /* indicates senderKey was initialized */ -} WC_PKCS7_KARI; - - /* wrap CEK (content encryption key) with KEK, 0 on success, < 0 on error */ static int wc_PKCS7_KeyWrap(byte* cek, word32 cekSz, byte* kek, word32 kekSz, byte* out, word32 outSz, @@ -2939,6 +2934,31 @@ static int wc_PKCS7_KeyWrap(byte* cek, word32 cekSz, byte* kek, } +#ifdef HAVE_ECC + +/* KARI == KeyAgreeRecipientInfo (key agreement) */ +typedef struct WC_PKCS7_KARI { + DecodedCert* decoded; /* decoded recip cert */ + void* heap; /* user heap, points to PKCS7->heap */ + int devId; /* device ID for HW based private key */ + ecc_key* recipKey; /* recip key (pub | priv) */ + ecc_key* senderKey; /* sender key (pub | priv) */ + byte* senderKeyExport; /* sender ephemeral key DER */ + byte* kek; /* key encryption key */ + byte* ukm; /* OPTIONAL user keying material */ + byte* sharedInfo; /* ECC-CMS-SharedInfo ASN.1 encoded blob */ + word32 senderKeyExportSz; /* size of sender ephemeral key DER */ + word32 kekSz; /* size of key encryption key */ + word32 ukmSz; /* size of user keying material */ + word32 sharedInfoSz; /* size of ECC-CMS-SharedInfo encoded */ + byte ukmOwner; /* do we own ukm buffer? 1:yes, 0:no */ + byte direction; /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */ + byte decodedInit : 1; /* indicates decoded was initialized */ + byte recipKeyInit : 1; /* indicates recipKey was initialized */ + byte senderKeyInit : 1; /* indicates senderKey was initialized */ +} WC_PKCS7_KARI; + + /* allocate and create new WC_PKCS7_KARI struct, * returns struct pointer on success, NULL on failure */ static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) @@ -4321,6 +4341,477 @@ int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, } +#ifndef NO_PWDBASED + + +static int wc_PKCS7_GenerateKEK_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, + byte* salt, word32 saltSz, int kdfOID, + int prfOID, int iterations, byte* out, + word32 outSz) +{ + int ret; + + if (pkcs7 == NULL || passwd == NULL || salt == NULL || out == NULL) + return BAD_FUNC_ARG; + + switch (kdfOID) { + + case PBKDF2_OID: + + ret = wc_PBKDF2(out, passwd, pLen, salt, saltSz, iterations, + outSz, prfOID); + if (ret != 0) { + return ret; + } + + break; + + default: + WOLFSSL_MSG("Unsupported KDF OID"); + return PKCS7_OID_E; + } + + return 0; +} + + +/* RFC3211 (Section 2.3.1) key wrap algorithm (id-alg-PWRI-KEK). + * + * Returns output size on success, negative upon error */ +static int wc_PKCS7_PwriKek_KeyWrap(PKCS7* pkcs7, const byte* kek, word32 kekSz, + const byte* cek, word32 cekSz, + byte* out, word32 *outSz, + const byte* iv, word32 ivSz, int algID) +{ + WC_RNG rng; + int blockSz, outLen, ret; + word32 padSz; + byte* lastBlock; + + if (kek == NULL || cek == NULL || iv == NULL || outSz == NULL) + return BAD_FUNC_ARG; + + /* get encryption algorithm block size */ + blockSz = wc_PKCS7_GetOIDBlockSize(algID); + if (blockSz < 0) + return blockSz; + + /* get pad bytes needed to block boundary */ + padSz = blockSz - ((4 + cekSz) % blockSz); + outLen = 4 + cekSz + padSz; + + /* must be at least two blocks long */ + if (outLen < 2 * blockSz) + padSz += blockSz; + + /* if user set out to NULL, give back required length */ + if (out == NULL) { + *outSz = outLen; + return LENGTH_ONLY_E; + } + + /* verify output buffer is large enough */ + if (*outSz < (word32)outLen) + return BUFFER_E; + + out[0] = cekSz; + out[1] = ~cek[0]; + out[2] = ~cek[1]; + out[3] = ~cek[2]; + XMEMCPY(out + 4, cek, cekSz); + + /* random padding of size padSz */ + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) + return ret; + + ret = wc_RNG_GenerateBlock(&rng, out + 4 + cekSz, padSz); + + if (ret == 0) { + /* encrypt, normal */ + ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, (byte*)iv, + ivSz, out, outLen, out); + } + + if (ret == 0) { + /* encrypt again, using last ciphertext block as IV */ + lastBlock = out + (((outLen / blockSz) - 1) * blockSz); + ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, lastBlock, + blockSz, out, outLen, out); + } + + if (ret == 0) { + *outSz = outLen; + } else { + outLen = ret; + } + + wc_FreeRng(&rng); + + return outLen; +} + + +/* RFC3211 (Section 2.3.2) key unwrap algorithm (id-alg-PWRI-KEK). + * + * Returns cek size on success, negative upon error */ +static int wc_PKCS7_PwriKek_KeyUnWrap(PKCS7* pkcs7, const byte* kek, + word32 kekSz, const byte* in, word32 inSz, + byte* out, word32 outSz, const byte* iv, + word32 ivSz, int algID) +{ + int blockSz, cekLen, ret; + byte* tmpIv = NULL; + byte* lastBlock = NULL; + byte* outTmp = NULL; + + if (pkcs7 == NULL || kek == NULL || in == NULL || + out == NULL || iv == NULL) { + return BAD_FUNC_ARG; + } + + outTmp = (byte*)XMALLOC(inSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (outTmp == NULL) + return MEMORY_E; + + /* get encryption algorithm block size */ + blockSz = wc_PKCS7_GetOIDBlockSize(algID); + if (blockSz < 0) { + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return blockSz; + } + + /* input needs to be blockSz multiple and at least 2 * blockSz */ + if (((inSz % blockSz) != 0) || (inSz < (2 * (word32)blockSz))) { + WOLFSSL_MSG("PWRI-KEK unwrap input must of block size and >= 2 " + "times block size"); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } + + /* use block out[n-1] as IV to decrypt block out[n] */ + lastBlock = (byte*)in + inSz - blockSz; + tmpIv = lastBlock - blockSz; + + /* decrypt last block */ + ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, tmpIv, blockSz, + 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, (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, outTmp, inSz, outTmp); + } + + if (ret != 0) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + cekLen = outTmp[0]; + + /* verify length */ + if ((word32)cekLen > inSz) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } + + /* verify check bytes */ + if ((outTmp[1] ^ outTmp[4]) != 0xFF || + (outTmp[2] ^ outTmp[5]) != 0xFF || + (outTmp[3] ^ outTmp[6]) != 0xFF) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } + + if (outSz < (word32)cekLen) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BUFFER_E; + } + + XMEMCPY(out, outTmp + 4, outTmp[0]); + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return cekLen; +} + + +/* Encode and add CMS EnvelopedData PWRI (PasswordRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Return 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, + byte* salt, word32 saltSz, int kdfOID, + int hashOID, int iterations, int encryptOID) +{ + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + /* PasswordRecipientInfo */ + byte recipSeq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + word32 recipSeqSz, verSz; + + /* KeyDerivationAlgorithmIdentifier */ + byte kdfAlgoIdSeq[MAX_SEQ_SZ]; + byte kdfAlgoId[MAX_OID_SZ]; + byte kdfParamsSeq[MAX_SEQ_SZ]; /* PBKDF2-params */ + byte kdfSaltOctetStr[MAX_OCTET_STR_SZ]; /* salt OCTET STRING */ + byte kdfIterations[MAX_VERSION_SZ]; + word32 kdfAlgoIdSeqSz, kdfAlgoIdSz; + word32 kdfParamsSeqSz, kdfSaltOctetStrSz, kdfIterationsSz; + /* OPTIONAL: keyLength, not supported yet */ + /* OPTIONAL: prf AlgorithIdentifier, not supported yet */ + + /* KeyEncryptionAlgorithmIdentifier */ + byte keyEncAlgoIdSeq[MAX_SEQ_SZ]; + byte keyEncAlgoId[MAX_OID_SZ]; /* id-alg-PWRI-KEK */ + byte pwriEncAlgoId[MAX_ALGO_SZ]; + byte ivOctetString[MAX_OCTET_STR_SZ]; + word32 keyEncAlgoIdSeqSz, keyEncAlgoIdSz; + word32 pwriEncAlgoIdSz, ivOctetStringSz; + + /* EncryptedKey */ + byte encKeyOctetStr[MAX_OCTET_STR_SZ]; + word32 encKeyOctetStrSz; + + byte tmpIv[MAX_CONTENT_IV_SIZE]; + byte* encryptedKey = NULL; + byte* kek = NULL; + + int blockKeySz = 0, ret = 0; + word32 idx, totalSz = 0, encryptedKeySz; + + if (pkcs7 == NULL || passwd == NULL || pLen == 0 || + salt == NULL || saltSz == 0) { + return BAD_FUNC_ARG; + } + + /* get content-encryption key size, based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(encryptOID); + if (blockKeySz < 0) + return blockKeySz; + + /* generate random CEK */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) + return ret; + + /* generate random IV */ + ret = wc_PKCS7_GenerateIV(pkcs7, NULL, tmpIv, blockKeySz); + if (ret != 0) + return ret; + + /* allocate memory for RecipientInfo, KEK, encrypted key */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (recip == NULL) + return MEMORY_E; + + kek = (byte*)XMALLOC(blockKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (kek == NULL) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (encryptedKey == NULL) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + XMEMSET(kek, 0, blockKeySz); + XMEMSET(encryptedKey, 0, encryptedKeySz); + + /* generate KEK: expand password into KEK */ + ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, passwd, pLen, salt, saltSz, + kdfOID, hashOID, iterations, kek, + blockKeySz); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* generate encrypted key: encrypt CEK with KEK */ + ret = wc_PKCS7_PwriKek_KeyWrap(pkcs7, kek, blockKeySz, pkcs7->cek, + pkcs7->cekSz, encryptedKey, &encryptedKeySz, + tmpIv, blockKeySz, pkcs7->encryptOID); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + encryptedKeySz = ret; + + /* put together encrypted key OCTET STRING */ + encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); + totalSz += (encKeyOctetStrSz + encryptedKeySz); + + /* put together IV OCTET STRING */ + ivOctetStringSz = SetOctetString(blockKeySz, ivOctetString); + totalSz += (ivOctetStringSz + blockKeySz); + + /* set PWRIAlgorithms AlgorithmIdentifier, adding (ivOctetStringSz + + blockKeySz) for IV OCTET STRING */ + pwriEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, pwriEncAlgoId, + oidBlkType, ivOctetStringSz + blockKeySz); + totalSz += pwriEncAlgoIdSz; + + /* set KeyEncryptionAlgorithms OID */ + ret = wc_SetContentType(PWRI_KEK_WRAP, keyEncAlgoId, sizeof(keyEncAlgoId)); + if (ret <= 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + keyEncAlgoIdSz = ret; + totalSz += keyEncAlgoIdSz; + + /* KeyEncryptionAlgorithm SEQ */ + keyEncAlgoIdSeqSz = SetSequence(keyEncAlgoIdSz + pwriEncAlgoIdSz + + ivOctetStringSz + blockKeySz, + keyEncAlgoIdSeq); + totalSz += keyEncAlgoIdSeqSz; + + /* set KDF salt */ + kdfSaltOctetStrSz = SetOctetString(saltSz, kdfSaltOctetStr); + totalSz += (kdfSaltOctetStrSz + saltSz); + + /* set KDF iteration count */ + kdfIterationsSz = SetMyVersion(iterations, kdfIterations, 0); + totalSz += kdfIterationsSz; + + /* set KDF params SEQ */ + kdfParamsSeqSz = SetSequence(kdfSaltOctetStrSz + saltSz + kdfIterationsSz, + kdfParamsSeq); + totalSz += kdfParamsSeqSz; + + /* set KDF algo OID */ + ret = wc_SetContentType(kdfOID, kdfAlgoId, sizeof(kdfAlgoId)); + if (ret <= 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + kdfAlgoIdSz = ret; + totalSz += kdfAlgoIdSz; + + /* set KeyDerivationAlgorithmIdentifier EXPLICIT [0] SEQ */ + kdfAlgoIdSeqSz = SetExplicit(0, kdfAlgoIdSz + kdfParamsSeqSz + + kdfSaltOctetStrSz + saltSz + kdfIterationsSz, + kdfAlgoIdSeq); + totalSz += kdfAlgoIdSeqSz; + + /* set PasswordRecipientInfo CMSVersion, MUST be 0 */ + verSz = SetMyVersion(0, ver, 0); + totalSz += verSz; + + /* set PasswordRecipientInfo SEQ */ + recipSeqSz = SetImplicit(ASN_SEQUENCE, 3, totalSz, recipSeq); + totalSz += recipSeqSz; + + if (totalSz > MAX_RECIP_SZ) { + WOLFSSL_MSG("CMS Recipient output buffer too small"); + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + idx = 0; + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + XMEMCPY(recip->recip + idx, ver, verSz); + idx += verSz; + XMEMCPY(recip->recip + idx, kdfAlgoIdSeq, kdfAlgoIdSeqSz); + idx += kdfAlgoIdSeqSz; + XMEMCPY(recip->recip + idx, kdfAlgoId, kdfAlgoIdSz); + idx += kdfAlgoIdSz; + XMEMCPY(recip->recip + idx, kdfParamsSeq, kdfParamsSeqSz); + idx += kdfParamsSeqSz; + XMEMCPY(recip->recip + idx, kdfSaltOctetStr, kdfSaltOctetStrSz); + idx += kdfSaltOctetStrSz; + XMEMCPY(recip->recip + idx, salt, saltSz); + idx += saltSz; + XMEMCPY(recip->recip + idx, kdfIterations, kdfIterationsSz); + idx += kdfIterationsSz; + XMEMCPY(recip->recip + idx, keyEncAlgoIdSeq, keyEncAlgoIdSeqSz); + idx += keyEncAlgoIdSeqSz; + XMEMCPY(recip->recip + idx, keyEncAlgoId, keyEncAlgoIdSz); + idx += keyEncAlgoIdSz; + XMEMCPY(recip->recip + idx, pwriEncAlgoId, pwriEncAlgoIdSz); + idx += pwriEncAlgoIdSz; + XMEMCPY(recip->recip + idx, ivOctetString, ivOctetStringSz); + idx += ivOctetStringSz; + XMEMCPY(recip->recip + idx, tmpIv, blockKeySz); + idx += blockKeySz; + XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); + idx += encKeyOctetStrSz; + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; + + ForceZero(kek, blockKeySz); + ForceZero(encryptedKey, encryptedKeySz); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + /* store recipient size */ + recip->recipSz = idx; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + return idx; +} + +/* Import password and KDF settings into a PKCS7 structure. Used for setting + * the password info for decryption a EnvelopedData PWRI RecipientInfo. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen) +{ + if (pkcs7 == NULL || passwd == NULL || pLen == 0) + return BAD_FUNC_ARG; + + pkcs7->pass = passwd; + pkcs7->passSz = pLen; + + return 0; +} + +#endif /* NO_PWDBASED */ + + /* Encode and add CMS EnvelopedData KEKRI (KEKRecipientInfo) RecipientInfo * to CMS/PKCS#7 EnvelopedData structure. * @@ -4573,7 +5064,6 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) verSz = SetMyVersion(0, ver, 0); } - /* generate random content encryption key */ ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); if (ret != 0) { @@ -5266,6 +5756,177 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, #endif /* HAVE_ECC */ +/* decode ASN.1 PasswordRecipientInfo (pwri), return 0 on success, + * < 0 on error */ +static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + byte* salt; + byte* cek; + byte* kek; + + byte tmpIv[MAX_CONTENT_IV_SIZE]; + + int ret, length, saltSz, iterations, blockSz; + int hashOID = WC_SHA; /* default to SHA1 */ + word32 kdfAlgoId, pwriEncAlgoId, keyEncAlgoId, cekSz; + + /* remove KeyDerivationAlgorithmIdentifier */ + if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KeyDerivationAlgorithmIdentifier */ + if (wc_GetContentType(pkiMsg, idx, &kdfAlgoId, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KDF params SEQ */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KDF salt OCTET STRING */ + if ( (pkiMsgSz > ((*idx) + 1)) && + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &saltSz, pkiMsgSz) < 0) + return ASN_PARSE_E; + + salt = (byte*)XMALLOC(saltSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (salt == NULL) + return MEMORY_E; + + XMEMCPY(salt, pkiMsg + (*idx), saltSz); + *idx += saltSz; + + /* get KDF iterations */ + if (GetMyVersion(pkiMsg, idx, &iterations, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get KeyEncAlgoId SEQ */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get KeyEncAlgoId */ + if (wc_GetContentType(pkiMsg, idx, &keyEncAlgoId, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get pwriEncAlgoId */ + if (GetAlgoId(pkiMsg, idx, &pwriEncAlgoId, oidBlkType, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + blockSz = wc_PKCS7_GetOIDBlockSize(pwriEncAlgoId); + if (blockSz < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockSz; + } + + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ + if ( (pkiMsgSz > ((*idx) + 1)) && + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (length != blockSz) { + WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + XMEMCPY(tmpIv, pkiMsg + (*idx), length); + *idx += length; + + /* get EncryptedKey */ + if ( (pkiMsgSz < ((*idx) + 1)) || + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* allocate temporary space for decrypted key */ + cekSz = length; + cek = (byte*)XMALLOC(cekSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cek == NULL) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* generate KEK */ + kek = (byte*)XMALLOC(blockSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (kek == NULL) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, pkcs7->pass, pkcs7->passSz, + salt, saltSz, kdfAlgoId, hashOID, + iterations, kek, blockSz); + if (ret < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* decrypt CEK with KEK */ + ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, blockSz, pkiMsg + (*idx), + length, cek, cekSz, tmpIv, + blockSz, pwriEncAlgoId); + if (ret < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + cekSz = ret; + + if (*decryptedKeySz < cekSz) { + WOLFSSL_MSG("Decrypted key buffer too small for CEK"); + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + XMEMCPY(decryptedKey, cek, cekSz); + *decryptedKeySz = cekSz; + + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + *idx += length; + + return 0; +} + + /* decode ASN.1 KEKRecipientInfo (kekri), return 0 on success, * < 0 on error */ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, @@ -5602,6 +6263,29 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, if (ret != 0) return ret; + /* pwri is IMPLICIT[3] */ + } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | + ASN_CONTEXT_SPECIFIC | 3)) { + (*idx)++; + + if (GetLength(pkiMsg, idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { + *idx = savedIdx; + break; + } + + if (version != 0) + return ASN_VERSION_E; + + /* found pwri */ + ret = wc_PKCS7_DecryptPwri(pkcs7, pkiMsg, pkiMsgSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + } else { /* failed to find RecipientInfo, restore idx and continue */ *idx = savedIdx; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index b494c945b..3da92d000 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -18954,6 +18954,15 @@ typedef struct { byte* otherAttr; /* OPTIONAL, other attribute, ASN.1 encoded */ word32 otherAttrSz; /* size of otherAttr, bytes */ + /* PWRI specific */ + char* password; + word32 passwordSz; + byte* salt; + word32 saltSz; + int kdfOID; + int hashOID; + int kdfIterations; + const char* outFileName; } pkcs7EnvelopedVector; @@ -18998,6 +19007,14 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, }; #endif +#if !defined(NO_PWDBASED) + char password[] = "password"; + + byte salt[] = { + 0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12 + }; +#endif + const pkcs7EnvelopedVector testVectors[] = { /* key transport key encryption technique */ @@ -19005,24 +19022,24 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #ifndef NO_DES3 {data, (word32)sizeof(data), DATA, DES3b, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, "pkcs7envelopedDataDES3.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataDES3.der"}, #endif #ifndef NO_AES #ifdef WOLFSSL_AES_128 {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, "pkcs7envelopedDataAES128CBC.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES128CBC.der"}, #endif #ifdef WOLFSSL_AES_192 {data, (word32)sizeof(data), DATA, AES192CBCb, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, "pkcs7envelopedDataAES192CBC.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES192CBC.der"}, #endif #ifdef WOLFSSL_AES_256 {data, (word32)sizeof(data), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, "pkcs7envelopedDataAES256CBC.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC.der"}, #endif #endif /* NO_AES */ #endif @@ -19034,6 +19051,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, dhSinglePass_stdDH_sha1kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, + NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der"}, #endif @@ -19041,6 +19059,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, + NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der"}, #endif /* NO_SHA256 && WOLFSSL_AES_256 */ @@ -19048,13 +19067,14 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, + NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der"}, /* with optional user keying material (ukm) */ {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz, optionalUkm, sizeof(optionalUkm), NULL, 0, - NULL, 0, NULL, NULL, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der"}, #endif /* WOLFSSL_SHA512 && WOLFSSL_AES_256 */ #endif /* NO_AES */ @@ -19066,7 +19086,18 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, 0, NULL, 0, NULL, 0, NULL, 0, secretKey, sizeof(secretKey), secretKeyId, sizeof(secretKeyId), NULL, NULL, 0, NULL, 0, - "pkcs7envelopedDataAES128CBC_KEKRI.der"}, + NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES128CBC_KEKRI.der"}, + #endif +#endif + + /* pwri (PasswordRecipientInfo) recipient types */ +#if !defined(NO_PWDBASED) && !defined(NO_AES) + #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) + {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, + NULL, 0, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, password, (word32)XSTRLEN(password), + salt, sizeof(salt), PBKDF2_OID, WC_SHA, 5, + "pkcs7envelopedDataAES128CBC_PWRI.der"}, #endif #endif }; @@ -19105,6 +19136,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, testVectors[i].timePtr, testVectors[i].otherAttrOID, testVectors[i].otherAttrOIDSz, testVectors[i].otherAttr, testVectors[i].otherAttrSz); + if (ret < 0) { wc_PKCS7_Free(pkcs7); return -9216; @@ -19113,11 +19145,49 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, /* set key, for decryption */ ret = wc_PKCS7_SetKey(pkcs7, testVectors[i].secretKey, testVectors[i].secretKeySz); + if (ret != 0) { wc_PKCS7_Free(pkcs7); return -9217; } + } else if (testVectors[i].password != NULL) { + /* PWRI recipient type */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -9218; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + + ret = wc_PKCS7_AddRecipient_PWRI(pkcs7, + (byte*)testVectors[i].password, + testVectors[i].passwordSz, testVectors[i].salt, + testVectors[i].saltSz, testVectors[i].kdfOID, + testVectors[i].hashOID, testVectors[i].kdfIterations, + testVectors[i].encryptOID); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -9219; + } + + /* set password, for decryption */ + ret = wc_PKCS7_SetPassword(pkcs7, (byte*)testVectors[i].password, + testVectors[i].passwordSz); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -9220; + } + + } else { /* KTRI or KARI recipient types */ @@ -19125,7 +19195,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, (word32)testVectors[i].certSz); if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9218; + return -9221; } pkcs7->keyWrapOID = testVectors[i].keyWrapOID; @@ -19144,24 +19214,22 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, envelopedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, enveloped, sizeof(enveloped)); if (envelopedSz <= 0) { - printf("DEBUG: i = %d, envelopedSz = %d\n", i, envelopedSz); wc_PKCS7_Free(pkcs7); - return -9219; + return -9222; } /* decode envelopedData */ - printf("CHRIS: Trying to decode: %s\n", testVectors[i].outFileName); decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, enveloped, envelopedSz, decoded, sizeof(decoded)); if (decodedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9220; + return -9223; } /* test decode result */ if (XMEMCMP(decoded, data, sizeof(data)) != 0){ wc_PKCS7_Free(pkcs7); - return -9221; + return -9224; } (void)decoded; (void)decodedSz; @@ -19171,14 +19239,14 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7File = fopen(testVectors[i].outFileName, "wb"); if (!pkcs7File) { wc_PKCS7_Free(pkcs7); - return -9222; + return -9225; } ret = (int)fwrite(enveloped, 1, envelopedSz, pkcs7File); fclose(pkcs7File); if (ret != envelopedSz) { wc_PKCS7_Free(pkcs7); - return -9223; + return -9226; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 17f6239e1..20c986dcf 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -377,19 +377,22 @@ enum Key_Sum { }; -#ifndef NO_AES +#if !defined(NO_AES) || defined(HAVE_PKCS7) enum KeyWrap_Sum { #ifdef WOLFSSL_AES_128 - AES128_WRAP = 417, + AES128_WRAP = 417, #endif #ifdef WOLFSSL_AES_192 - AES192_WRAP = 437, + AES192_WRAP = 437, #endif #ifdef WOLFSSL_AES_256 - AES256_WRAP = 457 + AES256_WRAP = 457, +#endif +#ifdef HAVE_PKCS7 + PWRI_KEK_WRAP = 680 /*id-alg-PWRI-KEK, 1.2.840.113549.1.9.16.3.9 */ #endif }; -#endif /* !NO_AES */ +#endif /* !NO_AES || PKCS7 */ enum Key_Agree { dhSinglePass_stdDH_sha1kdf_scheme = 464, @@ -495,7 +498,6 @@ enum CompressAlg_Sum { }; #endif - enum VerifyType { NO_VERIFY = 0, VERIFY = 1, diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index daf36cd8c..ee1ea015d 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -177,6 +177,8 @@ typedef struct PKCS7 { Pkcs7EncodedRecip* recipList; /* recipients list */ byte* cek; /* content encryption key, random, dynamic */ word32 cekSz; /* size of cek, bytes */ + byte* pass; /* password, for PWRI decryption */ + word32 passSz; /* size of pass, bytes */ /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ } PKCS7; @@ -228,9 +230,15 @@ WOLFSSL_API int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, void* timePtr, byte* otherOID, word32 otherOIDSz, byte* other, word32 otherSz); +WOLFSSL_API int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, + word32 pLen, byte* salt, + word32 saltSz, int kdfOID, + int prfOID, int iterations, + int encryptOID); WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz); -WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz); +WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz); +WOLFSSL_API int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen); WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz);