mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-04 21:24:43 +02:00
add PKCS7_EncodeEnvelopeData()
This commit is contained in:
@@ -106,22 +106,6 @@ CYASSL_LOCAL int SetContentType(int pkcs7TypeOID, byte* output)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create PKCS#7 envelopedData structure */
|
|
||||||
int Pkcs7_encrypt(const byte* certs, word32 certSz, byte* data, word32 dataSz,
|
|
||||||
int cipher, byte* out, word32* outSz, word32 flags)
|
|
||||||
{
|
|
||||||
(void)certs;
|
|
||||||
(void)certSz;
|
|
||||||
(void)data;
|
|
||||||
(void)dataSz;
|
|
||||||
(void)cipher;
|
|
||||||
(void)out;
|
|
||||||
(void)outSz;
|
|
||||||
(void)flags;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz)
|
int PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz)
|
||||||
{
|
{
|
||||||
@@ -172,12 +156,297 @@ int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* create ASN.1 fomatted RecipientInfo structure, returns sequence size */
|
||||||
|
CYASSL_LOCAL int CreateRecipientInfo(const byte* cert, word32 certSz,
|
||||||
|
int keyEncAlgo, int blockKeySz,
|
||||||
|
RNG* rng, byte* contentKeyPlain,
|
||||||
|
byte* contentKeyEnc,
|
||||||
|
int* keyEncSz, byte* out, word32 outSz)
|
||||||
|
{
|
||||||
|
word32 idx = 0;
|
||||||
|
int ret = 0, totalSz = 0;
|
||||||
|
int verSz, issuerSz, snSz, keyEncAlgSz;
|
||||||
|
int issuerSeqSz, recipSeqSz, issuerSerialSeqSz;
|
||||||
|
int encKeyOctetStrSz;
|
||||||
|
|
||||||
|
byte ver[MAX_VERSION_SZ];
|
||||||
|
byte serial[MAX_SN_SZ];
|
||||||
|
byte issuerSerialSeq[MAX_SEQ_SZ];
|
||||||
|
byte recipSeq[MAX_SEQ_SZ];
|
||||||
|
byte issuerSeq[MAX_SEQ_SZ];
|
||||||
|
byte keyAlgArray[MAX_ALGO_SZ];
|
||||||
|
byte encKeyOctetStr[MAX_OCTET_STR_SZ];
|
||||||
|
|
||||||
|
RsaKey pubKey;
|
||||||
|
DecodedCert decoded;
|
||||||
|
|
||||||
|
InitDecodedCert(&decoded, (byte*)cert, certSz, 0);
|
||||||
|
ret = ParseCert(&decoded, CA_TYPE, NO_VERIFY, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
FreeDecodedCert(&decoded);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* version */
|
||||||
|
verSz = SetMyVersion(0, ver, 0);
|
||||||
|
|
||||||
|
/* IssuerAndSerialNumber */
|
||||||
|
if (decoded.issuerRaw == NULL || decoded.issuerRawLen == 0) {
|
||||||
|
CYASSL_MSG("DecodedCert lacks raw issuer pointer and length");
|
||||||
|
FreeDecodedCert(&decoded);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
issuerSz = decoded.issuerRawLen;
|
||||||
|
issuerSeqSz = SetSequence(issuerSz, issuerSeq);
|
||||||
|
|
||||||
|
if (decoded.serial == NULL || decoded.serialSz == 0) {
|
||||||
|
CYASSL_MSG("DecodedCert missing serial number");
|
||||||
|
FreeDecodedCert(&decoded);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
snSz = SetSerialNumber(decoded.serial, decoded.serialSz, serial);
|
||||||
|
|
||||||
|
issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz,
|
||||||
|
issuerSerialSeq);
|
||||||
|
|
||||||
|
/* KeyEncryptionAlgorithmIdentifier, only support RSA now */
|
||||||
|
if (keyEncAlgo != RSAk)
|
||||||
|
return ALGO_ID_E;
|
||||||
|
|
||||||
|
keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, keyType, 0);
|
||||||
|
|
||||||
|
/* EncryptedKey */
|
||||||
|
InitRsaKey(&pubKey, 0);
|
||||||
|
if (RsaPublicKeyDecode(decoded.publicKey, &idx, &pubKey,
|
||||||
|
decoded.pubKeySize) < 0) {
|
||||||
|
CYASSL_MSG("ASN RSA key decode error");
|
||||||
|
return PUBLIC_KEY_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
*keyEncSz = RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc,
|
||||||
|
MAX_ENCRYPTED_KEY_SZ, &pubKey, rng);
|
||||||
|
if (*keyEncSz < 0) {
|
||||||
|
CYASSL_MSG("RSA Public Encrypt failed");
|
||||||
|
return *keyEncSz;
|
||||||
|
}
|
||||||
|
|
||||||
|
encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr);
|
||||||
|
|
||||||
|
/* RecipientInfo */
|
||||||
|
recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz +
|
||||||
|
issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz +
|
||||||
|
*keyEncSz, recipSeq);
|
||||||
|
|
||||||
|
if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz +
|
||||||
|
keyEncAlgSz + encKeyOctetStrSz + *keyEncSz > (int)outSz) {
|
||||||
|
CYASSL_MSG("RecipientInfo output buffer too small");
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMCPY(out + totalSz, recipSeq, recipSeqSz);
|
||||||
|
totalSz += recipSeqSz;
|
||||||
|
XMEMCPY(out + totalSz, ver, verSz);
|
||||||
|
totalSz += verSz;
|
||||||
|
XMEMCPY(out + totalSz, issuerSerialSeq, issuerSerialSeqSz);
|
||||||
|
totalSz += issuerSerialSeqSz;
|
||||||
|
XMEMCPY(out + totalSz, issuerSeq, issuerSeqSz);
|
||||||
|
totalSz += issuerSeqSz;
|
||||||
|
XMEMCPY(out + totalSz, decoded.issuerRaw, issuerSz);
|
||||||
|
totalSz += issuerSz;
|
||||||
|
XMEMCPY(out + totalSz, serial, snSz);
|
||||||
|
totalSz += snSz;
|
||||||
|
XMEMCPY(out + totalSz, keyAlgArray, keyEncAlgSz);
|
||||||
|
totalSz += keyEncAlgSz;
|
||||||
|
XMEMCPY(out + totalSz, encKeyOctetStr, encKeyOctetStrSz);
|
||||||
|
totalSz += encKeyOctetStrSz;
|
||||||
|
XMEMCPY(out + totalSz, contentKeyEnc, *keyEncSz);
|
||||||
|
totalSz += *keyEncSz;
|
||||||
|
|
||||||
|
FreeDecodedCert(&decoded);
|
||||||
|
|
||||||
|
return totalSz;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int PKCS7_EncodeEnvelopeData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
int PKCS7_EncodeEnvelopeData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
||||||
{
|
{
|
||||||
(void)pkcs7;
|
int i, idx = 0;
|
||||||
(void)output;
|
int totalSz = 0, padSz = 0, desOutSz = 0;
|
||||||
(void)outputSz;
|
|
||||||
return 0;
|
int contentInfoSeqSz, outerContentTypeSz, outerContentSz;
|
||||||
|
byte contentInfoSeq[MAX_SEQ_SZ];
|
||||||
|
byte outerContentType[MAX_ALGO_SZ];
|
||||||
|
byte outerContent[MAX_SEQ_SZ];
|
||||||
|
|
||||||
|
int envDataSeqSz, verSz;
|
||||||
|
byte envDataSeq[MAX_SEQ_SZ];
|
||||||
|
byte ver[MAX_VERSION_SZ];
|
||||||
|
|
||||||
|
RNG rng;
|
||||||
|
int contentKeyEncSz, blockKeySz;
|
||||||
|
int dynamicFlag = 0;
|
||||||
|
byte contentKeyPlain[MAX_CONTENT_KEY_LEN];
|
||||||
|
byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ];
|
||||||
|
byte* plain;
|
||||||
|
byte* encryptedContent;
|
||||||
|
|
||||||
|
int recipSz, recipSetSz;
|
||||||
|
byte recip[MAX_RECIP_SZ];
|
||||||
|
byte recipSet[MAX_SET_SZ];
|
||||||
|
|
||||||
|
int encContentOctetSz, encContentSeqSz, contentTypeSz, contentEncAlgoSz;
|
||||||
|
byte encContentSeq[MAX_SEQ_SZ];
|
||||||
|
byte contentType[MAX_ALGO_SZ];
|
||||||
|
byte contentEncAlgo[MAX_ALGO_SZ];
|
||||||
|
byte encContentOctet[MAX_OCTET_STR_SZ];
|
||||||
|
|
||||||
|
switch (pkcs7->encryptOID) {
|
||||||
|
case DESb:
|
||||||
|
blockKeySz = DES_KEYLEN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DES3b:
|
||||||
|
blockKeySz = DES3_KEYLEN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
CYASSL_MSG("Unsupported content cipher type");
|
||||||
|
return ALGO_ID_E;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* outer content type */
|
||||||
|
outerContentTypeSz = SetContentType(ENVELOPED_DATA, outerContentType);
|
||||||
|
|
||||||
|
/* version */
|
||||||
|
verSz = SetMyVersion(0, ver, 0);
|
||||||
|
|
||||||
|
/* generate random content enc key */
|
||||||
|
InitRng(&rng);
|
||||||
|
RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz);
|
||||||
|
|
||||||
|
/* build RecipientInfo, only handle 1 for now */
|
||||||
|
recipSz = CreateRecipientInfo(pkcs7->singleCert, pkcs7->singleCertSz, RSAk,
|
||||||
|
blockKeySz, &rng, contentKeyPlain,
|
||||||
|
contentKeyEnc, &contentKeyEncSz, recip,
|
||||||
|
MAX_RECIP_SZ);
|
||||||
|
|
||||||
|
if (recipSz < 0) {
|
||||||
|
CYASSL_MSG("Failed to create RecipientInfo");
|
||||||
|
return recipSz;
|
||||||
|
}
|
||||||
|
recipSetSz = SetSet(recipSz, recipSet);
|
||||||
|
|
||||||
|
/* EncryptedContentInfo */
|
||||||
|
contentTypeSz = SetContentType(pkcs7->contentOID, contentType);
|
||||||
|
contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
|
||||||
|
blkType, 0);
|
||||||
|
|
||||||
|
/* allocate memory for encrypted content, pad if necessary */
|
||||||
|
padSz = DES_BLOCK_SIZE - (pkcs7->contentSz % DES_BLOCK_SIZE);
|
||||||
|
desOutSz = pkcs7->contentSz + padSz;
|
||||||
|
|
||||||
|
if (padSz != 0) {
|
||||||
|
plain = XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (plain == NULL) {
|
||||||
|
return MEMORY_E;
|
||||||
|
}
|
||||||
|
XMEMCPY(plain, pkcs7->content, pkcs7->contentSz);
|
||||||
|
dynamicFlag = 1;
|
||||||
|
|
||||||
|
for (i = 0; i < padSz; i++) {
|
||||||
|
plain[pkcs7->contentSz + i + 1] = padSz;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
plain = pkcs7->content;
|
||||||
|
desOutSz = pkcs7->contentSz;
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptedContent = XMALLOC(desOutSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (encryptedContent == NULL) {
|
||||||
|
if (dynamicFlag)
|
||||||
|
XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
return MEMORY_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte tmpIv[blockKeySz];
|
||||||
|
if (pkcs7->encryptOID == DESb) {
|
||||||
|
Des des;
|
||||||
|
RNG_GenerateBlock(&rng, tmpIv, (word32)sizeof(tmpIv));
|
||||||
|
Des_SetKey(&des, contentKeyPlain, tmpIv, DES_ENCRYPTION);
|
||||||
|
Des_CbcEncrypt(&des, encryptedContent, plain, desOutSz);
|
||||||
|
|
||||||
|
} else if (pkcs7->encryptOID == DES3b) {
|
||||||
|
Des3 des3;
|
||||||
|
RNG_GenerateBlock(&rng, tmpIv, (word32)sizeof(tmpIv));
|
||||||
|
Des3_SetKey(&des3, contentKeyPlain, tmpIv, DES_ENCRYPTION);
|
||||||
|
Des3_CbcEncrypt(&des3, encryptedContent, plain, desOutSz);
|
||||||
|
}
|
||||||
|
|
||||||
|
encContentOctetSz = SetOctetString(desOutSz, encContentOctet);
|
||||||
|
|
||||||
|
encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz +
|
||||||
|
encContentOctetSz + desOutSz, encContentSeq);
|
||||||
|
|
||||||
|
/* keep track of sizes for outer wrapper layering */
|
||||||
|
totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz +
|
||||||
|
contentEncAlgoSz + encContentOctetSz + desOutSz;
|
||||||
|
|
||||||
|
/* EnvelopedData */
|
||||||
|
envDataSeqSz = SetSequence(totalSz, envDataSeq);
|
||||||
|
totalSz += envDataSeqSz;
|
||||||
|
|
||||||
|
/* outer content */
|
||||||
|
outerContent[0] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0);
|
||||||
|
outerContentSz = 1 + SetLength(totalSz, outerContent + 1);
|
||||||
|
totalSz += outerContentTypeSz;
|
||||||
|
totalSz += outerContentSz;
|
||||||
|
|
||||||
|
/* ContentInfo */
|
||||||
|
contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq);
|
||||||
|
totalSz += contentInfoSeqSz;
|
||||||
|
|
||||||
|
if (totalSz > (int)outputSz) {
|
||||||
|
CYASSL_MSG("Pkcs7_encrypt output buffer too small");
|
||||||
|
XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
if (dynamicFlag)
|
||||||
|
XFREE(plain, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
return BUFFER_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz);
|
||||||
|
idx += contentInfoSeqSz;
|
||||||
|
XMEMCPY(output + idx, outerContentType, outerContentTypeSz);
|
||||||
|
idx += outerContentTypeSz;
|
||||||
|
XMEMCPY(output + idx, outerContent, outerContentSz);
|
||||||
|
idx += outerContentSz;
|
||||||
|
XMEMCPY(output + idx, envDataSeq, envDataSeqSz);
|
||||||
|
idx += envDataSeqSz;
|
||||||
|
XMEMCPY(output + idx, ver, verSz);
|
||||||
|
idx += verSz;
|
||||||
|
XMEMCPY(output + idx, recipSet, recipSetSz);
|
||||||
|
idx += recipSetSz;
|
||||||
|
XMEMCPY(output + idx, recip, recipSz);
|
||||||
|
idx += recipSz;
|
||||||
|
XMEMCPY(output + idx, encContentSeq, encContentSeqSz);
|
||||||
|
idx += encContentSeqSz;
|
||||||
|
XMEMCPY(output + idx, contentType, contentTypeSz);
|
||||||
|
idx += contentTypeSz;
|
||||||
|
XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz);
|
||||||
|
idx += contentEncAlgoSz;
|
||||||
|
XMEMCPY(output + idx, encContentOctet, encContentOctetSz);
|
||||||
|
idx += encContentOctetSz;
|
||||||
|
XMEMCPY(output + idx, encryptedContent, desOutSz);
|
||||||
|
idx += desOutSz;
|
||||||
|
|
||||||
|
#ifdef NO_RC4
|
||||||
|
FreeRng(&rng);
|
||||||
|
#endif
|
||||||
|
if (dynamicFlag)
|
||||||
|
XFREE(plain, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -80,10 +80,6 @@ typedef struct PKCS7 {
|
|||||||
} PKCS7;
|
} PKCS7;
|
||||||
|
|
||||||
|
|
||||||
CYASSL_API int Pkcs7_encrypt(const byte* certs, word32 certSz, byte* data,
|
|
||||||
word32 dataSz, int cipher, byte* out,
|
|
||||||
word32* outSz, word32 flags);
|
|
||||||
|
|
||||||
CYASSL_LOCAL int SetContentType(int pkcs7TypeOID, byte* output);
|
CYASSL_LOCAL int SetContentType(int pkcs7TypeOID, byte* output);
|
||||||
CYASSL_LOCAL int CreateRecipientInfo(const byte* cert, word32 certSz,
|
CYASSL_LOCAL int CreateRecipientInfo(const byte* cert, word32 certSz,
|
||||||
int keyEncAlgo, int blockKeySz,
|
int keyEncAlgo, int blockKeySz,
|
||||||
|
Reference in New Issue
Block a user