add CMS AuthEnvelopedData support for authAttrs

This commit is contained in:
Chris Conlon
2018-09-21 17:13:33 -06:00
committed by David Garske
parent bc94cdc11b
commit 06a6f8400b
6 changed files with 190 additions and 15 deletions

1
.gitignore vendored
View File

@ -111,6 +111,7 @@ pkcs7authEnvelopedDataAES256GCM.der
pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der
pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der
pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der
pkcs7authEnvelopedDataAES256GCM_firmwarePkgData.der
pkcs7authEnvelopedDataAES256GCM_IANDS.der
pkcs7authEnvelopedDataAES256GCM_SKID.der
pkcs7compressedData_data_zlib.der

View File

@ -49,6 +49,7 @@ CLEANFILES+= cert.der \
pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der \
pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der \
pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der \
pkcs7authEnvelopedDataAES256GCM_firmwarePkgData.der \
pkcs7authEnvelopedDataAES256GCM_IANDS.der \
pkcs7authEnvelopedDataAES256GCM_SKID.der \
pkcs7compressedData_data_zlib.der \

View File

@ -14854,18 +14854,21 @@ static void test_wc_PKCS7_New (void)
static void test_wc_PKCS7_Init (void)
{
#if defined(HAVE_PKCS7)
PKCS7 pkcs7;
PKCS7* pkcs7;
void* heap = NULL;
printf(testingFmt, "wc_PKCS7_Init()");
AssertIntEQ(wc_PKCS7_Init(&pkcs7, heap, devId), 0);
pkcs7 = wc_PKCS7_New(heap, devId);
AssertNotNull(pkcs7);
AssertIntEQ(wc_PKCS7_Init(pkcs7, heap, devId), 0);
/* Pass in bad args. */
AssertIntEQ(wc_PKCS7_Init(NULL, heap, devId), BAD_FUNC_ARG);
printf(resultFmt, passed);
wc_PKCS7_Free(&pkcs7);
wc_PKCS7_Free(pkcs7);
#endif
} /* END test-wc_PKCS7_Init */

View File

