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_SHA256KDF.der
pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der
pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der
pkcs7authEnvelopedDataAES256GCM_firmwarePkgData.der
pkcs7authEnvelopedDataAES256GCM_IANDS.der pkcs7authEnvelopedDataAES256GCM_IANDS.der
pkcs7authEnvelopedDataAES256GCM_SKID.der pkcs7authEnvelopedDataAES256GCM_SKID.der
pkcs7compressedData_data_zlib.der pkcs7compressedData_data_zlib.der

View File

@@ -49,6 +49,7 @@ CLEANFILES+= cert.der \
pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der \ pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der \
pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der \ pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der \
pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der \ pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der \
pkcs7authEnvelopedDataAES256GCM_firmwarePkgData.der \
pkcs7authEnvelopedDataAES256GCM_IANDS.der \ pkcs7authEnvelopedDataAES256GCM_IANDS.der \
pkcs7authEnvelopedDataAES256GCM_SKID.der \ pkcs7authEnvelopedDataAES256GCM_SKID.der \
pkcs7compressedData_data_zlib.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) static void test_wc_PKCS7_Init (void)
{ {
#if defined(HAVE_PKCS7) #if defined(HAVE_PKCS7)
PKCS7 pkcs7; PKCS7* pkcs7;
void* heap = NULL; void* heap = NULL;
printf(testingFmt, "wc_PKCS7_Init()"); 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. */ /* Pass in bad args. */
AssertIntEQ(wc_PKCS7_Init(NULL, heap, devId), BAD_FUNC_ARG); AssertIntEQ(wc_PKCS7_Init(NULL, heap, devId), BAD_FUNC_ARG);
printf(resultFmt, passed); printf(resultFmt, passed);
wc_PKCS7_Free(&pkcs7); wc_PKCS7_Free(pkcs7);
#endif #endif
} /* END test-wc_PKCS7_Init */ } /* END test-wc_PKCS7_Init */

View File

