add PKCS7_EncodeEnvelopeData()

This commit is contained in:
Chris Conlon 2014-01-13 13:19:44 -07:00
parent ef9cfc2172
commit 69ffa3a481
2 changed files with 289 additions and 24 deletions

View File

@ -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)
{
@ -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)
{
(void)pkcs7;
(void)output;
(void)outputSz;
return 0;
int i, idx = 0;
int totalSz = 0, padSz = 0, desOutSz = 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;
}

View File

@ -80,10 +80,6 @@ typedef struct 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 CreateRecipientInfo(const byte* cert, word32 certSz,
int keyEncAlgo, int blockKeySz,