mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-02 12:14:38 +02:00
PKCS#7: add support for optional unprotectedAttributes with EncryptedData
This commit is contained in:
@@ -211,7 +211,10 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz)
|
|||||||
/* releases any memory allocated by a PKCS7 initializer */
|
/* releases any memory allocated by a PKCS7 initializer */
|
||||||
void wc_PKCS7_Free(PKCS7* pkcs7)
|
void wc_PKCS7_Free(PKCS7* pkcs7)
|
||||||
{
|
{
|
||||||
(void)pkcs7;
|
if (pkcs7 == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1306,7 +1309,7 @@ int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz,
|
|||||||
int wc_PKCS7_GenerateIV(WC_RNG* rng, byte* iv, word32 ivSz)
|
int wc_PKCS7_GenerateIV(WC_RNG* rng, byte* iv, word32 ivSz)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
WC_RNG* random;
|
WC_RNG* random = NULL;
|
||||||
|
|
||||||
if (iv == NULL || ivSz == 0)
|
if (iv == NULL || ivSz == 0)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
@@ -1316,17 +1319,19 @@ int wc_PKCS7_GenerateIV(WC_RNG* rng, byte* iv, word32 ivSz)
|
|||||||
random = XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
|
random = XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
|
||||||
if (random == NULL)
|
if (random == NULL)
|
||||||
return MEMORY_E;
|
return MEMORY_E;
|
||||||
|
|
||||||
|
ret = wc_InitRng(random);
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
random = rng;
|
random = rng;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = wc_InitRng(random);
|
ret = wc_RNG_GenerateBlock(random, iv, ivSz);
|
||||||
if (ret == 0) {
|
|
||||||
ret = wc_RNG_GenerateBlock(random, iv, ivSz);
|
|
||||||
wc_FreeRng(random);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rng == NULL) {
|
if (rng == NULL) {
|
||||||
|
wc_FreeRng(random);
|
||||||
XFREE(random, NULL, DYNAMIC_TYPE_RNG);
|
XFREE(random, NULL, DYNAMIC_TYPE_RNG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2098,8 +2103,8 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
byte encDataSeq[MAX_SEQ_SZ];
|
byte encDataSeq[MAX_SEQ_SZ];
|
||||||
byte ver[MAX_VERSION_SZ];
|
byte ver[MAX_VERSION_SZ];
|
||||||
|
|
||||||
byte* plain;
|
byte* plain = NULL;
|
||||||
byte* encryptedContent;
|
byte* encryptedContent = NULL;
|
||||||
|
|
||||||
int encContentOctetSz, encContentSeqSz, contentTypeSz;
|
int encContentOctetSz, encContentSeqSz, contentTypeSz;
|
||||||
int contentEncAlgoSz, ivOctetStringSz;
|
int contentEncAlgoSz, ivOctetStringSz;
|
||||||
@@ -2110,6 +2115,14 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
byte ivOctetString[MAX_OCTET_STR_SZ];
|
byte ivOctetString[MAX_OCTET_STR_SZ];
|
||||||
byte encContentOctet[MAX_OCTET_STR_SZ];
|
byte encContentOctet[MAX_OCTET_STR_SZ];
|
||||||
|
|
||||||
|
byte attribSet[MAX_SET_SZ];
|
||||||
|
EncodedAttrib* attribs = NULL;
|
||||||
|
word32 attribsSz;
|
||||||
|
word32 attribsCount;
|
||||||
|
word32 attribsSetSz;
|
||||||
|
|
||||||
|
byte* flatAttribs = NULL;
|
||||||
|
|
||||||
if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
|
if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
|
||||||
pkcs7->encryptOID == 0 || pkcs7->encryptionKey == NULL ||
|
pkcs7->encryptOID == 0 || pkcs7->encryptionKey == NULL ||
|
||||||
pkcs7->encryptionKeySz == 0)
|
pkcs7->encryptionKeySz == 0)
|
||||||
@@ -2122,7 +2135,11 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
outerContentTypeSz = wc_SetContentType(ENCRYPTED_DATA, outerContentType);
|
outerContentTypeSz = wc_SetContentType(ENCRYPTED_DATA, outerContentType);
|
||||||
|
|
||||||
/* version, 2 if unprotectedAttrs present, 0 if absent */
|
/* version, 2 if unprotectedAttrs present, 0 if absent */
|
||||||
verSz = SetMyVersion(0, ver, 0);
|
if (pkcs7->unprotectedAttribsSz > 0) {
|
||||||
|
verSz = SetMyVersion(2, ver, 0);
|
||||||
|
} else {
|
||||||
|
verSz = SetMyVersion(0, ver, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/* EncryptedContentInfo */
|
/* EncryptedContentInfo */
|
||||||
contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType);
|
contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType);
|
||||||
@@ -2194,9 +2211,49 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
encContentOctetSz + encryptedOutSz,
|
encContentOctetSz + encryptedOutSz,
|
||||||
encContentSeq);
|
encContentSeq);
|
||||||
|
|
||||||
|
/* optional UnprotectedAttributes */
|
||||||
|
if (pkcs7->unprotectedAttribsSz != 0) {
|
||||||
|
|
||||||
|
if (pkcs7->unprotectedAttribs == NULL) {
|
||||||
|
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribs = (EncodedAttrib*)XMALLOC(
|
||||||
|
sizeof(EncodedAttrib) * pkcs7->unprotectedAttribsSz,
|
||||||
|
pkcs7->heap, DYNAMIC_TYPE_PKCS);
|
||||||
|
if (attribs == NULL) {
|
||||||
|
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
return MEMORY_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
attribsCount = pkcs7->unprotectedAttribsSz;
|
||||||
|
attribsSz = EncodeAttributes(attribs, pkcs7->unprotectedAttribsSz,
|
||||||
|
pkcs7->unprotectedAttribs,
|
||||||
|
pkcs7->unprotectedAttribsSz);
|
||||||
|
|
||||||
|
flatAttribs = (byte*)XMALLOC(attribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS);
|
||||||
|
if (flatAttribs == NULL) {
|
||||||
|
XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS);
|
||||||
|
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
return MEMORY_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlattenAttributes(flatAttribs, attribs, attribsCount);
|
||||||
|
attribsSetSz = SetImplicit(ASN_SET, 1, attribsSz, attribSet);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
attribsSz = 0;
|
||||||
|
attribsSetSz = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* keep track of sizes for outer wrapper layering */
|
/* keep track of sizes for outer wrapper layering */
|
||||||
totalSz = verSz + encContentSeqSz + contentTypeSz + contentEncAlgoSz +
|
totalSz = verSz + encContentSeqSz + contentTypeSz + contentEncAlgoSz +
|
||||||
ivOctetStringSz + blockSz + encContentOctetSz + encryptedOutSz;
|
ivOctetStringSz + blockSz + encContentOctetSz + encryptedOutSz +
|
||||||
|
attribsSz + attribsSetSz;;
|
||||||
|
|
||||||
/* EncryptedData */
|
/* EncryptedData */
|
||||||
encDataSeqSz = SetSequence(totalSz, encDataSeq);
|
encDataSeqSz = SetSequence(totalSz, encDataSeq);
|
||||||
@@ -2213,6 +2270,10 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
|
|
||||||
if (totalSz > (int)outputSz) {
|
if (totalSz > (int)outputSz) {
|
||||||
WOLFSSL_MSG("PKCS#7 output buffer too small");
|
WOLFSSL_MSG("PKCS#7 output buffer too small");
|
||||||
|
if (pkcs7->unprotectedAttribsSz != 0) {
|
||||||
|
XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS);
|
||||||
|
XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS);
|
||||||
|
}
|
||||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
return BUFFER_E;
|
return BUFFER_E;
|
||||||
@@ -2243,6 +2304,15 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
|
XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
|
||||||
idx += encryptedOutSz;
|
idx += encryptedOutSz;
|
||||||
|
|
||||||
|
if (pkcs7->unprotectedAttribsSz != 0) {
|
||||||
|
XMEMCPY(output + idx, attribSet, attribsSetSz);
|
||||||
|
idx += attribsSetSz;
|
||||||
|
XMEMCPY(output + idx, flatAttribs, attribsSz);
|
||||||
|
idx += attribsSz;
|
||||||
|
XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS);
|
||||||
|
XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS);
|
||||||
|
}
|
||||||
|
|
||||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
@@ -2250,11 +2320,120 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* unwrap and decrypt PKCS#7/CMS encrypted-data object, returned decoded size */
|
void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib, void* heap)
|
||||||
int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
|
|
||||||
byte* output, word32 outputSz)
|
|
||||||
{
|
{
|
||||||
int ret, version, length;
|
PKCS7DecodedAttrib* current;
|
||||||
|
|
||||||
|
if (attrib == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = attrib;
|
||||||
|
while (current != NULL) {
|
||||||
|
PKCS7DecodedAttrib* next = current->next;
|
||||||
|
if (current->oid != NULL) {
|
||||||
|
XFREE(current->oid, heap, DYNAMIC_TYPE_PKCS7);
|
||||||
|
}
|
||||||
|
if (current->value != NULL) {
|
||||||
|
XFREE(current->value, heap, DYNAMIC_TYPE_PKCS7);
|
||||||
|
}
|
||||||
|
XFREE(current, heap, DYNAMIC_TYPE_PKCS7);
|
||||||
|
current = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)heap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* decode and store unprotected attributes in PKCS7->decodedAttrib. Return
|
||||||
|
* 0 on success, negative on error. User must call wc_PKCS7_Free(). */
|
||||||
|
int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg,
|
||||||
|
word32 pkiMsgSz, word32* inOutIdx)
|
||||||
|
{
|
||||||
|
int length, attribLen;
|
||||||
|
word32 oid, savedIdx, idx;
|
||||||
|
PKCS7DecodedAttrib* attrib = NULL;
|
||||||
|
|
||||||
|
if (pkcs7 == NULL || pkiMsg == NULL ||
|
||||||
|
pkiMsgSz == 0 || inOutIdx == NULL)
|
||||||
|
return BAD_FUNC_ARG;
|
||||||
|
|
||||||
|
idx = *inOutIdx;
|
||||||
|
|
||||||
|
if (pkiMsg[idx] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
if (GetLength(pkiMsg, &idx, &attribLen, pkiMsgSz) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
/* loop through attributes */
|
||||||
|
while (attribLen > 0) {
|
||||||
|
|
||||||
|
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
attribLen -= (length + 2); /* TAG + LENGTH + DATA */
|
||||||
|
savedIdx = idx;
|
||||||
|
|
||||||
|
attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib),
|
||||||
|
pkcs7->heap, DYNAMIC_TYPE_PKCS);
|
||||||
|
if (attrib == NULL) {
|
||||||
|
return MEMORY_E;
|
||||||
|
}
|
||||||
|
XMEMSET(attrib, 0, sizeof(PKCS7DecodedAttrib));
|
||||||
|
|
||||||
|
/* save attribute OID bytes and size */
|
||||||
|
if (GetObjectId(pkiMsg, &idx, &oid, oidIgnoreType, pkiMsgSz) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
attrib->oidSz = idx - savedIdx;
|
||||||
|
attrib->oid = (byte*)XMALLOC(attrib->oidSz, pkcs7->heap,
|
||||||
|
DYNAMIC_TYPE_PKCS);
|
||||||
|
if (attrib->oid == NULL) {
|
||||||
|
XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS);
|
||||||
|
return MEMORY_E;
|
||||||
|
}
|
||||||
|
XMEMCPY(attrib->oid, pkiMsg + savedIdx, attrib->oidSz);
|
||||||
|
|
||||||
|
/* save attribute value bytes and size */
|
||||||
|
if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
if ((pkiMsgSz - idx) < (word32)length)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
attrib->valueSz = (word32)length;
|
||||||
|
attrib->value = (byte*)XMALLOC(attrib->valueSz, pkcs7->heap,
|
||||||
|
DYNAMIC_TYPE_PKCS);
|
||||||
|
if (attrib->value == NULL) {
|
||||||
|
XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS);
|
||||||
|
XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS);
|
||||||
|
return MEMORY_E;
|
||||||
|
}
|
||||||
|
XMEMCPY(attrib->value, pkiMsg + idx, attrib->valueSz);
|
||||||
|
idx += length;
|
||||||
|
|
||||||
|
/* store attribute in linked list */
|
||||||
|
if (pkcs7->decodedAttrib != NULL) {
|
||||||
|
attrib->next = pkcs7->decodedAttrib;
|
||||||
|
pkcs7->decodedAttrib = attrib;
|
||||||
|
} else {
|
||||||
|
pkcs7->decodedAttrib = attrib;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*inOutIdx = idx;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* unwrap and decrypt PKCS#7/CMS encrypted-data object, returned decoded size */
|
||||||
|
int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
|
||||||
|
byte* output, word32 outputSz)
|
||||||
|
{
|
||||||
|
int ret, version, length, haveAttribs;
|
||||||
word32 idx = 0;
|
word32 idx = 0;
|
||||||
word32 contentType, encOID;
|
word32 contentType, encOID;
|
||||||
|
|
||||||
@@ -2295,14 +2474,11 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
|
|||||||
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
/* get version, check later */
|
||||||
|
haveAttribs = 0;
|
||||||
if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
|
if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
if (version != 0) {
|
|
||||||
WOLFSSL_MSG("PKCS#7 EncryptedData needs to be of version 0");
|
|
||||||
return ASN_VERSION_E;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* remove EncryptedContentInfo */
|
/* remove EncryptedContentInfo */
|
||||||
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
@@ -2345,6 +2521,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
|
|||||||
return MEMORY_E;
|
return MEMORY_E;
|
||||||
|
|
||||||
XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
|
XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
|
||||||
|
idx += encryptedContentSz;
|
||||||
|
|
||||||
/* decrypt encryptedContent */
|
/* decrypt encryptedContent */
|
||||||
ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey,
|
ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey,
|
||||||
@@ -2361,6 +2538,29 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz,
|
|||||||
/* copy plaintext to output */
|
/* copy plaintext to output */
|
||||||
XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
|
XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
|
||||||
|
|
||||||
|
/* get implicit[1] unprotected attributes, optional */
|
||||||
|
if (idx < pkiMsgSz) {
|
||||||
|
|
||||||
|
haveAttribs = 1;
|
||||||
|
pkcs7->decodedAttrib = NULL;
|
||||||
|
|
||||||
|
ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg,
|
||||||
|
pkiMsgSz, &idx);
|
||||||
|
if (ret != 0) {
|
||||||
|
printf("DEBUG: DecodeUnprotectedAttributes failed!\n");
|
||||||
|
ForceZero(encryptedContent, encryptedContentSz);
|
||||||
|
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* go back and check the version now that attribs have been processed */
|
||||||
|
if ((haveAttribs == 0 && version != 0) ||
|
||||||
|
(haveAttribs == 1 && version != 2) ) {
|
||||||
|
WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version");
|
||||||
|
return ASN_VERSION_E;
|
||||||
|
}
|
||||||
|
|
||||||
ForceZero(encryptedContent, encryptedContentSz);
|
ForceZero(encryptedContent, encryptedContentSz);
|
||||||
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
|
||||||
|
@@ -9041,14 +9041,16 @@ int compress_test(void)
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char* outFileName;
|
const char* outFileName;
|
||||||
const byte* content;
|
const byte* content;
|
||||||
word32 contentSz;
|
word32 contentSz;
|
||||||
int contentOID;
|
int contentOID;
|
||||||
int encryptOID;
|
int encryptOID;
|
||||||
byte* privateKey;
|
byte* privateKey;
|
||||||
word32 privateKeySz;
|
word32 privateKeySz;
|
||||||
byte* encryptionKey;
|
byte* encryptionKey;
|
||||||
word32 encryptionKeySz;
|
word32 encryptionKeySz;
|
||||||
|
PKCS7Attrib* attribs;
|
||||||
|
word32 attribsSz;
|
||||||
} pkcs7Vector;
|
} pkcs7Vector;
|
||||||
|
|
||||||
int pkcs7enveloped_test(void)
|
int pkcs7enveloped_test(void)
|
||||||
@@ -9224,6 +9226,9 @@ int pkcs7encrypted_test(void)
|
|||||||
byte decoded[2048];
|
byte decoded[2048];
|
||||||
FILE* pkcs7File;
|
FILE* pkcs7File;
|
||||||
|
|
||||||
|
PKCS7Attrib* expectedAttrib;
|
||||||
|
PKCS7DecodedAttrib* decodedAttrib;
|
||||||
|
|
||||||
const byte data[] = { /* Hello World */
|
const byte data[] = { /* Hello World */
|
||||||
0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,
|
0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,
|
||||||
0x72,0x6c,0x64
|
0x72,0x6c,0x64
|
||||||
@@ -9248,19 +9253,52 @@ int pkcs7encrypted_test(void)
|
|||||||
};
|
};
|
||||||
byte aes256Key[] = {
|
byte aes256Key[] = {
|
||||||
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
|
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
|
||||||
0x01,0x02,0x03,0x05,0x05,0x06,0x07,0x08,
|
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
|
||||||
0x01,0x02,0x03,0x05,0x05,0x06,0x07,0x08,
|
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
|
||||||
0x01,0x02,0x03,0x05,0x05,0x06,0x07,0x08
|
0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Attribute example from RFC 4134, Section 7.2
|
||||||
|
* OID = 1.2.5555
|
||||||
|
* OCTET STRING = 'This is a test General ASN Attribute, number 1.' */
|
||||||
|
static byte genAttrOid[] = { 0x06, 0x03, 0x2a, 0xab, 0x33 };
|
||||||
|
static byte genAttr[] = { 0x04, 47,
|
||||||
|
0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
|
||||||
|
0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x47,
|
||||||
|
0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x41,
|
||||||
|
0x53, 0x4e, 0x20, 0x41, 0x74, 0x74, 0x72, 0x69,
|
||||||
|
0x62, 0x75, 0x74, 0x65, 0x2c, 0x20, 0x6e, 0x75,
|
||||||
|
0x6d, 0x62, 0x65, 0x72, 0x20, 0x31, 0x2e };
|
||||||
|
|
||||||
|
static byte genAttrOid2[] = { 0x06, 0x03, 0x2a, 0xab, 0x34 };
|
||||||
|
static byte genAttr2[] = { 0x04, 47,
|
||||||
|
0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
|
||||||
|
0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x47,
|
||||||
|
0x65, 0x6e, 0x65, 0x72, 0x61, 0x6c, 0x20, 0x41,
|
||||||
|
0x53, 0x4e, 0x20, 0x41, 0x74, 0x74, 0x72, 0x69,
|
||||||
|
0x62, 0x75, 0x74, 0x65, 0x2c, 0x20, 0x6e, 0x75,
|
||||||
|
0x6d, 0x62, 0x65, 0x72, 0x20, 0x32, 0x2e };
|
||||||
|
|
||||||
|
PKCS7Attrib attribs[] =
|
||||||
|
{
|
||||||
|
{ genAttrOid, sizeof(genAttrOid), genAttr, sizeof(genAttr) }
|
||||||
|
};
|
||||||
|
|
||||||
|
PKCS7Attrib multiAttribs[] =
|
||||||
|
{
|
||||||
|
{ genAttrOid, sizeof(genAttrOid), genAttr, sizeof(genAttr) },
|
||||||
|
{ genAttrOid2, sizeof(genAttrOid2), genAttr2, sizeof(genAttr2) }
|
||||||
};
|
};
|
||||||
|
|
||||||
pkcs7Vector a, b;
|
pkcs7Vector a, b;
|
||||||
#ifndef NO_AES
|
#ifndef NO_AES
|
||||||
pkcs7Vector c, d, e;
|
pkcs7Vector c, d, e, f, g;
|
||||||
pkcs7Vector test_pkcs7enc[4];
|
pkcs7Vector test_pkcs7enc[7];
|
||||||
#else
|
#else
|
||||||
pkcs7Vector test_pkcs7enc[1];
|
pkcs7Vector test_pkcs7enc[1];
|
||||||
#endif
|
#endif
|
||||||
int times = sizeof(test_pkcs7enc) / sizeof(pkcs7Vector), i;
|
int times = sizeof(test_pkcs7enc) / sizeof(pkcs7Vector);
|
||||||
|
int i, attribIdx;
|
||||||
|
|
||||||
/* set up test vectors */
|
/* set up test vectors */
|
||||||
a.content = data;
|
a.content = data;
|
||||||
@@ -9270,6 +9308,8 @@ int pkcs7encrypted_test(void)
|
|||||||
a.encryptionKey = des3Key;
|
a.encryptionKey = des3Key;
|
||||||
a.encryptionKeySz = sizeof(des3Key);
|
a.encryptionKeySz = sizeof(des3Key);
|
||||||
a.outFileName = "pkcs7encryptedDataDES3.der";
|
a.outFileName = "pkcs7encryptedDataDES3.der";
|
||||||
|
a.attribs = NULL;
|
||||||
|
a.attribsSz = 0;
|
||||||
|
|
||||||
b.content = data;
|
b.content = data;
|
||||||
b.contentSz = (word32)sizeof(data);
|
b.contentSz = (word32)sizeof(data);
|
||||||
@@ -9278,6 +9318,8 @@ int pkcs7encrypted_test(void)
|
|||||||
b.encryptionKey = desKey;
|
b.encryptionKey = desKey;
|
||||||
b.encryptionKeySz = sizeof(desKey);
|
b.encryptionKeySz = sizeof(desKey);
|
||||||
b.outFileName = "pkcs7encryptedDataDES.der";
|
b.outFileName = "pkcs7encryptedDataDES.der";
|
||||||
|
b.attribs = NULL;
|
||||||
|
b.attribsSz = 0;
|
||||||
|
|
||||||
#ifndef NO_AES
|
#ifndef NO_AES
|
||||||
c.content = data;
|
c.content = data;
|
||||||
@@ -9287,6 +9329,8 @@ int pkcs7encrypted_test(void)
|
|||||||
c.encryptionKey = aes128Key;
|
c.encryptionKey = aes128Key;
|
||||||
c.encryptionKeySz = sizeof(aes128Key);
|
c.encryptionKeySz = sizeof(aes128Key);
|
||||||
c.outFileName = "pkcs7encryptedDataAES128CBC.der";
|
c.outFileName = "pkcs7encryptedDataAES128CBC.der";
|
||||||
|
c.attribs = NULL;
|
||||||
|
c.attribsSz = 0;
|
||||||
|
|
||||||
d.content = data;
|
d.content = data;
|
||||||
d.contentSz = (word32)sizeof(data);
|
d.contentSz = (word32)sizeof(data);
|
||||||
@@ -9295,6 +9339,8 @@ int pkcs7encrypted_test(void)
|
|||||||
d.encryptionKey = aes192Key;
|
d.encryptionKey = aes192Key;
|
||||||
d.encryptionKeySz = sizeof(aes192Key);
|
d.encryptionKeySz = sizeof(aes192Key);
|
||||||
d.outFileName = "pkcs7encryptedDataAES192CBC.der";
|
d.outFileName = "pkcs7encryptedDataAES192CBC.der";
|
||||||
|
d.attribs = NULL;
|
||||||
|
d.attribsSz = 0;
|
||||||
|
|
||||||
e.content = data;
|
e.content = data;
|
||||||
e.contentSz = (word32)sizeof(data);
|
e.contentSz = (word32)sizeof(data);
|
||||||
@@ -9303,6 +9349,28 @@ int pkcs7encrypted_test(void)
|
|||||||
e.encryptionKey = aes256Key;
|
e.encryptionKey = aes256Key;
|
||||||
e.encryptionKeySz = sizeof(aes256Key);
|
e.encryptionKeySz = sizeof(aes256Key);
|
||||||
e.outFileName = "pkcs7encryptedDataAES256CBC.der";
|
e.outFileName = "pkcs7encryptedDataAES256CBC.der";
|
||||||
|
e.attribs = NULL;
|
||||||
|
e.attribsSz = 0;
|
||||||
|
|
||||||
|
f.content = data;
|
||||||
|
f.contentSz = (word32)sizeof(data);
|
||||||
|
f.contentOID = DATA;
|
||||||
|
f.encryptOID = AES256CBCb;
|
||||||
|
f.encryptionKey = aes256Key;
|
||||||
|
f.encryptionKeySz = sizeof(aes256Key);
|
||||||
|
f.outFileName = "pkcs7encryptedDataAES256CBC_attribs.der";
|
||||||
|
f.attribs = attribs;
|
||||||
|
f.attribsSz = sizeof(attribs)/sizeof(PKCS7Attrib);
|
||||||
|
|
||||||
|
g.content = data;
|
||||||
|
g.contentSz = (word32)sizeof(data);
|
||||||
|
g.contentOID = DATA;
|
||||||
|
g.encryptOID = AES256CBCb;
|
||||||
|
g.encryptionKey = aes256Key;
|
||||||
|
g.encryptionKeySz = sizeof(aes256Key);
|
||||||
|
g.outFileName = "pkcs7encryptedDataAES256CBC_multi_attribs.der";
|
||||||
|
g.attribs = multiAttribs;
|
||||||
|
g.attribsSz = sizeof(multiAttribs)/sizeof(PKCS7Attrib);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
test_pkcs7enc[0] = a;
|
test_pkcs7enc[0] = a;
|
||||||
@@ -9311,6 +9379,8 @@ int pkcs7encrypted_test(void)
|
|||||||
test_pkcs7enc[2] = c;
|
test_pkcs7enc[2] = c;
|
||||||
test_pkcs7enc[3] = d;
|
test_pkcs7enc[3] = d;
|
||||||
test_pkcs7enc[4] = e;
|
test_pkcs7enc[4] = e;
|
||||||
|
test_pkcs7enc[5] = f;
|
||||||
|
test_pkcs7enc[6] = g;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < times; i++) {
|
for (i = 0; i < times; i++) {
|
||||||
@@ -9320,6 +9390,8 @@ int pkcs7encrypted_test(void)
|
|||||||
pkcs7.encryptOID = test_pkcs7enc[i].encryptOID;
|
pkcs7.encryptOID = test_pkcs7enc[i].encryptOID;
|
||||||
pkcs7.encryptionKey = test_pkcs7enc[i].encryptionKey;
|
pkcs7.encryptionKey = test_pkcs7enc[i].encryptionKey;
|
||||||
pkcs7.encryptionKeySz = test_pkcs7enc[i].encryptionKeySz;
|
pkcs7.encryptionKeySz = test_pkcs7enc[i].encryptionKeySz;
|
||||||
|
pkcs7.unprotectedAttribs = test_pkcs7enc[i].attribs;
|
||||||
|
pkcs7.unprotectedAttribsSz = test_pkcs7enc[i].attribsSz;
|
||||||
|
|
||||||
/* encode encryptedData */
|
/* encode encryptedData */
|
||||||
encryptedSz = wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted,
|
encryptedSz = wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted,
|
||||||
@@ -9337,10 +9409,36 @@ int pkcs7encrypted_test(void)
|
|||||||
if (XMEMCMP(decoded, data, sizeof(data)) != 0)
|
if (XMEMCMP(decoded, data, sizeof(data)) != 0)
|
||||||
return -205;
|
return -205;
|
||||||
|
|
||||||
|
/* verify decoded unprotected attributes */
|
||||||
|
if (pkcs7.decodedAttrib != NULL) {
|
||||||
|
decodedAttrib = pkcs7.decodedAttrib;
|
||||||
|
attribIdx = 1;
|
||||||
|
|
||||||
|
while (decodedAttrib != NULL) {
|
||||||
|
|
||||||
|
/* expected attribute, stored list is reversed */
|
||||||
|
expectedAttrib = &(pkcs7.unprotectedAttribs
|
||||||
|
[pkcs7.unprotectedAttribsSz - attribIdx]);
|
||||||
|
|
||||||
|
/* verify oid */
|
||||||
|
if (XMEMCMP(decodedAttrib->oid, expectedAttrib->oid,
|
||||||
|
decodedAttrib->oidSz) != 0)
|
||||||
|
return -206;
|
||||||
|
|
||||||
|
/* verify value */
|
||||||
|
if (XMEMCMP(decodedAttrib->value, expectedAttrib->value,
|
||||||
|
decodedAttrib->valueSz) != 0)
|
||||||
|
return -207;
|
||||||
|
|
||||||
|
decodedAttrib = decodedAttrib->next;
|
||||||
|
attribIdx++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* output pkcs7 envelopedData for external testing */
|
/* output pkcs7 envelopedData for external testing */
|
||||||
pkcs7File = fopen(test_pkcs7enc[i].outFileName, "wb");
|
pkcs7File = fopen(test_pkcs7enc[i].outFileName, "wb");
|
||||||
if (!pkcs7File)
|
if (!pkcs7File)
|
||||||
return -206;
|
return -208;
|
||||||
|
|
||||||
ret = (int)fwrite(encrypted, encryptedSz, 1, pkcs7File);
|
ret = (int)fwrite(encrypted, encryptedSz, 1, pkcs7File);
|
||||||
fclose(pkcs7File);
|
fclose(pkcs7File);
|
||||||
|
@@ -78,6 +78,15 @@ typedef struct PKCS7Attrib {
|
|||||||
} PKCS7Attrib;
|
} PKCS7Attrib;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct PKCS7DecodedAttrib {
|
||||||
|
byte* oid;
|
||||||
|
word32 oidSz;
|
||||||
|
byte* value;
|
||||||
|
word32 valueSz;
|
||||||
|
struct PKCS7DecodedAttrib* next;
|
||||||
|
} PKCS7DecodedAttrib;
|
||||||
|
|
||||||
|
|
||||||
typedef struct PKCS7 {
|
typedef struct PKCS7 {
|
||||||
byte* content; /* inner content, not owner */
|
byte* content; /* inner content, not owner */
|
||||||
word32 contentSz; /* content size */
|
word32 contentSz; /* content size */
|
||||||
@@ -105,10 +114,11 @@ typedef struct PKCS7 {
|
|||||||
word32 signedAttribsSz;
|
word32 signedAttribsSz;
|
||||||
|
|
||||||
/* Encrypted-data Content Type */
|
/* Encrypted-data Content Type */
|
||||||
byte* encryptionKey; /* block cipher encryption key */
|
byte* encryptionKey; /* block cipher encryption key */
|
||||||
word32 encryptionKeySz; /* size of key buffer, bytes */
|
word32 encryptionKeySz; /* size of key buffer, bytes */
|
||||||
PKCS7Attrib* unprotectedAttribs; /* optional */
|
PKCS7Attrib* unprotectedAttribs; /* optional */
|
||||||
word32 unprotectedAttribsSz;
|
word32 unprotectedAttribsSz;
|
||||||
|
PKCS7DecodedAttrib* decodedAttrib; /* linked list of decoded attribs */
|
||||||
} PKCS7;
|
} PKCS7;
|
||||||
|
|
||||||
|
|
||||||
@@ -133,6 +143,11 @@ WOLFSSL_LOCAL int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outS
|
|||||||
word32 blockSz);
|
word32 blockSz);
|
||||||
WOLFSSL_LOCAL int wc_PKCS7_GetOIDBlockSize(int oid);
|
WOLFSSL_LOCAL int wc_PKCS7_GetOIDBlockSize(int oid);
|
||||||
WOLFSSL_LOCAL int wc_PKCS7_GetOIDKeySize(int oid);
|
WOLFSSL_LOCAL int wc_PKCS7_GetOIDKeySize(int oid);
|
||||||
|
WOLFSSL_LOCAL int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7,
|
||||||
|
byte* pkiMsg, word32 pkiMsgSz,
|
||||||
|
word32* inOutIdx);
|
||||||
|
WOLFSSL_LOCAL void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib,
|
||||||
|
void* heap);
|
||||||
|
|
||||||
|
|
||||||
WOLFSSL_API int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz);
|
WOLFSSL_API int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz);
|
||||||
|
Reference in New Issue
Block a user