@@ -176,8 +176,10 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz)
return 0; 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; return BAD_FUNC_ARG;
}
idSz = SetLength(typeSz, ID_Length); idSz = SetLength(typeSz, ID_Length);
output[idx++] = ASN_OBJECT_ID; output[idx++] = ASN_OBJECT_ID;
@@ -7117,6 +7119,23 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
byte macInt[MAX_VERSION_SZ]; byte macInt[MAX_VERSION_SZ];
word32 nonceSz, macIntSz; 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) if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
@@ -7219,20 +7238,99 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
return ret; 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 */ /* allocate encrypted content buffer */
encryptedOutSz = pkcs7->contentSz; encryptedOutSz = pkcs7->contentSz;
encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap,
DYNAMIC_TYPE_PKCS7); DYNAMIC_TYPE_PKCS7);
if (encryptedContent == NULL) if (encryptedContent == NULL) {
if (flatAuthAttribs)
XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
return MEMORY_E; return MEMORY_E;
}
/* encrypt content */ /* encrypt content */
ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek, ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek,
pkcs7->cekSz, nonce, nonceSz, NULL, 0, authTag, sizeof(authTag), pkcs7->cekSz, nonce, nonceSz, aadBuffer, aadBufferSz, authTag,
pkcs7->content, encryptedOutSz, encryptedContent); sizeof(authTag), pkcs7->content, encryptedOutSz, encryptedContent);
if (aadBuffer)
XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (ret != 0) { if (ret != 0) {
if (flatAuthAttribs)
XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
return ret; return ret;
} }
@@ -7240,8 +7338,12 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
/* EncryptedContentInfo */ /* EncryptedContentInfo */
ret = wc_SetContentType(pkcs7->contentOID, contentType, ret = wc_SetContentType(pkcs7->contentOID, contentType,
sizeof(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; return ret;
}
contentTypeSz = ret; contentTypeSz = ret;
@@ -7259,6 +7361,8 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
macIntSz); macIntSz);
if (contentEncAlgoSz == 0) { if (contentEncAlgoSz == 0) {
if (flatAuthAttribs)
XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
} }
@@ -7276,8 +7380,8 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
/* keep track of sizes for outer wrapper layering */ /* keep track of sizes for outer wrapper layering */
totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz +
contentEncAlgoSz + nonceOctetStringSz + nonceSz + macIntSz + contentEncAlgoSz + nonceOctetStringSz + nonceSz + macIntSz +
encContentOctetSz + encryptedOutSz + macOctetStringSz + encContentOctetSz + encryptedOutSz + flatAuthAttribsSz +
sizeof(authTag); authAttribsSetSz + macOctetStringSz + sizeof(authTag);
/* EnvelopedData */ /* EnvelopedData */
envDataSeqSz = SetSequence(totalSz, envDataSeq); envDataSeqSz = SetSequence(totalSz, envDataSeq);
@@ -7294,6 +7398,8 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
if (totalSz > (int)outputSz) { if (totalSz > (int)outputSz) {
WOLFSSL_MSG("Pkcs7_encrypt output buffer too small"); WOLFSSL_MSG("Pkcs7_encrypt output buffer too small");
if (flatAuthAttribs)
XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
return BUFFER_E; return BUFFER_E;
} }
@@ -7334,6 +7440,16 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output,
idx += encContentOctetSz; idx += encContentOctetSz;
XMEMCPY(output + idx, encryptedContent, encryptedOutSz); XMEMCPY(output + idx, encryptedContent, encryptedOutSz);
idx += 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); XMEMCPY(output + idx, macOctetString, macOctetStringSz);
idx += macOctetStringSz; idx += macOctetStringSz;
XMEMCPY(output + idx, authTag, sizeof(authTag)); XMEMCPY(output + idx, authTag, sizeof(authTag));
@@ -7370,6 +7486,12 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
byte* encryptedContent = NULL; byte* encryptedContent = NULL;
int explicitOctet; int explicitOctet;
byte authAttribSetByte = 0;
byte* encodedAttribs = NULL;
word32 encodedAttribIdx = 0, encodedAttribSz = 0;
byte* authAttrib = NULL;
int authAttribSz = 0;
if (pkcs7 == NULL) if (pkcs7 == NULL)
return BAD_FUNC_ARG; return BAD_FUNC_ARG;
@@ -7527,6 +7649,28 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
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 */ /* get authTag OCTET STRING */
if (pkiMsg[idx++] != ASN_OCTET_STRING) { if (pkiMsg[idx++] != ASN_OCTET_STRING) {
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
@@ -7553,11 +7697,20 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
XMEMCPY(authTag, &pkiMsg[idx], authTagSz); XMEMCPY(authTag, &pkiMsg[idx], authTagSz);
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 */ /* decrypt encryptedContent */
ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz,
nonce, nonceSz, NULL, 0, authTag, nonce, nonceSz, encodedAttribs,
authTagSz, encryptedContent, encodedAttribSz, authTag, authTagSz,
encryptedContentSz, encryptedContent); encryptedContent, encryptedContentSz,
encryptedContent);
if (ret != 0) { if (ret != 0) {
XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7);
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
@@ -7566,6 +7719,11 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
return ret; return ret;
} }
if (authAttrib != NULL) {
/* restore authAttrib IMPLICIT [1] */
encodedAttribs[0] = authAttribSetByte;
}
/* copy plaintext to output */ /* copy plaintext to output */
XMEMCPY(output, encryptedContent, encryptedContentSz); 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, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0,
"pkcs7authEnvelopedDataAES256GCM.der"}, "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 */ /* explicitly using SKID for SubjectKeyIdentifier */
{data, (word32)sizeof(data), DATA, AES256GCMb, 0, 0, rsaCert, rsaCertSz, {data, (word32)sizeof(data), DATA, AES256GCMb, 0, 0, rsaCert, rsaCertSz,
rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, CMS_SKID, 0, NULL, 0, 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); testVectors[i].kekEncryptOID, testVectors[i].pwriOptions);
if (ret < 0) { if (ret < 0) {
printf("CHRIS: ret = %d\n", ret);
wc_PKCS7_Free(pkcs7); wc_PKCS7_Free(pkcs7);
return -9219; return -9219;
} }

View File

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