mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-03 12:44:45 +02:00
add CMS EnvelopedData PasswordRecipientInfo support
This commit is contained in:
committed by
David Garske
parent
dbb5bb7570
commit
13b30a6a21
1
.gitignore
vendored
1
.gitignore
vendored
@@ -116,6 +116,7 @@ pkcs7signedData_ECDSA_SHA512.der
|
||||
pkcs7envelopedDataDES3.der
|
||||
pkcs7envelopedDataAES128CBC.der
|
||||
pkcs7envelopedDataAES128CBC_KEKRI.der
|
||||
pkcs7envelopedDataAES128CBC_PWRI.der
|
||||
pkcs7envelopedDataAES192CBC.der
|
||||
pkcs7envelopedDataAES256CBC.der
|
||||
diff
|
||||
|
@@ -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 \
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -41,6 +41,9 @@
|
||||
#ifdef HAVE_LIBZ
|
||||
#include <wolfssl/wolfcrypt/compress.h>
|
||||
#endif
|
||||
#ifndef NO_PWDBASED
|
||||
#include <wolfssl/wolfcrypt/pwdbased.h>
|
||||
#endif
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssl/wolfcrypt/misc.h>
|
||||
#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;
|
||||
|
@@ -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 */
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user