@ -176,8 +176,10 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz)
return 0;
};
if (outputSz < (MAX_LENGTH_SZ + 1 + typeSz))
if (outputSz < (MAX_LENGTH_SZ + 1 + typeSz)) {
WOLFSSL_MSG("CMS content type buffer too small");
return BAD_FUNC_ARG;
}
idSz = SetLength(typeSz, ID_Length);
output[idx++] = ASN_OBJECT_ID;
@ -7117,6 +7119,23 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
byte macInt[MAX_VERSION_SZ];
word32 nonceSz, macIntSz;
byte* flatAuthAttribs = NULL;
word32 flatAuthAttribsSz = 0;
byte* aadBuffer = NULL;
word32 aadBufferSz = 0;
byte authAttribSet[MAX_SET_SZ];
byte authAttribAadSet[MAX_SET_SZ];
EncodedAttrib authAttribs[MAX_SIGNED_ATTRIBS_SZ];
word32 authAttribsSz = 0, authAttribsCount = 0;
word32 authAttribsSetSz = 0, authAttribsAadSetSz = 0;
PKCS7Attrib contentTypeAttrib;
byte contentTypeValue[MAX_OID_SZ];
/* contentType OID (1.2.840.113549.1.9.3) */
const byte contentTypeOid[] =
{ ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
0x09, 0x03 };
if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0)
return BAD_FUNC_ARG;
@ -7219,20 +7238,99 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
return ret;
}
/* build up authenticated attributes (authAttrs) */
if (pkcs7->contentOID != DATA) {
/* if type is not id-data, contentType attribute MUST be added */
contentTypeAttrib.oid = contentTypeOid;
contentTypeAttrib.oidSz = sizeof(contentTypeOid);
/* try to set from contentOID first, known types */
ret = wc_SetContentType(pkcs7->contentOID, contentTypeValue,
sizeof(contentTypeValue));
if (ret > 0) {
contentTypeAttrib.value = contentTypeValue;
contentTypeAttrib.valueSz = ret;
} else if (ret <= 0) {
/* try to set from custom content type */
if (pkcs7->contentType == NULL || pkcs7->contentTypeSz == 0) {
WOLFSSL_MSG("CMS pkcs7->contentType must be set if "
"contentOID is not");
return BAD_FUNC_ARG;
}
contentTypeAttrib.value = pkcs7->contentType;
contentTypeAttrib.valueSz = pkcs7->contentTypeSz;
}
authAttribsCount += 1;
authAttribsSz += EncodeAttributes(authAttribs, 1,
&contentTypeAttrib, 1);
/* add in user's signed attributes */
if (pkcs7->authAttribsSz > 0) {
authAttribsCount += pkcs7->authAttribsSz;
authAttribsSz += EncodeAttributes(authAttribs +
authAttribsCount * sizeof(PKCS7Attrib),
MAX_SIGNED_ATTRIBS_SZ - authAttribsCount,
pkcs7->authAttribs,
pkcs7->authAttribsSz);
}
flatAuthAttribs = (byte*)XMALLOC(authAttribsSz, pkcs7->heap,
DYNAMIC_TYPE_PKCS7);
flatAuthAttribsSz = authAttribsSz;
if (flatAuthAttribs == NULL) {
return MEMORY_E;
}
FlattenAttributes(flatAuthAttribs, authAttribs, authAttribsCount);
authAttribsSetSz = SetImplicit(ASN_SET, 1, authAttribsSz,
authAttribSet);
/* From RFC5083, "For the purpose of constructing the AAD, the
* IMPLICIT [1] tag in the authAttrs field is not used for the
* DER encoding: rather a universal SET OF tag is used. */
authAttribsAadSetSz = SetSet(authAttribsSz, authAttribAadSet);
/* allocate temp buffer to hold alternate attrib encoding for aad */
aadBuffer = (byte*)XMALLOC(flatAuthAttribsSz + authAttribsAadSetSz,
pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (aadBuffer == NULL) {
XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
return MEMORY_E;
}
/* build up alternate attrib encoding for aad */
aadBufferSz = 0;
XMEMCPY(aadBuffer + aadBufferSz, authAttribAadSet, authAttribsAadSetSz);
aadBufferSz += authAttribsAadSetSz;
XMEMCPY(aadBuffer + aadBufferSz, flatAuthAttribs, flatAuthAttribsSz);
aadBufferSz += flatAuthAttribsSz;
}
/* allocate encrypted content buffer */
encryptedOutSz = pkcs7->contentSz;
encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
DYNAMIC_TYPE_PKCS7);
if (encryptedContent == NULL)
if (encryptedContent == NULL) {
if (flatAuthAttribs)
XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
return MEMORY_E;
}
/* encrypt content */
ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek,
pkcs7->cekSz, nonce, nonceSz, NULL, 0, authTag, sizeof(authTag),
pkcs7->content, encryptedOutSz, encryptedContent);
pkcs7->cekSz, nonce, nonceSz, aadBuffer, aadBufferSz, authTag,
sizeof(authTag), pkcs7->content, encryptedOutSz, encryptedContent);
if (aadBuffer)
XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (ret != 0) {
if (flatAuthAttribs)
XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
return ret;
}
@ -7240,8 +7338,12 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
/* EncryptedContentInfo */
ret = wc_SetContentType(pkcs7->contentOID, contentType,
sizeof(contentType));
if (ret < 0)
if (ret < 0) {
if (flatAuthAttribs)
XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
return ret;
}
contentTypeSz = ret;
@ -7259,6 +7361,8 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
macIntSz);
if (contentEncAlgoSz == 0) {
if (flatAuthAttribs)
XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
return BAD_FUNC_ARG;
}
@ -7276,8 +7380,8 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
/* keep track of sizes for outer wrapper layering */
totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz +
contentEncAlgoSz + nonceOctetStringSz + nonceSz + macIntSz +
encContentOctetSz + encryptedOutSz + macOctetStringSz +
sizeof(authTag);
encContentOctetSz + encryptedOutSz + flatAuthAttribsSz +
authAttribsSetSz + macOctetStringSz + sizeof(authTag);
/* EnvelopedData */
envDataSeqSz = SetSequence(totalSz, envDataSeq);
@ -7294,6 +7398,8 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
if (totalSz > (int)outputSz) {
WOLFSSL_MSG("Pkcs7_encrypt output buffer too small");
if (flatAuthAttribs)
XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
return BUFFER_E;
}
@ -7334,6 +7440,16 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
idx += encContentOctetSz;
XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
idx += encryptedOutSz;
/* authenticated attributes */
if (flatAuthAttribsSz > 0) {
XMEMCPY(output + idx, authAttribSet, authAttribsSetSz);
idx += authAttribsSetSz;
XMEMCPY(output + idx, flatAuthAttribs, flatAuthAttribsSz);
idx += flatAuthAttribsSz;
XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
}
XMEMCPY(output + idx, macOctetString, macOctetStringSz);
idx += macOctetStringSz;
XMEMCPY(output + idx, authTag, sizeof(authTag));
@ -7370,6 +7486,12 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
byte* encryptedContent = NULL;
int explicitOctet;
byte authAttribSetByte = 0;
byte* encodedAttribs = NULL;
word32 encodedAttribIdx = 0, encodedAttribSz = 0;
byte* authAttrib = NULL;
int authAttribSz = 0;
if (pkcs7 == NULL)
return BAD_FUNC_ARG;
@ -7527,6 +7649,28 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
idx += encryptedContentSz;
/* may have IMPLICIT [1] authenticatedAttributes */
if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
encodedAttribIdx = idx;
encodedAttribs = pkiMsg + idx;
idx++;
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
return ASN_PARSE_E;
/* save pointer and length */
authAttrib = &pkiMsg[idx];
authAttribSz = length;
encodedAttribSz = length + (idx - encodedAttribIdx);
if (wc_PKCS7_ParseAttribs(pkcs7, authAttrib, authAttribSz) < 0) {
WOLFSSL_MSG("Error parsing authenticated attributes");
return ASN_PARSE_E;
}
idx += length;
}
/* get authTag OCTET STRING */
if (pkiMsg[idx++] != ASN_OCTET_STRING) {
#ifdef WOLFSSL_SMALL_STACK
@ -7553,11 +7697,20 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
XMEMCPY(authTag, &pkiMsg[idx], authTagSz);
idx += authTagSz;
if (authAttrib != NULL) {
/* temporarily swap authAttribs byte[0] to SET OF instead of
* IMPLICIT [1], for aad calculation */
authAttribSetByte = encodedAttribs[0];
encodedAttribs[0] = ASN_SET | ASN_CONSTRUCTED;
}
/* decrypt encryptedContent */
ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz,
nonce, nonceSz, NULL, 0, authTag,
authTagSz, encryptedContent,
encryptedContentSz, encryptedContent);
nonce, nonceSz, encodedAttribs,
encodedAttribSz, authTag, authTagSz,
encryptedContent, encryptedContentSz,
encryptedContent);
if (ret != 0) {
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
#ifdef WOLFSSL_SMALL_STACK
@ -7566,6 +7719,11 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
return ret;
}
if (authAttrib != NULL) {
/* restore authAttrib IMPLICIT [1] */
encodedAttribs[0] = authAttribSetByte;
}
/* copy plaintext to output */
XMEMCPY(output, encryptedContent, encryptedContentSz);

View File

@ -19640,6 +19640,12 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz,
NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0,
"pkcs7authEnvelopedDataAES256GCM.der"},
/* test with contentType set to FirmwarePkgData */
{data, (word32)sizeof(data), FIRMWARE_PKG_DATA, AES256GCMb, 0, 0,
rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, 0, 0,
NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0,
0, 0, 0, 0, 0, "pkcs7authEnvelopedDataAES256GCM_firmwarePkgData.der"},
/* explicitly using SKID for SubjectKeyIdentifier */
{data, (word32)sizeof(data), DATA, AES256GCMb, 0, 0, rsaCert, rsaCertSz,
rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, CMS_SKID, 0, NULL, 0,
@ -19797,7 +19803,6 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz,
testVectors[i].kekEncryptOID, testVectors[i].pwriOptions);
if (ret < 0) {
printf("CHRIS: ret = %d\n", ret);
wc_PKCS7_Free(pkcs7);
return -9219;
}

View File

@ -58,6 +58,10 @@
#define MAX_ORI_VALUE_SZ 512
#endif
#ifndef MAX_SIGNED_ATTRIBS_SZ
#define MAX_SIGNED_ATTRIBS_SZ 7
#endif
/* PKCS#7 content types, ref RFC 2315 (Section 14) */
enum PKCS7_TYPES {
PKCS7_MSG = 650, /* 1.2.840.113549.1.7 */
@ -205,6 +209,9 @@ typedef struct PKCS7 {
void* oriEncryptCtx; /* ORI encrypt user context ptr */
void* oriDecryptCtx; /* ORI decrypt user context ptr */
PKCS7Attrib* authAttribs; /* authenticated attribs */
word32 authAttribsSz;
/* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */
} PKCS7;