From 70ca95b357ed3affce354caa1050e980150822b4 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 9 Aug 2018 14:22:06 -0600 Subject: [PATCH 01/56] add support for custom contentType with CMS SignedData type --- Makefile.am | 2 + wolfcrypt/src/asn.c | 2 +- wolfcrypt/src/pkcs7.c | 93 ++++++++++++++++++++++++++++++--------- wolfcrypt/test/test.c | 91 +++++++++++++++++++++++++++----------- wolfssl/wolfcrypt/asn.h | 11 +++-- wolfssl/wolfcrypt/pkcs7.h | 5 +++ 6 files changed, 153 insertions(+), 51 deletions(-) diff --git a/Makefile.am b/Makefile.am index 6c1f3827d..b9d60b6da 100644 --- a/Makefile.am +++ b/Makefile.am @@ -59,12 +59,14 @@ CLEANFILES+= cert.der \ pkcs7signedData_RSA_SHA_noattr.der \ pkcs7signedData_RSA_SHA224.der \ pkcs7signedData_RSA_SHA256.der \ + pkcs7signedData_RSA_SHA256_custom_contentType.der \ pkcs7signedData_RSA_SHA384.der \ pkcs7signedData_RSA_SHA512.der \ pkcs7signedData_ECDSA_SHA.der \ pkcs7signedData_ECDSA_SHA_noattr.der \ pkcs7signedData_ECDSA_SHA224.der \ pkcs7signedData_ECDSA_SHA256.der \ + pkcs7signedData_ECDSA_SHA256_custom_contentType.der \ pkcs7signedData_ECDSA_SHA384.der \ pkcs7signedData_ECDSA_SHA512.der diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index b02733c0e..8743e7ecb 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1938,7 +1938,7 @@ int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz) * ASN_PARSE_E when length is invalid. * Otherwise, 0 to indicate success. */ -static int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, +int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) { word32 idx = *inOutIdx; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index c478225b7..2d4f2cc45 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -383,6 +383,8 @@ void wc_PKCS7_Free(PKCS7* pkcs7) pkcs7->isDynamic = 0; XFREE(pkcs7, pkcs7->heap, DYNAMIC_TYPE_PKCS7); } + + pkcs7->contentTypeSz = 0; } @@ -1030,19 +1032,22 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, const byte* hashBuf, word32 hashSz, byte* output, word32* outputSz, byte* output2, word32* output2Sz) { - const byte outerOid[] = - { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, - 0x07, 0x02 }; + /* id-signedData (1.2.840.113549.1.7.2) */ + static const byte outerOid[] = + { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x07, 0x02 }; + + /* default id-data OID (1.2.840.113549.1.7.1), user can override */ const byte innerOid[] = - { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01 }; + /* 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 }; - const byte contentType[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01 }; + + /* messageDigest OID (1.2.840.113549.1.9.4) */ const byte messageDigestOid[] = { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04 }; @@ -1053,7 +1058,6 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, int digEncAlgoId, digEncAlgoType; byte* flatSignedAttribs = NULL; word32 flatSignedAttribsSz = 0; - word32 innerOidSz = sizeof(innerOid); word32 outerOidSz = sizeof(outerOid); if (pkcs7 == NULL || pkcs7->contentSz == 0 || @@ -1065,6 +1069,20 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, } /* verify the hash size matches */ +#ifdef WOLFSSL_SMALL_STACK + esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (esd == NULL) + return MEMORY_E; +#endif + + XMEMSET(esd, 0, sizeof(ESD)); + + /* use default DATA contentType if not set by user */ + if (pkcs7->contentTypeSz == 0) { + XMEMCPY(pkcs7->contentType, innerOid, sizeof(innerOid)); + pkcs7->contentTypeSz = sizeof(innerOid); + } + esd->hashType = wc_OidGetHash(pkcs7->hashOID); if (wc_HashGetDigestSize(esd->hashType) != (int)hashSz) { WOLFSSL_MSG("hashSz did not match hashOID"); @@ -1080,8 +1098,8 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz + pkcs7->contentSz, esd->innerContSeq); esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd->innerOctetsSz + - innerOidSz + esd->innerContSeqSz, - esd->contentInfoSeq); + pkcs7->contentTypeSz + esd->innerContSeqSz, + esd->contentInfoSeq); esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, esd->issuerSn, MAX_SN_SZ); @@ -1111,7 +1129,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, /* build up signed attributes */ ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, contentTypeOid, sizeof(contentTypeOid), - contentType, sizeof(contentType), + pkcs7->contentType, pkcs7->contentTypeSz, messageDigestOid, sizeof(messageDigestOid)); if (ret < 0) { return MEMORY_E; @@ -1205,8 +1223,8 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, idx += esd->singleDigAlgoIdSz; XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz); idx += esd->contentInfoSeqSz; - XMEMCPY(output + idx, innerOid, innerOidSz); - idx += innerOidSz; + XMEMCPY(output + idx, pkcs7->contentType, pkcs7->contentTypeSz); + idx += pkcs7->contentTypeSz; XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz); idx += esd->innerContSeqSz; XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz); @@ -1928,13 +1946,14 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, word32 hashSz, byte* pkiMsg, word32 pkiMsgSz, byte* pkiMsg2, word32 pkiMsg2Sz) { - word32 idx, contentType, hashOID, sigOID, totalSz; + word32 idx, outerContentType, hashOID, sigOID, contentTypeSz, totalSz; int length, version, ret; byte* content = NULL; byte* contentDynamic = NULL; byte* sig = NULL; byte* cert = NULL; byte* signedAttrib = NULL; + byte* contentType = NULL; int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0; word32 localIdx, start; byte degenerate; @@ -1984,10 +2003,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } /* Get the contentInfo contentType */ - if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) + if (wc_GetContentType(pkiMsg, &idx, &outerContentType, pkiMsgSz) < 0) return ASN_PARSE_E; - if (contentType != SIGNED_DATA) { + if (outerContentType != SIGNED_DATA) { WOLFSSL_MSG("PKCS#7 input not of type SignedData"); return PKCS7_OID_E; } @@ -2028,12 +2047,16 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, return ASN_PARSE_E; /* Get the inner ContentInfo contentType */ - if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) - return ASN_PARSE_E; + { + word32 localIdx = idx; - if (contentType != DATA) { - WOLFSSL_MSG("PKCS#7 inner input not of type Data"); - return PKCS7_OID_E; + if (GetASNObjectId(pkiMsg, &idx, &length, pkiMsgSz) != 0) + return ASN_PARSE_E; + + contentType = pkiMsg + localIdx; + contentTypeSz = length + (idx - localIdx); + + idx += length; } /* Check for content info, it could be omitted when degenerate */ @@ -2240,6 +2263,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkcs7->content = content; pkcs7->contentSz = contentSz; + /* set contentType and size after init of PKCS7 structure */ + if (wc_PKCS7_SetContentType(pkcs7, contentType, contentTypeSz) < 0) + return ASN_PARSE_E; + /* Get the implicit[1] set of crls */ if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { idx++; @@ -3532,6 +3559,30 @@ static int wc_PKCS7_GenerateIV(PKCS7* pkcs7, WC_RNG* rng, byte* iv, word32 ivSz) } +/* Set custom contentType, currently supported with SignedData type + * + * pkcs7 - pointer to initialized PKCS7 structure + * contentType - pointer to array with ASN.1 encoded OID value + * sz - length of contentType array, octets + * + * return 0 on success, negative upon error */ +int wc_PKCS7_SetContentType(PKCS7* pkcs7, byte* contentType, word32 sz) +{ + if (pkcs7 == NULL || contentType == NULL || sz == 0) + return BAD_FUNC_ARG; + + if (sz > MAX_OID_SZ) { + WOLFSSL_MSG("input array too large, bounded by MAX_OID_SZ"); + return BAD_FUNC_ARG; + } + + XMEMCPY(pkcs7->contentType, contentType, sz); + pkcs7->contentTypeSz = sz; + + return 0; +} + + /* return size of padded data, padded to blockSz chunks, or negative on error */ int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz) { diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 879e6e848..ff72d3f27 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19298,6 +19298,8 @@ typedef struct { PKCS7Attrib* signedAttribs; word32 signedAttribsSz; const char* outFileName; + byte* contentType; + word32 contentTypeSz; } pkcs7SignedVector; @@ -19348,6 +19350,11 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, sizeof(senderNonce) } }; + /* for testing custom contentType, FirmwarePkgData */ + byte customContentType[] = { 0x06, 0x0B, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x01, 0x10 }; + const pkcs7SignedVector testVectors[] = { #ifndef NO_RSA @@ -19355,36 +19362,42 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, /* RSA with SHA */ {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA.der"}, + "pkcs7signedData_RSA_SHA.der", NULL, 0}, /* RSA with SHA, no signed attributes */ {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, NULL, 0, - "pkcs7signedData_RSA_SHA_noattr.der"}, + "pkcs7signedData_RSA_SHA_noattr.der", NULL, 0}, #endif #ifdef WOLFSSL_SHA224 /* RSA with SHA224 */ {data, (word32)sizeof(data), SHA224h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA224.der"}, + "pkcs7signedData_RSA_SHA224.der", NULL, 0}, #endif #ifndef NO_SHA256 /* RSA with SHA256 */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA256.der"}, + "pkcs7signedData_RSA_SHA256.der", NULL, 0}, + + /* RSA with SHA256 and custom contentType */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA256_custom_contentType.der", customContentType, + sizeof(customContentType)}, #endif #if defined(WOLFSSL_SHA384) /* RSA with SHA384 */ {data, (word32)sizeof(data), SHA384h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA384.der"}, + "pkcs7signedData_RSA_SHA384.der", NULL, 0}, #endif #if defined(WOLFSSL_SHA512) /* RSA with SHA512 */ {data, (word32)sizeof(data), SHA512h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA512.der"}, + "pkcs7signedData_RSA_SHA512.der", NULL, 0}, #endif #endif /* NO_RSA */ @@ -19393,36 +19406,42 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, /* ECDSA with SHA */ {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA.der"}, + "pkcs7signedData_ECDSA_SHA.der", NULL, 0}, /* ECDSA with SHA, no signed attributes */ {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, NULL, 0, - "pkcs7signedData_ECDSA_SHA_noattr.der"}, + "pkcs7signedData_ECDSA_SHA_noattr.der", NULL, 0}, #endif #ifdef WOLFSSL_SHA224 /* ECDSA with SHA224 */ {data, (word32)sizeof(data), SHA224h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA224.der"}, + "pkcs7signedData_ECDSA_SHA224.der", NULL, 0}, #endif #ifndef NO_SHA256 /* ECDSA with SHA256 */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA256.der"}, + "pkcs7signedData_ECDSA_SHA256.der", NULL, 0}, + + /* ECDSA with SHA256 and custom contentType */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA256_custom_contentType.der", + customContentType, sizeof(customContentType)}, #endif #ifdef WOLFSSL_SHA384 /* ECDSA with SHA384 */ {data, (word32)sizeof(data), SHA384h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA384.der"}, + "pkcs7signedData_ECDSA_SHA384.der", NULL, 0}, #endif #ifdef WOLFSSL_SHA512 /* ECDSA with SHA512 */ {data, (word32)sizeof(data), SHA512h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA512.der"}, + "pkcs7signedData_ECDSA_SHA512.der", NULL, 0}, #endif #endif /* HAVE_ECC */ }; @@ -19476,6 +19495,17 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7->signedAttribs = testVectors[i].signedAttribs; pkcs7->signedAttribsSz = testVectors[i].signedAttribsSz; + /* optional custom contentType, default is DATA */ + if (testVectors[i].contentType != NULL) { + ret = wc_PKCS7_SetContentType(pkcs7, testVectors[i].contentType, + testVectors[i].contentTypeSz); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9411; + } + } + /* generate senderNonce */ { senderNonce[0] = 0x04; @@ -19485,7 +19515,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9411; + return -9412; } } @@ -19508,7 +19538,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9412; + return -9413; } wc_ShaUpdate(&sha, pkcs7->publicKey, pkcs7->publicKeySz); wc_ShaFinal(&sha, digest); @@ -19518,7 +19548,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9413; + return -9414; } wc_Sha256Update(&sha, pkcs7->publicKey, pkcs7->publicKeySz); wc_Sha256Final(&sha, digest); @@ -19534,7 +19564,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (encodedSz < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9414; + return -9415; } #ifdef PKCS7_OUTPUT_TEST_BUNDLES @@ -19543,14 +19573,14 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (!file) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9415; + return -9416; } ret = (int)fwrite(out, 1, encodedSz, file); fclose(file); if (ret != (int)encodedSz) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9416; + return -9417; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ @@ -19558,20 +19588,31 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); if (pkcs7 == NULL) - return -9410; + return -9418; wc_PKCS7_InitWithCert(pkcs7, NULL, 0); ret = wc_PKCS7_VerifySignedData(pkcs7, out, outSz); if (ret < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9417; + return -9419; } + /* verify contentType extracted successfully for custom content types */ + if (testVectors[i].contentTypeSz > 0) { + if (pkcs7->contentTypeSz != testVectors[i].contentTypeSz) { + return -9420; + } else if (XMEMCMP(pkcs7->contentType, testVectors[i].contentType, + pkcs7->contentTypeSz) != 0) { + return -9421; + } + } + + if (pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9418; + return -9422; } { @@ -19590,13 +19631,13 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, NULL, (word32*)&bufSz) != LENGTH_ONLY_E) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9419; + return -9423; } if (bufSz > (int)sizeof(buf)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9420; + return -9424; } bufSz = wc_PKCS7_GetAttributeValue(pkcs7, oidPt, oidSz, @@ -19605,7 +19646,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, (testVectors[i].signedAttribs == NULL && bufSz > 0)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9421; + return -9425; } } @@ -19614,7 +19655,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (!file) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9422; + return -9426; } ret = (int)fwrite(pkcs7->singleCert, 1, pkcs7->singleCertSz, file); fclose(file); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 382698d75..4eeea1ceb 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -276,7 +276,7 @@ enum Misc_ASN { #endif /* Max total extensions, id + len + others */ #endif -#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) +#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) || defined(HAVE_PKCS7) MAX_OID_SZ = 32, /* Max DER length of OID*/ MAX_OID_STRING_SZ = 64, /* Max string length representation of OID*/ #endif @@ -285,7 +285,8 @@ enum Misc_ASN { MAX_KEYUSAGE_SZ = 18, /* Max encoded Key Usage length */ MAX_EXTKEYUSAGE_SZ = 12 + (6 * (8 + 2)) + CTC_MAX_EKU_OID_SZ, /* Max encoded ExtKeyUsage - (SEQ/LEN + OBJID + OCTSTR/LEN + SEQ + (6 * (SEQ + OID))) */ + (SEQ/LEN + OBJID + OCTSTR/LEN + SEQ + + (6 * (SEQ + OID))) */ MAX_CERTPOL_NB = CTC_MAX_CERTPOL_NB,/* Max number of Cert Policy */ MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ, #endif @@ -303,8 +304,8 @@ enum Misc_ASN { #endif TRAILING_ZERO = 1, /* Used for size of zero pad */ MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */ -#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \ - defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) +#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) MAX_TIME_STRING_SZ = 25, /* Max length of formatted time string */ #endif @@ -1012,6 +1013,8 @@ WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, WOLFSSL_LOCAL int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz); #endif +WOLFSSL_LOCAL int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx); WOLFSSL_LOCAL int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, word32 oidType, word32 maxIdx); WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 41a39e757..43f7a22ad 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -147,6 +147,9 @@ typedef struct PKCS7 { word16 isDynamic:1; word16 noDegenerate:1; /* allow degenerate case in verify function */ + byte contentType[MAX_OID_SZ]; /* custom contentType byte array */ + word32 contentTypeSz; /* size of contentType, bytes */ + /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ } PKCS7; @@ -177,6 +180,8 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz); +WOLFSSL_API int wc_PKCS7_SetContentType(PKCS7* pkcs7, byte* contentType, + word32 sz); WOLFSSL_API int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz); WOLFSSL_API int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, word32 blockSz); From 2a60fbd7664796b8e964502aed0d65fea5fd3bca Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Tue, 14 Aug 2018 15:28:25 -0600 Subject: [PATCH 02/56] add support for SubjectKeyIdentifier in CMS SignedData SignerInfo --- Makefile.am | 2 + wolfcrypt/src/pkcs7.c | 143 ++++++++++++++++++++++++++++++++------ wolfcrypt/test/test.c | 83 ++++++++++++++-------- wolfssl/wolfcrypt/pkcs7.h | 10 +++ 4 files changed, 188 insertions(+), 50 deletions(-) diff --git a/Makefile.am b/Makefile.am index b9d60b6da..320115dbb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -60,6 +60,7 @@ CLEANFILES+= cert.der \ pkcs7signedData_RSA_SHA224.der \ pkcs7signedData_RSA_SHA256.der \ pkcs7signedData_RSA_SHA256_custom_contentType.der \ + pkcs7signedData_RSA_SHA256_SKID.der \ pkcs7signedData_RSA_SHA384.der \ pkcs7signedData_RSA_SHA512.der \ pkcs7signedData_ECDSA_SHA.der \ @@ -67,6 +68,7 @@ CLEANFILES+= cert.der \ pkcs7signedData_ECDSA_SHA224.der \ pkcs7signedData_ECDSA_SHA256.der \ pkcs7signedData_ECDSA_SHA256_custom_contentType.der \ + pkcs7signedData_ECDSA_SHA256_SKID.der \ pkcs7signedData_ECDSA_SHA384.der \ pkcs7signedData_ECDSA_SHA512.der diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 2d4f2cc45..da38e586e 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -327,6 +327,11 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) pkcs7->issuerSz = dCert->issuerRawLen; XMEMCPY(pkcs7->issuerSn, dCert->serial, dCert->serialSz); pkcs7->issuerSnSz = dCert->serialSz; + XMEMCPY(pkcs7->issuerSubjKeyId, dCert->extSubjKeyId, KEYID_SIZE); + + /* default to IssuerAndSerialNumber for SignerIdentifier */ + pkcs7->sidType = SID_ISSUER_AND_SERIAL_NUMBER; + FreeDecodedCert(dCert); #ifdef WOLFSSL_SMALL_STACK @@ -537,9 +542,13 @@ typedef struct ESD { byte signerInfoSet[MAX_SET_SZ]; byte signerInfoSeq[MAX_SEQ_SZ]; byte signerVersion[MAX_VERSION_SZ]; + /* issuerAndSerialNumber ...*/ byte issuerSnSeq[MAX_SEQ_SZ]; byte issuerName[MAX_SEQ_SZ]; byte issuerSn[MAX_SN_SZ]; + /* OR subjectKeyIdentifier */ + byte issuerSKIDSeq[MAX_SEQ_SZ]; + byte issuerSKID[MAX_OCTET_STR_SZ]; byte signerDigAlgoId[MAX_ALGO_SZ]; byte digEncAlgoId[MAX_ALGO_SZ]; byte signedAttribSet[MAX_SET_SZ]; @@ -549,8 +558,8 @@ typedef struct ESD { word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz, singleDigAlgoIdSz, certsSetSz; word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz, - issuerSnSeqSz, issuerNameSz, issuerSnSz, - signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz; + issuerSnSeqSz, issuerNameSz, issuerSnSz, issuerSKIDSz, + issuerSKIDSeqSz, signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz; word32 encContentDigestSz, signedAttribsSz, signedAttribsCount, signedAttribSetSz; } ESD; @@ -1058,6 +1067,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, int digEncAlgoId, digEncAlgoType; byte* flatSignedAttribs = NULL; word32 flatSignedAttribsSz = 0; + word32 innerOidSz = sizeof(innerOid); word32 outerOidSz = sizeof(outerOid); if (pkcs7 == NULL || pkcs7->contentSz == 0 || @@ -1101,14 +1111,34 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, pkcs7->contentTypeSz + esd->innerContSeqSz, esd->contentInfoSeq); - esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, - esd->issuerSn, MAX_SN_SZ); - signerInfoSz += esd->issuerSnSz; - esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName); - signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz; - esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq); - signerInfoSz += esd->issuerSnSeqSz; - esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0); + /* SignerIdentifier */ + if (pkcs7->sidType == SID_ISSUER_AND_SERIAL_NUMBER) { + /* IssuerAndSerialNumber */ + esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, + esd->issuerSn, MAX_SN_SZ); + signerInfoSz += esd->issuerSnSz; + esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName); + signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz; + esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq); + signerInfoSz += esd->issuerSnSeqSz; + + /* version MUST be 1 */ + esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0); + + } else if (pkcs7->sidType == SID_SUBJECT_KEY_IDENTIFIER) { + /* SubjectKeyIdentifier */ + esd->issuerSKIDSz = SetOctetString(KEYID_SIZE, esd->issuerSKID); + esd->issuerSKIDSeqSz = SetExplicit(0, esd->issuerSKIDSz + KEYID_SIZE, + esd->issuerSKIDSeq); + signerInfoSz += (esd->issuerSKIDSz + esd->issuerSKIDSeqSz + + KEYID_SIZE); + + /* version MUST be 3 */ + esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0); + } else { + return SKID_E; + } + signerInfoSz += esd->signerVersionSz; esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId, oidHashType, 0); @@ -1250,14 +1280,28 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, idx += esd->signerInfoSeqSz; XMEMCPY(output2 + idx, esd->signerVersion, esd->signerVersionSz); idx += esd->signerVersionSz; - XMEMCPY(output2 + idx, esd->issuerSnSeq, esd->issuerSnSeqSz); - idx += esd->issuerSnSeqSz; - XMEMCPY(output2 + idx, esd->issuerName, esd->issuerNameSz); - idx += esd->issuerNameSz; - XMEMCPY(output2 + idx, pkcs7->issuer, pkcs7->issuerSz); - idx += pkcs7->issuerSz; - XMEMCPY(output2 + idx, esd->issuerSn, esd->issuerSnSz); - idx += esd->issuerSnSz; + /* SignerIdentifier */ + if (pkcs7->sidType == SID_ISSUER_AND_SERIAL_NUMBER) { + /* IssuerAndSerialNumber */ + XMEMCPY(output2 + idx, esd->issuerSnSeq, esd->issuerSnSeqSz); + idx += esd->issuerSnSeqSz; + XMEMCPY(output2 + idx, esd->issuerName, esd->issuerNameSz); + idx += esd->issuerNameSz; + XMEMCPY(output2 + idx, pkcs7->issuer, pkcs7->issuerSz); + idx += pkcs7->issuerSz; + XMEMCPY(output2 + idx, esd->issuerSn, esd->issuerSnSz); + idx += esd->issuerSnSz; + } else if (pkcs7->sidType == SID_SUBJECT_KEY_IDENTIFIER) { + /* SubjectKeyIdentifier */ + XMEMCPY(output2 + idx, esd->issuerSKIDSeq, esd->issuerSKIDSeqSz); + idx += esd->issuerSKIDSeqSz; + XMEMCPY(output2 + idx, esd->issuerSKID, esd->issuerSKIDSz); + idx += esd->issuerSKIDSz; + XMEMCPY(output2 + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE); + idx += KEYID_SIZE; + } else { + return SKID_E; + } XMEMCPY(output2 + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz); idx += esd->signerDigAlgoIdSz; @@ -2048,7 +2092,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, /* Get the inner ContentInfo contentType */ { - word32 localIdx = idx; + localIdx = idx; if (GetASNObjectId(pkiMsg, &idx, &length, pkiMsgSz) != 0) return ASN_PARSE_E; @@ -2299,11 +2343,44 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (GetMyVersion(pkiMsg2, &idx, &version, pkiMsg2Sz) < 0) return ASN_PARSE_E; - if (version != 1) { - WOLFSSL_MSG("PKCS#7 signerInfo needs to be of version 1"); + if (version == 1) { + /* Get the sequence of IssuerAndSerialNumber */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* Skip it */ + idx += length; + + } else if (version == 3) { + /* Get the sequence of SubjectKeyIdentifier */ + if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + /* Skip it */ + idx += length; + + } else { + WOLFSSL_MSG("PKCS#7 signerInfo version must be 1 or 3"); return ASN_VERSION_E; } + /* Get the sequence of digestAlgorithm */ + if (GetAlgoId(pkiMsg2, &idx, &hashOID, oidHashType, pkiMsg2Sz) < 0) { + return ASN_PARSE_E; + } + pkcs7->hashOID = (int)hashOID; + /* Get the sequence of IssuerAndSerialNumber */ if (GetSequence(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) return ASN_PARSE_E; @@ -3559,6 +3636,30 @@ static int wc_PKCS7_GenerateIV(PKCS7* pkcs7, WC_RNG* rng, byte* iv, word32 ivSz) } +/* Set SignerIdentifier type to be used in SignedData encoding. Is either + * IssuerAndSerialNumber or SubjectKeyIdentifier. SignedData encoding + * defaults to using IssuerAndSerialNumber unless set with this function. + * + * pkcs7 - pointer to initialized PKCS7 structure + * type - either SID_ISSUER_AND_SERIAL_NUMBER or SID_SUBJECT_KEY_IDENTIFIER + * + * return 0 on success, negative upon error */ +int wc_PKCS7_SetSignerIdentifierType(PKCS7* pkcs7, int type) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + if (type != SID_ISSUER_AND_SERIAL_NUMBER && + type != SID_SUBJECT_KEY_IDENTIFIER) { + return BAD_FUNC_ARG; + } + + pkcs7->sidType = type; + + return 0; +} + + /* Set custom contentType, currently supported with SignedData type * * pkcs7 - pointer to initialized PKCS7 structure diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index ff72d3f27..1a9efe39a 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19300,6 +19300,7 @@ typedef struct { const char* outFileName; byte* contentType; word32 contentTypeSz; + int sidType; } pkcs7SignedVector; @@ -19362,42 +19363,48 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, /* RSA with SHA */ {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA.der", NULL, 0}, + "pkcs7signedData_RSA_SHA.der", NULL, 0, 0}, /* RSA with SHA, no signed attributes */ {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, NULL, 0, - "pkcs7signedData_RSA_SHA_noattr.der", NULL, 0}, + "pkcs7signedData_RSA_SHA_noattr.der", NULL, 0, 0}, #endif #ifdef WOLFSSL_SHA224 /* RSA with SHA224 */ {data, (word32)sizeof(data), SHA224h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA224.der", NULL, 0}, + "pkcs7signedData_RSA_SHA224.der", NULL, 0, 0}, #endif #ifndef NO_SHA256 /* RSA with SHA256 */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA256.der", NULL, 0}, + "pkcs7signedData_RSA_SHA256.der", NULL, 0, 0}, + + /* RSA with SHA256 and SubjectKeyIdentifier in SignerIdentifier */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA256_SKID.der", NULL, 0, + SID_SUBJECT_KEY_IDENTIFIER}, /* RSA with SHA256 and custom contentType */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_RSA_SHA256_custom_contentType.der", customContentType, - sizeof(customContentType)}, + sizeof(customContentType), 0}, #endif #if defined(WOLFSSL_SHA384) /* RSA with SHA384 */ {data, (word32)sizeof(data), SHA384h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA384.der", NULL, 0}, + "pkcs7signedData_RSA_SHA384.der", NULL, 0, 0}, #endif #if defined(WOLFSSL_SHA512) /* RSA with SHA512 */ {data, (word32)sizeof(data), SHA512h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA512.der", NULL, 0}, + "pkcs7signedData_RSA_SHA512.der", NULL, 0, 0}, #endif #endif /* NO_RSA */ @@ -19406,42 +19413,48 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, /* ECDSA with SHA */ {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA.der", NULL, 0}, + "pkcs7signedData_ECDSA_SHA.der", NULL, 0, 0}, /* ECDSA with SHA, no signed attributes */ {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, NULL, 0, - "pkcs7signedData_ECDSA_SHA_noattr.der", NULL, 0}, + "pkcs7signedData_ECDSA_SHA_noattr.der", NULL, 0, 0}, #endif #ifdef WOLFSSL_SHA224 /* ECDSA with SHA224 */ {data, (word32)sizeof(data), SHA224h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA224.der", NULL, 0}, + "pkcs7signedData_ECDSA_SHA224.der", NULL, 0, 0}, #endif #ifndef NO_SHA256 /* ECDSA with SHA256 */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA256.der", NULL, 0}, + "pkcs7signedData_ECDSA_SHA256.der", NULL, 0, 0}, + + /* ECDSA with SHA256 and SubjectKeyIdentifier in SigherIdentifier */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA256_SKID.der", NULL, 0, + SID_SUBJECT_KEY_IDENTIFIER}, /* ECDSA with SHA256 and custom contentType */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_ECDSA_SHA256_custom_contentType.der", - customContentType, sizeof(customContentType)}, + customContentType, sizeof(customContentType), 0}, #endif #ifdef WOLFSSL_SHA384 /* ECDSA with SHA384 */ {data, (word32)sizeof(data), SHA384h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA384.der", NULL, 0}, + "pkcs7signedData_ECDSA_SHA384.der", NULL, 0, 0}, #endif #ifdef WOLFSSL_SHA512 /* ECDSA with SHA512 */ {data, (word32)sizeof(data), SHA512h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA512.der", NULL, 0}, + "pkcs7signedData_ECDSA_SHA512.der", NULL, 0, 0}, #endif #endif /* HAVE_ECC */ }; @@ -19506,6 +19519,18 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, } } + /* set SignerIdentifier to use SubjectKeyIdentifier if desired, + default is IssuerAndSerialNumber */ + if (testVectors[i].sidType == SID_SUBJECT_KEY_IDENTIFIER) { + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, + SID_SUBJECT_KEY_IDENTIFIER); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9412; + } + } + /* generate senderNonce */ { senderNonce[0] = 0x04; @@ -19515,7 +19540,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9412; + return -9413; } } @@ -19538,7 +19563,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9413; + return -9414; } wc_ShaUpdate(&sha, pkcs7->publicKey, pkcs7->publicKeySz); wc_ShaFinal(&sha, digest); @@ -19548,7 +19573,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9414; + return -9415; } wc_Sha256Update(&sha, pkcs7->publicKey, pkcs7->publicKeySz); wc_Sha256Final(&sha, digest); @@ -19564,7 +19589,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (encodedSz < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9415; + return -9416; } #ifdef PKCS7_OUTPUT_TEST_BUNDLES @@ -19573,14 +19598,14 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (!file) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9416; + return -9417; } ret = (int)fwrite(out, 1, encodedSz, file); fclose(file); if (ret != (int)encodedSz) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9417; + return -9418; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ @@ -19588,23 +19613,23 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); if (pkcs7 == NULL) - return -9418; + return -9419; wc_PKCS7_InitWithCert(pkcs7, NULL, 0); ret = wc_PKCS7_VerifySignedData(pkcs7, out, outSz); if (ret < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9419; + return -9420; } /* verify contentType extracted successfully for custom content types */ if (testVectors[i].contentTypeSz > 0) { if (pkcs7->contentTypeSz != testVectors[i].contentTypeSz) { - return -9420; + return -9421; } else if (XMEMCMP(pkcs7->contentType, testVectors[i].contentType, pkcs7->contentTypeSz) != 0) { - return -9421; + return -9422; } } @@ -19612,7 +19637,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9422; + return -9423; } { @@ -19631,13 +19656,13 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, NULL, (word32*)&bufSz) != LENGTH_ONLY_E) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9423; + return -9424; } if (bufSz > (int)sizeof(buf)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9424; + return -9425; } bufSz = wc_PKCS7_GetAttributeValue(pkcs7, oidPt, oidSz, @@ -19646,7 +19671,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, (testVectors[i].signedAttribs == NULL && bufSz > 0)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9425; + return -9426; } } @@ -19655,7 +19680,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (!file) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9426; + return -9427; } ret = (int)fwrite(pkcs7->singleCert, 1, pkcs7->singleCertSz, file); fclose(file); diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 43f7a22ad..6353e14de 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -77,6 +77,10 @@ enum Pkcs7_Misc { MAX_SEQ_SZ + MAX_ALGO_SZ + 1 + MAX_ENCRYPTED_KEY_SZ }; +enum Pkcs7_SignerIdentifier_Types { + SID_ISSUER_AND_SERIAL_NUMBER = 0, + SID_SUBJECT_KEY_IDENTIFIER = 1 +}; typedef struct PKCS7Attrib { const byte* oid; @@ -150,6 +154,11 @@ typedef struct PKCS7 { byte contentType[MAX_OID_SZ]; /* custom contentType byte array */ word32 contentTypeSz; /* size of contentType, bytes */ + int sidType; /* SignerIdentifier type to use, of type + Pkcs7_SignerIdentifier_Types, default to + SID_ISSUER_AND_SERIAL_NUMBER */ + byte issuerSubjKeyId[KEYID_SIZE]; /* SubjectKeyIdentifier of singleCert */ + /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ } PKCS7; @@ -180,6 +189,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz); +WOLFSSL_API int wc_PKCS7_SetSignerIdentifierType(PKCS7* pkcs7, int type); WOLFSSL_API int wc_PKCS7_SetContentType(PKCS7* pkcs7, byte* contentType, word32 sz); WOLFSSL_API int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz); From 32b70dd56ce8f9b3c1f4fcc6441692348faf364f Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 15 Aug 2018 11:15:31 -0600 Subject: [PATCH 03/56] add support for FirmwarePkgData in CMS SignedData EncapsulatedContentInfo --- Makefile.am | 2 ++ wolfcrypt/src/asn.c | 2 +- wolfcrypt/src/pkcs7.c | 70 ++++++++++++++++++++++++++++----------- wolfcrypt/test/test.c | 51 ++++++++++++++++++---------- wolfssl/wolfcrypt/asn.h | 1 + wolfssl/wolfcrypt/pkcs7.h | 15 +++++---- 6 files changed, 95 insertions(+), 46 deletions(-) diff --git a/Makefile.am b/Makefile.am index 320115dbb..875dffc50 100644 --- a/Makefile.am +++ b/Makefile.am @@ -59,6 +59,7 @@ CLEANFILES+= cert.der \ pkcs7signedData_RSA_SHA_noattr.der \ pkcs7signedData_RSA_SHA224.der \ pkcs7signedData_RSA_SHA256.der \ + pkcs7signedData_RSA_SHA256_firmwarePkgData.der \ pkcs7signedData_RSA_SHA256_custom_contentType.der \ pkcs7signedData_RSA_SHA256_SKID.der \ pkcs7signedData_RSA_SHA384.der \ @@ -67,6 +68,7 @@ CLEANFILES+= cert.der \ pkcs7signedData_ECDSA_SHA_noattr.der \ pkcs7signedData_ECDSA_SHA224.der \ pkcs7signedData_ECDSA_SHA256.der \ + pkcs7signedData_ECDSA_SHA256_firmwarePkgData.der \ pkcs7signedData_ECDSA_SHA256_custom_contentType.der \ pkcs7signedData_ECDSA_SHA256_SKID.der \ pkcs7signedData_ECDSA_SHA384.der \ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 8743e7ecb..44278d32f 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1966,7 +1966,7 @@ int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, * output Buffer to write into. * returns the number of bytes added to the buffer. */ -static int SetObjectId(int len, byte* output) +int SetObjectId(int len, byte* output) { int idx = 0; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index da38e586e..3c3866ef0 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -58,7 +58,7 @@ typedef enum { /* placed ASN.1 contentType OID into *output, return idx on success, * 0 upon failure */ -static int wc_SetContentType(int pkcs7TypeOID, byte* output) +static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) { /* PKCS#7 content types, RFC 2315, section 14 */ const byte pkcs7[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, @@ -73,14 +73,16 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output) 0x0D, 0x01, 0x07, 0x04 }; const byte digestedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x05 }; - #ifndef NO_PKCS7_ENCRYPTED_DATA const byte encryptedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 }; #endif + /* FirmwarePkgData (1.2.840.113549.1.9.16.1.16), from RFC 4108 */ + const byte firmwarePkgData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x10, 0x01, 0x10 }; - int idSz; - int typeSz = 0, idx = 0; + int idSz, idx = 0; + word32 typeSz = 0; const byte* typeName = 0; byte ID_Length[MAX_LENGTH_SZ]; @@ -121,12 +123,19 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output) typeName = encryptedData; break; #endif + case FIRMWARE_PKG_DATA: + typeSz = sizeof(firmwarePkgData); + typeName = firmwarePkgData; + break; default: WOLFSSL_MSG("Unknown PKCS#7 Type"); return 0; }; + if (outputSz < (MAX_LENGTH_SZ + 1 + typeSz)) + return BAD_FUNC_ARG; + idSz = SetLength(typeSz, ID_Length); output[idx++] = ASN_OBJECT_ID; XMEMCPY(output + idx, ID_Length, idSz); @@ -1046,11 +1055,6 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02 }; - /* default id-data OID (1.2.840.113549.1.7.1), user can override */ - const byte innerOid[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01 }; - /* contentType OID (1.2.840.113549.1.9.3) */ const byte contentTypeOid[] = { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, @@ -1087,10 +1091,21 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, XMEMSET(esd, 0, sizeof(ESD)); - /* use default DATA contentType if not set by user */ + /* set content type based on contentOID, unless user has set custom one + with wc_PKCS7_SetContentType() */ if (pkcs7->contentTypeSz == 0) { - XMEMCPY(pkcs7->contentType, innerOid, sizeof(innerOid)); - pkcs7->contentTypeSz = sizeof(innerOid); + + /* default to DATA content type if user has not set */ + if (pkcs7->contentOID == 0) { + pkcs7->contentOID = DATA; + } + + ret = wc_SetContentType(pkcs7->contentOID, pkcs7->contentType, + sizeof(pkcs7->contentType)); + if (ret < 0) + return ret; + + pkcs7->contentTypeSz = ret; } esd->hashType = wc_OidGetHash(pkcs7->hashOID); @@ -3784,7 +3799,12 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) return blockSz; /* outer content type */ - outerContentTypeSz = wc_SetContentType(ENVELOPED_DATA, outerContentType); + ret = wc_SetContentType(ENVELOPED_DATA, outerContentType, + sizeof(outerContentType)); + if (ret < 0) + return ret; + + outerContentTypeSz = ret; /* version, defined as 0 in RFC 2315 */ #ifdef HAVE_ECC @@ -3877,13 +3897,15 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* EncryptedContentInfo */ - contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType); - if (contentTypeSz == 0) { + ret = wc_SetContentType(pkcs7->contentOID, contentType, + sizeof(contentType)); + if (ret < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return BAD_FUNC_ARG; + return ret; } + contentTypeSz = ret; /* allocate encrypted content buffer and PKCS#7 padding */ padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz); @@ -5081,7 +5103,12 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) return BAD_FUNC_ARG; /* outer content type */ - outerContentTypeSz = wc_SetContentType(ENCRYPTED_DATA, outerContentType); + ret = wc_SetContentType(ENCRYPTED_DATA, outerContentType, + sizeof(outerContentType)); + if (ret < 0) + return ret; + + outerContentTypeSz = ret; /* version, 2 if unprotectedAttrs present, 0 if absent */ if (pkcs7->unprotectedAttribsSz > 0) { @@ -5091,9 +5118,12 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* EncryptedContentInfo */ - contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType); - if (contentTypeSz == 0) - return BAD_FUNC_ARG; + contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType, + sizeof(contentType)); + if (ret < 0) + return ret; + + contentTypeSz = ret; /* allocate encrypted content buffer, do PKCS#7 padding */ blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 1a9efe39a..c550d3c34 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19298,6 +19298,7 @@ typedef struct { PKCS7Attrib* signedAttribs; word32 signedAttribsSz; const char* outFileName; + int contentOID; byte* contentType; word32 contentTypeSz; int sidType; @@ -19363,48 +19364,54 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, /* RSA with SHA */ {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA.der", NULL, 0, 0}, + "pkcs7signedData_RSA_SHA.der", 0, NULL, 0, 0}, /* RSA with SHA, no signed attributes */ {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, NULL, 0, - "pkcs7signedData_RSA_SHA_noattr.der", NULL, 0, 0}, + "pkcs7signedData_RSA_SHA_noattr.der", 0, NULL, 0, 0}, #endif #ifdef WOLFSSL_SHA224 /* RSA with SHA224 */ {data, (word32)sizeof(data), SHA224h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA224.der", NULL, 0, 0}, + "pkcs7signedData_RSA_SHA224.der", 0, NULL, 0, 0}, #endif #ifndef NO_SHA256 /* RSA with SHA256 */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA256.der", NULL, 0, 0}, + "pkcs7signedData_RSA_SHA256.der", 0, NULL, 0, 0}, /* RSA with SHA256 and SubjectKeyIdentifier in SignerIdentifier */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA256_SKID.der", NULL, 0, + "pkcs7signedData_RSA_SHA256_SKID.der", 0, NULL, 0, SID_SUBJECT_KEY_IDENTIFIER}, /* RSA with SHA256 and custom contentType */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA256_custom_contentType.der", customContentType, - sizeof(customContentType), 0}, + "pkcs7signedData_RSA_SHA256_custom_contentType.der", 0, + customContentType, sizeof(customContentType), 0}, + + /* RSA with SHA256 and FirmwarePkgData contentType */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA256_firmwarePkgData.der", + FIRMWARE_PKG_DATA, NULL, 0, 0}, #endif #if defined(WOLFSSL_SHA384) /* RSA with SHA384 */ {data, (word32)sizeof(data), SHA384h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA384.der", NULL, 0, 0}, + "pkcs7signedData_RSA_SHA384.der", 0, NULL, 0, 0}, #endif #if defined(WOLFSSL_SHA512) /* RSA with SHA512 */ {data, (word32)sizeof(data), SHA512h, RSAk, rsaPrivKey, rsaPrivKeySz, rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA512.der", NULL, 0, 0}, + "pkcs7signedData_RSA_SHA512.der", 0, NULL, 0, 0}, #endif #endif /* NO_RSA */ @@ -19413,48 +19420,54 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, /* ECDSA with SHA */ {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA.der", NULL, 0, 0}, + "pkcs7signedData_ECDSA_SHA.der", 0, NULL, 0, 0}, /* ECDSA with SHA, no signed attributes */ {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, NULL, 0, - "pkcs7signedData_ECDSA_SHA_noattr.der", NULL, 0, 0}, + "pkcs7signedData_ECDSA_SHA_noattr.der", 0, NULL, 0, 0}, #endif #ifdef WOLFSSL_SHA224 /* ECDSA with SHA224 */ {data, (word32)sizeof(data), SHA224h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA224.der", NULL, 0, 0}, + "pkcs7signedData_ECDSA_SHA224.der", 0, NULL, 0, 0}, #endif #ifndef NO_SHA256 /* ECDSA with SHA256 */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA256.der", NULL, 0, 0}, + "pkcs7signedData_ECDSA_SHA256.der", 0, NULL, 0, 0}, /* ECDSA with SHA256 and SubjectKeyIdentifier in SigherIdentifier */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA256_SKID.der", NULL, 0, + "pkcs7signedData_ECDSA_SHA256_SKID.der", 0, NULL, 0, SID_SUBJECT_KEY_IDENTIFIER}, /* ECDSA with SHA256 and custom contentType */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA256_custom_contentType.der", + "pkcs7signedData_ECDSA_SHA256_custom_contentType.der", 0, customContentType, sizeof(customContentType), 0}, + + /* ECDSA with SHA256 and FirmwarePkgData contentType */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA256_firmwarePkgData.der", + FIRMWARE_PKG_DATA, NULL, 0, 0}, #endif #ifdef WOLFSSL_SHA384 /* ECDSA with SHA384 */ {data, (word32)sizeof(data), SHA384h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA384.der", NULL, 0, 0}, + "pkcs7signedData_ECDSA_SHA384.der", 0, NULL, 0, 0}, #endif #ifdef WOLFSSL_SHA512 /* ECDSA with SHA512 */ {data, (word32)sizeof(data), SHA512h, ECDSAk, eccPrivKey, eccPrivKeySz, eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA512.der", NULL, 0, 0}, + "pkcs7signedData_ECDSA_SHA512.der", 0, NULL, 0, 0}, #endif #endif /* HAVE_ECC */ }; @@ -19503,12 +19516,14 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7->contentSz = testVectors[i].contentSz; pkcs7->hashOID = testVectors[i].hashOID; pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->contentOID = testVectors[i].contentOID; pkcs7->privateKey = testVectors[i].privateKey; pkcs7->privateKeySz = testVectors[i].privateKeySz; pkcs7->signedAttribs = testVectors[i].signedAttribs; pkcs7->signedAttribsSz = testVectors[i].signedAttribsSz; - /* optional custom contentType, default is DATA */ + /* optional custom contentType, default is DATA, + overrides contentOID if set */ if (testVectors[i].contentType != NULL) { ret = wc_PKCS7_SetContentType(pkcs7, testVectors[i].contentType, testVectors[i].contentTypeSz); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 4eeea1ceb..009c9f501 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1015,6 +1015,7 @@ WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, #endif WOLFSSL_LOCAL int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, word32 maxIdx); +WOLFSSL_LOCAL int SetObjectId(int len, byte* output); WOLFSSL_LOCAL int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, word32 oidType, word32 maxIdx); WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 6353e14de..8d6fd0c32 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -53,13 +53,14 @@ /* PKCS#7 content types, ref RFC 2315 (Section 14) */ enum PKCS7_TYPES { - PKCS7_MSG = 650, /* 1.2.840.113549.1.7 */ - DATA = 651, /* 1.2.840.113549.1.7.1 */ - SIGNED_DATA = 652, /* 1.2.840.113549.1.7.2 */ - ENVELOPED_DATA = 653, /* 1.2.840.113549.1.7.3 */ - SIGNED_AND_ENVELOPED_DATA = 654, /* 1.2.840.113549.1.7.4 */ - DIGESTED_DATA = 655, /* 1.2.840.113549.1.7.5 */ - ENCRYPTED_DATA = 656 /* 1.2.840.113549.1.7.6 */ + PKCS7_MSG = 650, /* 1.2.840.113549.1.7 */ + DATA = 651, /* 1.2.840.113549.1.7.1 */ + SIGNED_DATA = 652, /* 1.2.840.113549.1.7.2 */ + ENVELOPED_DATA = 653, /* 1.2.840.113549.1.7.3 */ + SIGNED_AND_ENVELOPED_DATA = 654, /* 1.2.840.113549.1.7.4 */ + DIGESTED_DATA = 655, /* 1.2.840.113549.1.7.5 */ + ENCRYPTED_DATA = 656, /* 1.2.840.113549.1.7.6 */ + FIRMWARE_PKG_DATA = 685 /* 1.2.840.113549.1.9.16.1.16, RFC 4108 */ }; enum Pkcs7_Misc { From c51cf4472ef88d534b98a4684557f19e732286fb Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 17 Aug 2018 10:52:18 -0600 Subject: [PATCH 04/56] add support for CMS CompressedData content type --- Makefile.am | 2 + wolfcrypt/src/asn.c | 16 +++ wolfcrypt/src/pkcs7.c | 280 +++++++++++++++++++++++++++++++++++++- wolfcrypt/test/test.c | 117 +++++++++++++++- wolfssl/wolfcrypt/asn.h | 7 + wolfssl/wolfcrypt/pkcs7.h | 11 ++ 6 files changed, 421 insertions(+), 12 deletions(-) diff --git a/Makefile.am b/Makefile.am index 875dffc50..00928d2a6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,10 +39,12 @@ CLEANFILES+= cert.der \ othercert.der \ othercert.pem \ pkcs7cert.der \ + pkcs7compressedData_zlib.der \ pkcs7encryptedDataAES128CBC.der \ pkcs7encryptedDataAES192CBC.der \ pkcs7encryptedDataAES256CBC_attribs.der \ pkcs7encryptedDataAES256CBC.der \ + pkcs7encryptedDataAES256CBC_firmwarePkgData.der \ pkcs7encryptedDataAES256CBC_multi_attribs.der \ pkcs7encryptedDataDES3.der \ pkcs7encryptedDataDES.der \ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 44278d32f..cc51ad2a1 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1319,6 +1319,11 @@ static const byte pbeSha1RC4128[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 1}; static const byte pbeSha1Des3[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 3}; #endif +#ifdef HAVE_LIBZ +/* zlib compression */ +static const byte zlibCompress[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3, 8}; +#endif + /* returns a pointer to the OID string on success and NULL on fail */ const byte* OidFromId(word32 id, word32 type, word32* oidSz) @@ -1805,6 +1810,17 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) break; #endif /* !NO_HMAC */ +#ifdef HAVE_LIBZ + case oidCompressType: + switch (id) { + case ZLIBc: + oid = zlibCompress; + *oidSz = sizeof(zlibCompress); + break; + } + break; +#endif /* HAVE_LIBZ */ + case oidIgnoreType: default: break; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 3c3866ef0..db847d014 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -38,6 +38,9 @@ #ifdef HAVE_ECC #include #endif +#ifdef HAVE_LIBZ + #include +#endif #ifdef NO_INLINE #include #else @@ -77,9 +80,14 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) const byte encryptedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06 }; #endif - /* FirmwarePkgData (1.2.840.113549.1.9.16.1.16), from RFC 4108 */ - const byte firmwarePkgData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, - 0x0D, 0x01, 0x09, 0x10, 0x01, 0x10 }; + /* FirmwarePkgData (1.2.840.113549.1.9.16.1.16), RFC 4108 */ + const byte firmwarePkgData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x01, 0x10 }; +#ifdef HAVE_LIBZ + /* id-ct-compressedData (1.2.840.113549.1.9.16.1.9), RFC 3274 */ + const byte compressedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x01, 0x09 }; +#endif int idSz, idx = 0; word32 typeSz = 0; @@ -122,6 +130,12 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) typeSz = sizeof(encryptedData); typeName = encryptedData; break; +#endif +#ifdef HAVE_LIBZ + case COMPRESSED_DATA: + typeSz = sizeof(compressedData); + typeName = compressedData; + break; #endif case FIRMWARE_PKG_DATA: typeSz = sizeof(firmwarePkgData); @@ -5080,7 +5094,7 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) int encContentOctetSz, encContentSeqSz, contentTypeSz; int contentEncAlgoSz, ivOctetStringSz; byte encContentSeq[MAX_SEQ_SZ]; - byte contentType[MAX_ALGO_SZ]; + byte contentType[MAX_OID_SZ]; byte contentEncAlgo[MAX_ALGO_SZ]; byte tmpIv[MAX_CONTENT_IV_SIZE]; byte ivOctetString[MAX_OCTET_STR_SZ]; @@ -5118,8 +5132,8 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* EncryptedContentInfo */ - contentTypeSz = wc_SetContentType(pkcs7->contentOID, contentType, - sizeof(contentType)); + ret = wc_SetContentType(pkcs7->contentOID, contentType, + sizeof(contentType)); if (ret < 0) return ret; @@ -5356,6 +5370,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, if (pkiMsg == NULL || pkiMsgSz == 0 || output == NULL || outputSz == 0) return BAD_FUNC_ARG; + /* read past ContentInfo, verify type is encrypted-data */ if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; @@ -5473,6 +5488,259 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, #endif /* NO_PKCS7_ENCRYPTED_DATA */ +#ifdef HAVE_LIBZ + +/* build PKCS#7 compressedData content type, return encrypted size */ +int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz) +{ + byte contentInfoSeq[MAX_SEQ_SZ]; + byte contentInfoTypeOid[MAX_OID_SZ]; + byte contentInfoContentSeq[MAX_SEQ_SZ]; /* EXPLICIT [0] */ + byte compressedDataSeq[MAX_SEQ_SZ]; + byte cmsVersion[MAX_VERSION_SZ]; + byte compressAlgId[MAX_ALGO_SZ]; + byte encapContentInfoSeq[MAX_SEQ_SZ]; + byte contentTypeOid[MAX_OID_SZ]; + byte contentSeq[MAX_SEQ_SZ]; /* EXPLICIT [0] */ + byte contentOctetStr[MAX_OCTET_STR_SZ]; + + int ret; + word32 totalSz, idx; + word32 contentInfoSeqSz, contentInfoContentSeqSz, contentInfoTypeOidSz; + word32 compressedDataSeqSz, cmsVersionSz, compressAlgIdSz; + word32 encapContentInfoSeqSz, contentTypeOidSz, contentSeqSz; + word32 contentOctetStrSz; + + byte* compressed; + word32 compressedSz; + + if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || + output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* allocate space for compressed content. The libz code says the compressed + * buffer should be srcSz + 0.1% + 12. */ + compressedSz = (pkcs7->contentSz + (word32)(pkcs7->contentSz * 0.001) + 12); + compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (compressed == NULL) { + WOLFSSL_MSG("Error allocating memory for CMS compressed content"); + return MEMORY_E; + } + + /* compress content */ + ret = wc_Compress(compressed, compressedSz, pkcs7->content, + pkcs7->contentSz, 0); + if (ret < 0) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + compressedSz = (word32)ret; + + /* eContent OCTET STRING, working backwards */ + contentOctetStrSz = SetOctetString(compressedSz, contentOctetStr); + totalSz = contentOctetStrSz + compressedSz; + + /* EXPLICIT [0] eContentType */ + contentSeqSz = SetExplicit(0, totalSz, contentSeq); + totalSz += contentSeqSz; + + /* eContentType OBJECT IDENTIFIER */ + ret = wc_SetContentType(pkcs7->contentOID, contentTypeOid, + sizeof(contentTypeOid)); + if (ret < 0) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + contentTypeOidSz = ret; + totalSz += contentTypeOidSz; + + /* EncapsulatedContentInfo SEQUENCE */ + encapContentInfoSeqSz = SetSequence(totalSz, encapContentInfoSeq); + totalSz += encapContentInfoSeqSz; + + /* compressionAlgorithm AlgorithmIdentifier */ + /* Only supports zlib for compression currently: + * id-alg-zlibCompress (1.2.840.113549.1.9.16.3.8) */ + compressAlgIdSz = SetAlgoID(ZLIBc, compressAlgId, oidCompressType, 0); + totalSz += compressAlgIdSz; + + /* version */ + cmsVersionSz = SetMyVersion(0, cmsVersion, 0); + totalSz += cmsVersionSz; + + /* CompressedData SEQUENCE */ + compressedDataSeqSz = SetSequence(totalSz, compressedDataSeq); + totalSz += compressedDataSeqSz; + + /* ContentInfo content EXPLICIT SEQUENCE */ + contentInfoContentSeqSz = SetExplicit(0, totalSz, contentInfoContentSeq); + totalSz += contentInfoContentSeqSz; + + /* ContentInfo ContentType (compressedData) */ + ret = wc_SetContentType(COMPRESSED_DATA, contentInfoTypeOid, + sizeof(contentInfoTypeOid)); + if (ret < 0) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + contentInfoTypeOidSz = ret; + totalSz += contentInfoTypeOidSz; + + /* ContentInfo SEQUENCE */ + contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); + totalSz += contentInfoSeqSz; + + if (outputSz < totalSz) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + idx = 0; + XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); + idx += contentInfoSeqSz; + XMEMCPY(output + idx, contentInfoTypeOid, contentInfoTypeOidSz); + idx += contentInfoTypeOidSz; + XMEMCPY(output + idx, contentInfoContentSeq, contentInfoContentSeqSz); + idx += contentInfoContentSeqSz; + XMEMCPY(output + idx, compressedDataSeq, compressedDataSeqSz); + idx += compressedDataSeqSz; + XMEMCPY(output + idx, cmsVersion, cmsVersionSz); + idx += cmsVersionSz; + XMEMCPY(output + idx, compressAlgId, compressAlgIdSz); + idx += compressAlgIdSz; + XMEMCPY(output + idx, encapContentInfoSeq, encapContentInfoSeqSz); + idx += encapContentInfoSeqSz; + XMEMCPY(output + idx, contentTypeOid, contentTypeOidSz); + idx += contentTypeOidSz; + XMEMCPY(output + idx, contentSeq, contentSeqSz); + idx += contentSeqSz; + XMEMCPY(output + idx, contentOctetStr, contentOctetStrSz); + idx += contentOctetStrSz; + XMEMCPY(output + idx, compressed, compressedSz); + idx += compressedSz; + + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + return idx; +} + +/* unwrap and decompress PKCS#7/CMS compressedData object, + * returned decoded size */ +int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, + byte* output, word32 outputSz) +{ + int length, version, ret; + word32 idx = 0, algOID, contentType; + + byte* decompressed; + word32 decompressedSz; + + if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || + output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* get ContentInfo SEQUENCE */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get ContentInfo contentType */ + if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (contentType != COMPRESSED_DATA) { + printf("ContentInfo not of type CompressedData"); + return ASN_PARSE_E; + } + + /* get ContentInfo content EXPLICIT SEQUENCE */ + if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get CompressedData SEQUENCE */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get version */ + if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (version != 0) { + WOLFSSL_MSG("CMS CompressedData version MUST be 0, but is not"); + return ASN_PARSE_E; + } + + /* get CompressionAlgorithmIdentifier */ + if (GetAlgoId(pkiMsg, &idx, &algOID, oidIgnoreType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* Only supports zlib for compression currently: + * id-alg-zlibCompress (1.2.840.113549.1.9.16.3.8) */ + if (algOID != ZLIBc) { + WOLFSSL_MSG("CMS CompressedData only supports zlib algorithm"); + return ASN_PARSE_E; + } + + /* get EncapsulatedContentInfo SEQUENCE */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get ContentType OID */ + if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + pkcs7->contentOID = contentType; + + /* get eContent EXPLICIT SEQUENCE */ + if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get content OCTET STRING */ + if (pkiMsg[idx++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* allocate space for decompressed data */ + decompressed = (byte*)XMALLOC(length, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (decompressed == NULL) { + WOLFSSL_MSG("Error allocating memory for CMS decompression buffer"); + return MEMORY_E; + } + + /* decompress content */ + ret = wc_DeCompress(decompressed, length, &pkiMsg[idx], length); + if (ret < 0) { + XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + decompressedSz = (word32)ret; + + /* get content */ + if (outputSz < decompressedSz) { + WOLFSSL_MSG("CMS output buffer too small to hold decompressed data"); + XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + XMEMCPY(output, decompressed, decompressedSz); + XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + return decompressedSz; +} + +#endif /* HAVE_LIBZ */ + #else /* HAVE_PKCS7 */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index c550d3c34..7b3f54796 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -326,6 +326,9 @@ int scrypt_test(void); #ifndef NO_PKCS7_ENCRYPTED_DATA int pkcs7encrypted_test(void); #endif + #ifdef HAVE_LIBZ + int pkcs7compressed_test(void); + #endif #endif #if !defined(NO_ASN_TIME) && !defined(NO_RSA) && defined(WOLFSSL_TEST_CERT) int cert_test(void); @@ -949,20 +952,26 @@ initDefaultName(); #ifdef HAVE_PKCS7 if ( (ret = pkcs7enveloped_test()) != 0) - return err_sys("PKCS7enveloped test failed!\n", ret); + return err_sys("PKCS7enveloped test failed!\n", ret); else - printf( "PKCS7enveloped test passed!\n"); + printf( "PKCS7enveloped test passed!\n"); if ( (ret = pkcs7signed_test()) != 0) - return err_sys("PKCS7signed test failed!\n", ret); + return err_sys("PKCS7signed test failed!\n", ret); else - printf( "PKCS7signed test passed!\n"); + printf( "PKCS7signed test passed!\n"); #ifndef NO_PKCS7_ENCRYPTED_DATA if ( (ret = pkcs7encrypted_test()) != 0) - return err_sys("PKCS7encrypted test failed!\n", ret); + return err_sys("PKCS7encrypted test failed!\n", ret); else - printf( "PKCS7encrypted test passed!\n"); + printf( "PKCS7encrypted test passed!\n"); + #endif + #ifdef HAVE_LIBZ + if ( (ret = pkcs7compressed_test()) != 0) + return err_sys("PKCS7compressed test failed!\n", ret); + else + printf( "PKCS7compressed test passed!\n"); #endif #endif @@ -19190,6 +19199,11 @@ int pkcs7encrypted_test(void) sizeof(aes256Key), multiAttribs, (sizeof(multiAttribs)/sizeof(PKCS7Attrib)), "pkcs7encryptedDataAES256CBC_multi_attribs.der"}, + + /* test with contentType set to FirmwarePkgData */ + {data, (word32)sizeof(data), FIRMWARE_PKG_DATA, AES256CBCb, aes256Key, + sizeof(aes256Key), NULL, 0, + "pkcs7encryptedDataAES256CBC_firmwarePkgData.der"}, #endif #endif /* NO_AES */ }; @@ -19286,6 +19300,97 @@ int pkcs7encrypted_test(void) #endif /* NO_PKCS7_ENCRYPTED_DATA */ +#ifdef HAVE_LIBZ + +typedef struct { + const byte* content; + word32 contentSz; + int contentOID; + const char* outFileName; +} pkcs7CompressedVector; + + +int pkcs7compressed_test(void) +{ + int ret = 0; + int i, testSz; + int compressedSz, decodedSz; + PKCS7* pkcs7; + byte compressed[2048]; + byte decoded[2048]; +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + FILE* pkcs7File; +#endif + + const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 + }; + + const pkcs7CompressedVector testVectors[] = + { + {data, (word32)sizeof(data), DATA, "pkcs7compressedData_zlib.der"}, + }; + + testSz = sizeof(testVectors) / sizeof(pkcs7CompressedVector); + + for (i = 0; i < testSz; i++) { + pkcs7 = wc_PKCS7_New(HEAP_HINT, devId); + if (pkcs7 == NULL) + return -9400; + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + + /* encode compressedData */ + compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, compressed, + sizeof(compressed)); + if (compressedSz <= 0) { + wc_PKCS7_Free(pkcs7); + return -9401; + } + + /* decode compressedData */ + decodedSz = wc_PKCS7_DecodeCompressedData(pkcs7, compressed, + compressedSz, decoded, + sizeof(decoded)); + if (decodedSz <= 0){ + wc_PKCS7_Free(pkcs7); + return -9402; + } + + /* test decode result */ + if (XMEMCMP(decoded, testVectors[i].content, + testVectors[i].contentSz) != 0) { + wc_PKCS7_Free(pkcs7); + return -9403; + } + +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* output pkcs7 compressedData for external testing */ + pkcs7File = fopen(testVectors[i].outFileName, "wb"); + if (!pkcs7File) { + wc_PKCS7_Free(pkcs7); + return -9406; + } + + ret = (int)fwrite(compressed, compressedSz, 1, pkcs7File); + fclose(pkcs7File); + + if (ret > 0) + ret = 0; +#endif + + wc_PKCS7_Free(pkcs7); + } + + return ret; +} /* pkcs7compressed_test() */ + +#endif /* HAVE_LIBZ */ + + typedef struct { const byte* content; word32 contentSz; diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 009c9f501..82ef21871 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -332,6 +332,7 @@ enum Oid_Types { oidCmsKeyAgreeType = 13, oidPBEType = 14, oidHmacType = 15, + oidCompressType = 16, oidIgnoreType }; @@ -487,6 +488,12 @@ enum ExtKeyUsage_Sum { /* From RFC 5280 */ EKU_OCSP_SIGN_OID = 79 /* 1.3.6.1.5.5.7.3.9, id-kp-OCSPSigning */ }; +#ifdef HAVE_LIBZ +enum CompressAlg_Sum { + ZLIBc = 679 /* 1.2.840.113549.1.9.16.3.8, id-alg-zlibCompress */ +}; +#endif + enum VerifyType { NO_VERIFY = 0, diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 8d6fd0c32..83460c9b1 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -60,6 +60,9 @@ enum PKCS7_TYPES { SIGNED_AND_ENVELOPED_DATA = 654, /* 1.2.840.113549.1.7.4 */ DIGESTED_DATA = 655, /* 1.2.840.113549.1.7.5 */ ENCRYPTED_DATA = 656, /* 1.2.840.113549.1.7.6 */ +#ifdef HAVE_LIBZ + COMPRESSED_DATA = 678, /* 1.2.840.113549.1.9.16.1.9, RFC 3274 */ +#endif FIRMWARE_PKG_DATA = 685 /* 1.2.840.113549.1.9.16.1.16, RFC 4108 */ }; @@ -205,6 +208,14 @@ WOLFSSL_API int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 outputSz); #endif /* NO_PKCS7_ENCRYPTED_DATA */ +#ifdef HAVE_LIBZ +WOLFSSL_API int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, + word32 outputSz); +WOLFSSL_API int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, + word32 pkiMsgSz, byte* output, + word32 outputSz); +#endif /* HAVE_LIBZ */ + #ifdef __cplusplus } /* extern "C" */ #endif From 6a06a3b63bcaae73b188907aacdef14177800252 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 17 Aug 2018 11:07:54 -0600 Subject: [PATCH 05/56] add CMS CompressedData test using FirmwarePkgData --- Makefile.am | 3 ++- wolfcrypt/test/test.c | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 00928d2a6..57d7bba1b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,7 +39,8 @@ CLEANFILES+= cert.der \ othercert.der \ othercert.pem \ pkcs7cert.der \ - pkcs7compressedData_zlib.der \ + pkcs7compressedData_data_zlib.der \ + pkcs7compressedData_firmwarePkgData_zlib.der \ pkcs7encryptedDataAES128CBC.der \ pkcs7encryptedDataAES192CBC.der \ pkcs7encryptedDataAES256CBC_attribs.der \ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 7b3f54796..73631bf54 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19329,7 +19329,10 @@ int pkcs7compressed_test(void) const pkcs7CompressedVector testVectors[] = { - {data, (word32)sizeof(data), DATA, "pkcs7compressedData_zlib.der"}, + {data, (word32)sizeof(data), DATA, + "pkcs7compressedData_data_zlib.der"}, + {data, (word32)sizeof(data), FIRMWARE_PKG_DATA, + "pkcs7compressedData_firmwarePkgData_zlib.der"}, }; testSz = sizeof(testVectors) / sizeof(pkcs7CompressedVector); From ce1381dc9a9c9855b2ead3d4d33c6f664d3282a9 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 17 Aug 2018 11:18:39 -0600 Subject: [PATCH 06/56] add contentType check to CMS compressed tests --- wolfcrypt/test/test.c | 58 +++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 73631bf54..64d35de6d 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19213,7 +19213,7 @@ int pkcs7encrypted_test(void) for (i = 0; i < testSz; i++) { pkcs7 = wc_PKCS7_New(HEAP_HINT, devId); if (pkcs7 == NULL) - return -9400; + return -9407; pkcs7->content = (byte*)testVectors[i].content; pkcs7->contentSz = testVectors[i].contentSz; @@ -19351,7 +19351,7 @@ int pkcs7compressed_test(void) sizeof(compressed)); if (compressedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9401; + return -9408; } /* decode compressedData */ @@ -19360,22 +19360,26 @@ int pkcs7compressed_test(void) sizeof(decoded)); if (decodedSz <= 0){ wc_PKCS7_Free(pkcs7); - return -9402; + return -9409; } /* test decode result */ if (XMEMCMP(decoded, testVectors[i].content, testVectors[i].contentSz) != 0) { wc_PKCS7_Free(pkcs7); - return -9403; + return -9410; } + /* make sure content type is the same */ + if (testVectors[i].contentOID != pkcs7->contentOID) + return -9411; + #ifdef PKCS7_OUTPUT_TEST_BUNDLES /* output pkcs7 compressedData for external testing */ pkcs7File = fopen(testVectors[i].outFileName, "wb"); if (!pkcs7File) { wc_PKCS7_Free(pkcs7); - return -9406; + return -9412; } ret = (int)fwrite(compressed, compressedSz, 1, pkcs7File); @@ -19585,12 +19589,12 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, outSz = FOURK_BUF; out = (byte*)XMALLOC(outSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (out == NULL) - return -9407; + return -9413; ret = wc_PKCS7_PadData((byte*)data, sizeof(data), out, outSz, 16); if (ret < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -9408; + return -9414; } #ifndef HAVE_FIPS @@ -19600,13 +19604,13 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, #endif if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -9409; + return -9415; } for (i = 0; i < testSz; i++) { pkcs7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); if (pkcs7 == NULL) - return -9410; + return -9416; pkcs7->heap = HEAP_HINT; pkcs7->devId = INVALID_DEVID; @@ -19616,7 +19620,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9410; + return -9417; } pkcs7->rng = &rng; @@ -19638,7 +19642,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9411; + return -9418; } } @@ -19650,7 +19654,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9412; + return -9419; } } @@ -19663,7 +19667,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9413; + return -9420; } } @@ -19686,7 +19690,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9414; + return -9421; } wc_ShaUpdate(&sha, pkcs7->publicKey, pkcs7->publicKeySz); wc_ShaFinal(&sha, digest); @@ -19696,7 +19700,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9415; + return -9422; } wc_Sha256Update(&sha, pkcs7->publicKey, pkcs7->publicKeySz); wc_Sha256Final(&sha, digest); @@ -19712,7 +19716,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (encodedSz < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9416; + return -9423; } #ifdef PKCS7_OUTPUT_TEST_BUNDLES @@ -19721,14 +19725,14 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (!file) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9417; + return -9424; } ret = (int)fwrite(out, 1, encodedSz, file); fclose(file); if (ret != (int)encodedSz) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9418; + return -9425; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ @@ -19736,23 +19740,23 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); if (pkcs7 == NULL) - return -9419; + return -9426; wc_PKCS7_InitWithCert(pkcs7, NULL, 0); ret = wc_PKCS7_VerifySignedData(pkcs7, out, outSz); if (ret < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9420; + return -9427; } /* verify contentType extracted successfully for custom content types */ if (testVectors[i].contentTypeSz > 0) { if (pkcs7->contentTypeSz != testVectors[i].contentTypeSz) { - return -9421; + return -9428; } else if (XMEMCMP(pkcs7->contentType, testVectors[i].contentType, pkcs7->contentTypeSz) != 0) { - return -9422; + return -9429; } } @@ -19760,7 +19764,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9423; + return -9430; } { @@ -19779,13 +19783,13 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, NULL, (word32*)&bufSz) != LENGTH_ONLY_E) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9424; + return -9431; } if (bufSz > (int)sizeof(buf)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9425; + return -9432; } bufSz = wc_PKCS7_GetAttributeValue(pkcs7, oidPt, oidSz, @@ -19794,7 +19798,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, (testVectors[i].signedAttribs == NULL && bufSz > 0)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9426; + return -9433; } } @@ -19803,7 +19807,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (!file) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9427; + return -9434; } ret = (int)fwrite(pkcs7->singleCert, 1, pkcs7->singleCertSz, file); fclose(file); From 56f1b684425662b3429ac5fc995d2d793b441289 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 22 Aug 2018 10:31:51 -0600 Subject: [PATCH 07/56] use SetContentType() to set SignedData content type --- wolfcrypt/src/pkcs7.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index db847d014..64557907c 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -1064,11 +1064,6 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, const byte* hashBuf, word32 hashSz, byte* output, word32* outputSz, byte* output2, word32* output2Sz) { - /* id-signedData (1.2.840.113549.1.7.2) */ - static const byte outerOid[] = - { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, - 0x07, 0x02 }; - /* contentType OID (1.2.840.113549.1.9.3) */ const byte contentTypeOid[] = { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, @@ -1085,8 +1080,9 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, int digEncAlgoId, digEncAlgoType; byte* flatSignedAttribs = NULL; word32 flatSignedAttribsSz = 0; - word32 innerOidSz = sizeof(innerOid); - word32 outerOidSz = sizeof(outerOid); + + byte signedDataOid[MAX_OID_SZ]; + word32 signedDataOidSz; if (pkcs7 == NULL || pkcs7->contentSz == 0 || pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 || @@ -1116,12 +1112,25 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, ret = wc_SetContentType(pkcs7->contentOID, pkcs7->contentType, sizeof(pkcs7->contentType)); - if (ret < 0) + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif return ret; - + } pkcs7->contentTypeSz = ret; } + /* set signedData outer content type */ + ret = wc_SetContentType(SIGNED_DATA, signedDataOid, sizeof(signedDataOid)); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + signedDataOidSz = ret; + esd->hashType = wc_OidGetHash(pkcs7->hashOID); if (wc_HashGetDigestSize(esd->hashType) != (int)hashSz) { WOLFSSL_MSG("hashSz did not match hashOID"); @@ -1238,14 +1247,14 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, esd->versionSz = SetMyVersion(1, esd->version, 0); totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz + - esd->contentInfoSeqSz + innerOidSz + esd->innerContSeqSz + - esd->innerOctetsSz + pkcs7->contentSz; + esd->contentInfoSeqSz + pkcs7->contentTypeSz + + esd->innerContSeqSz + esd->innerOctetsSz + pkcs7->contentSz; total2Sz = esd->certsSetSz + pkcs7->singleCertSz + signerInfoSz; esd->innerSeqSz = SetSequence(totalSz + total2Sz, esd->innerSeq); totalSz += esd->innerSeqSz; esd->outerContentSz = SetExplicit(0, totalSz + total2Sz, esd->outerContent); - totalSz += esd->outerContentSz + outerOidSz; + totalSz += esd->outerContentSz + signedDataOidSz; esd->outerSeqSz = SetSequence(totalSz + total2Sz, esd->outerSeq); totalSz += esd->outerSeqSz; @@ -1268,8 +1277,8 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, idx = 0; XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz); idx += esd->outerSeqSz; - XMEMCPY(output + idx, outerOid, outerOidSz); - idx += outerOidSz; + XMEMCPY(output + idx, signedDataOid, signedDataOidSz); + idx += signedDataOidSz; XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz); idx += esd->outerContentSz; XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz); From a25a6372702f1c78cfc213216c4910e8bb1f4cc6 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 23 Aug 2018 11:30:57 -0600 Subject: [PATCH 08/56] add CMS signingTime attribute support for SignedData --- wolfcrypt/src/asn.c | 86 +++++++++++++++++++++++++++++++++++++++++ wolfcrypt/src/pkcs7.c | 38 ++++++++++++++++-- wolfssl/wolfcrypt/asn.h | 6 ++- 3 files changed, 125 insertions(+), 5 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index cc51ad2a1..84f9da44a 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -4861,6 +4861,92 @@ int GetTimeString(byte* date, int format, char* buf, int len) #endif /* OPENSSL_ALL || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ +#if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7) + +/* set current time string, either UTC or GeneralizedTime */ +int GetAsnTimeString(byte* buf, word32 len) +{ + time_t currTime; + struct tm* ts = NULL; + struct tm* tmpTime = NULL; +#if defined(NEED_TMP_TIME) + struct tm tmpTimeStorage; + tmpTime = &tmpTimeStorage; +#else + (void)tmpTime; +#endif + byte* data_ptr = buf; + word32 data_len = 0; + int year, mon, day, hour, min, sec; + + WOLFSSL_ENTER("SetAsnTimeString"); + + if (buf == NULL || len == 0) + return BAD_FUNC_ARG; + + currTime = XTIME(0); + ts = (struct tm *)XGMTIME(&currTime, tmpTime); + if (ts == NULL){ + WOLFSSL_MSG("failed to get time data."); + return ASN_TIME_E; + } + + /* Note ASN_UTC_TIME_SIZE and ASN_GENERALIZED_TIME_SIZE include space for + * the null terminator. ASN encoded values leave off the terminator. */ + + if (ts->tm_year >= 50 && ts->tm_year < 150){ + /* UTC Time */ + char utc_str[ASN_UTC_TIME_SIZE]; + data_len = ASN_UTC_TIME_SIZE -1 + 2; + + if (len < data_len) + return BUFFER_E; + + if (ts->tm_year >= 50 && ts->tm_year < 100){ + year = ts->tm_year; + } else if (ts->tm_year >= 100 && ts->tm_year < 150){ + year = ts->tm_year - 100; + } + mon = ts->tm_mon + 1; + day = ts->tm_mday; + hour = ts->tm_hour; + min = ts->tm_min; + sec = ts->tm_sec; + XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE, + "%02d%02d%02d%02d%02d%02dZ", year, mon, day, hour, min, sec); + *data_ptr = (byte) ASN_UTC_TIME; data_ptr++; + /* -1 below excludes null terminator */ + *data_ptr = (byte) ASN_UTC_TIME_SIZE - 1; data_ptr++; + XMEMCPY(data_ptr,(byte *)utc_str, ASN_UTC_TIME_SIZE - 1); + + } else { + /* GeneralizedTime */ + char gt_str[ASN_GENERALIZED_TIME_SIZE]; + data_len = ASN_GENERALIZED_TIME_SIZE + 1; + + if (len < data_len) + return BUFFER_E; + + year = ts->tm_year + 1900; + mon = ts->tm_mon + 1; + day = ts->tm_mday; + hour = ts->tm_hour; + min = ts->tm_min; + sec = ts->tm_sec; + XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_SIZE, + "%4d%02d%02d%02d%02d%02dZ", year, mon, day, hour, min, sec); + *data_ptr = (byte) ASN_GENERALIZED_TIME; data_ptr++; + /* -1 below excludes null terminator */ + *data_ptr = (byte) ASN_GENERALIZED_TIME_SIZE - 1; data_ptr++; + XMEMCPY(data_ptr,(byte *)gt_str, ASN_GENERALIZED_TIME_SIZE - 1); + } + + return data_len; +} + +#endif /* !NO_ASN_TIME && HAVE_PKCS7 */ + + #if defined(USE_WOLF_VALIDDATE) /* to the second */ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 64557907c..87eeeb8a7 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -575,7 +575,7 @@ typedef struct ESD { byte signerDigAlgoId[MAX_ALGO_SZ]; byte digEncAlgoId[MAX_ALGO_SZ]; byte signedAttribSet[MAX_SET_SZ]; - EncodedAttrib signedAttribs[6]; + EncodedAttrib signedAttribs[7]; byte signerDigest[MAX_OCTET_STR_SZ]; word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz; word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz, @@ -751,11 +751,18 @@ static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, const byte* contentTypeOid, word32 contentTypeOidSz, const byte* contentType, word32 contentTypeSz, - const byte* messageDigestOid, word32 messageDigestOidSz) + const byte* messageDigestOid, word32 messageDigestOidSz, + const byte* signingTimeOid, word32 signingTimeOidSz) { int hashSz; +#ifdef NO_ASN_TIME PKCS7Attrib cannedAttribs[2]; +#else + PKCS7Attrib cannedAttribs[3]; + byte signingTime[MAX_TIME_STRING_SZ]; + int signingTimeSz; +#endif word32 cannedAttribsCount; if (pkcs7 == NULL || esd == NULL || contentTypeOid == NULL || @@ -766,6 +773,12 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, if (hashSz < 0) return hashSz; +#ifndef NO_ASN_TIME + signingTimeSz = GetAsnTimeString(signingTime, sizeof(signingTime)); + if (signingTimeSz < 0) + return signingTimeSz; +#endif + cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); cannedAttribs[0].oid = contentTypeOid; @@ -776,14 +789,25 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, cannedAttribs[1].oidSz = messageDigestOidSz; cannedAttribs[1].value = esd->contentDigest; cannedAttribs[1].valueSz = hashSz + 2; /* ASN.1 heading */ +#ifndef NO_ASN_TIME + cannedAttribs[2].oid = signingTimeOid; + cannedAttribs[2].oidSz = signingTimeOidSz; + cannedAttribs[2].value = (byte*)signingTime; + cannedAttribs[2].valueSz = signingTimeSz; +#endif esd->signedAttribsCount += cannedAttribsCount; - esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2, + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 3, cannedAttribs, cannedAttribsCount); esd->signedAttribsCount += pkcs7->signedAttribsSz; +#ifdef NO_ASN_TIME esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, pkcs7->signedAttribs, pkcs7->signedAttribsSz); +#else + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[3], 4, + pkcs7->signedAttribs, pkcs7->signedAttribsSz); +#endif return 0; } @@ -1074,6 +1098,11 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04 }; + /* signingTime OID () */ + byte signingTimeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x05}; + word32 signerInfoSz = 0; word32 totalSz, total2Sz; int idx = 0, ret = 0; @@ -1198,7 +1227,8 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, contentTypeOid, sizeof(contentTypeOid), pkcs7->contentType, pkcs7->contentTypeSz, - messageDigestOid, sizeof(messageDigestOid)); + messageDigestOid, sizeof(messageDigestOid), + signingTimeOid, sizeof(signingTimeOid)); if (ret < 0) { return MEMORY_E; } diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 82ef21871..a026d8787 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -305,7 +305,8 @@ enum Misc_ASN { TRAILING_ZERO = 1, /* Used for size of zero pad */ MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */ #if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ - defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(OPENSSL_EXTRA) || defined(HAVE_PKCS7) MAX_TIME_STRING_SZ = 25, /* Max length of formatted time string */ #endif @@ -990,6 +991,9 @@ typedef struct tm wolfssl_tm; defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) WOLFSSL_LOCAL int GetTimeString(byte* date, int format, char* buf, int len); #endif +#if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7) +WOLFSSL_LOCAL int GetAsnTimeString(byte* buf, word32 len); +#endif WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format, wolfssl_tm* certTime, int* idx); WOLFSSL_LOCAL int ValidateDate(const byte* date, byte format, int dateType); From 897c6b455f5ddf805a1a99d3bd63ff9ef52402fb Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 23 Aug 2018 16:06:07 -0600 Subject: [PATCH 09/56] move CMS signed attribute OIDs into BuildSignedAttributes() --- wolfcrypt/src/pkcs7.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 87eeeb8a7..88322416d 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -754,6 +754,21 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, const byte* messageDigestOid, word32 messageDigestOidSz, const byte* signingTimeOid, word32 signingTimeOidSz) { + /* contentType OID (1.2.840.113549.1.9.3) */ + byte contentTypeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, + 0x09, 0x03 }; + + /* messageDigest OID (1.2.840.113549.1.9.4) */ + byte messageDigestOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x04 }; + + /* signingTime OID () */ + byte signingTimeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x05}; + int hashSz; #ifdef NO_ASN_TIME @@ -765,9 +780,10 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, #endif word32 cannedAttribsCount; - if (pkcs7 == NULL || esd == NULL || contentTypeOid == NULL || - contentType == NULL || messageDigestOid == NULL) + if (pkcs7 == NULL || esd == NULL || contentType == NULL || + messageDigestOid == NULL) { return BAD_FUNC_ARG; + } hashSz = wc_HashGetDigestSize(esd->hashType); if (hashSz < 0) @@ -782,16 +798,16 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); cannedAttribs[0].oid = contentTypeOid; - cannedAttribs[0].oidSz = contentTypeOidSz; + cannedAttribs[0].oidSz = sizeof(contentTypeOid); cannedAttribs[0].value = contentType; cannedAttribs[0].valueSz = contentTypeSz; cannedAttribs[1].oid = messageDigestOid; - cannedAttribs[1].oidSz = messageDigestOidSz; + cannedAttribs[1].oidSz = sizeof(messageDigestOid); cannedAttribs[1].value = esd->contentDigest; cannedAttribs[1].valueSz = hashSz + 2; /* ASN.1 heading */ #ifndef NO_ASN_TIME cannedAttribs[2].oid = signingTimeOid; - cannedAttribs[2].oidSz = signingTimeOidSz; + cannedAttribs[2].oidSz = sizeof(signingTimeOid); cannedAttribs[2].value = (byte*)signingTime; cannedAttribs[2].valueSz = signingTimeSz; #endif @@ -1224,11 +1240,8 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, if (pkcs7->signedAttribsSz != 0) { /* build up signed attributes */ - ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, - contentTypeOid, sizeof(contentTypeOid), - pkcs7->contentType, pkcs7->contentTypeSz, - messageDigestOid, sizeof(messageDigestOid), - signingTimeOid, sizeof(signingTimeOid)); + ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, pkcs7->contentType, + pkcs7->contentTypeSz); if (ret < 0) { return MEMORY_E; } From 78414347448d553e6d6788f1b9a829474e9d57f5 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 31 Aug 2018 10:18:18 -0600 Subject: [PATCH 10/56] add support for multiple certificates in CMS SignedData certificates field --- Makefile.am | 1 + wolfcrypt/src/pkcs7.c | 303 ++++++++++++++++---- wolfcrypt/test/test.c | 585 +++++++++++++++++++++++++++----------- wolfssl/wolfcrypt/pkcs7.h | 7 +- 4 files changed, 674 insertions(+), 222 deletions(-) diff --git a/Makefile.am b/Makefile.am index 57d7bba1b..47b084047 100644 --- a/Makefile.am +++ b/Makefile.am @@ -64,6 +64,7 @@ CLEANFILES+= cert.der \ pkcs7signedData_RSA_SHA256.der \ pkcs7signedData_RSA_SHA256_firmwarePkgData.der \ pkcs7signedData_RSA_SHA256_custom_contentType.der \ + pkcs7signedData_RSA_SHA256_with_ca_cert.der \ pkcs7signedData_RSA_SHA256_SKID.der \ pkcs7signedData_RSA_SHA384.der \ pkcs7signedData_RSA_SHA512.der \ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 88322416d..3a37fc7e2 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -296,16 +296,28 @@ int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId) } -/* init PKCS7 struct with recipient cert, decode into DecodedCert +/* Certificate structure holding der pointer, size, and pointer to next + * Pkcs7Cert struct. Used when creating SignedData types with multiple + * certificates. */ +typedef struct Pkcs7Cert { + byte* der; + word32 derSz; + Pkcs7Cert* next; +} Pkcs7Cert; + + +/* Init PKCS7 struct with recipient cert, decode into DecodedCert * NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */ -int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) +int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) { int ret = 0; void* heap; int devId; word16 isDynamic; + Pkcs7Cert* cert; + Pkcs7Cert* lastCert; - if (pkcs7 == NULL || (cert == NULL && certSz != 0)) { + if (pkcs7 == NULL || (derCert == NULL && derCertSz != 0)) { return BAD_FUNC_ARG; } @@ -317,7 +329,7 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) return ret; pkcs7->isDynamic = isDynamic; - if (cert != NULL && certSz > 0) { + if (derCert != NULL && derCertSz > 0) { #ifdef WOLFSSL_SMALL_STACK DecodedCert* dCert; @@ -329,10 +341,29 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) DecodedCert dCert[1]; #endif - pkcs7->singleCert = cert; - pkcs7->singleCertSz = certSz; - InitDecodedCert(dCert, cert, certSz, pkcs7->heap); + pkcs7->singleCert = derCert; + pkcs7->singleCertSz = derCertSz; + /* create new Pkcs7Cert for recipient, freed during cleanup */ + cert = (Pkcs7Cert*)XMALLOC(sizeof(Pkcs7Cert), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + XMEMSET(cert, 0, sizeof(Pkcs7Cert)); + cert->der = derCert; + cert->derSz = derCertSz; + cert->next = NULL; + + /* add recipient to cert list */ + if (pkcs7->certList == NULL) { + pkcs7->certList = cert; + } else { + lastCert = pkcs7->certList; + while (lastCert->next != NULL) { + lastCert = lastCert->next; + } + lastCert->next = cert; + } + + InitDecodedCert(dCert, derCert, derCertSz, pkcs7->heap); ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { FreeDecodedCert(dCert); @@ -366,6 +397,45 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz) } +/* Adds one DER-formatted certificate to the internal PKCS7/CMS certificate + * list, to be added as part of the certificates CertificateSet. Currently + * used in SignedData content type. + * + * Must be called after wc_PKCS7_Init() or wc_PKCS7_InitWithCert(). + * + * Does not represent the recipient/signer certificate, only certificates that + * are part of the certificate chain used to build and verify signer + * certificates. + * + * This API does not currently validate certificates. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_AddCertificate(PKCS7* pkcs7, byte* derCert, word32 derCertSz) +{ + Pkcs7Cert* cert; + + if (pkcs7 == NULL || derCert == NULL || derCertSz == 0) + return BAD_FUNC_ARG; + + cert = (Pkcs7Cert*)XMALLOC(sizeof(Pkcs7Cert), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (cert == NULL) + return MEMORY_E; + + cert->der = derCert; + cert->derSz = derCertSz; + + if (pkcs7->certList == NULL) { + pkcs7->certList = cert; + } else { + cert->next = pkcs7->certList; + pkcs7->certList = cert; + } + + return 0; +} + + /* free linked list of PKCS7DecodedAttrib structs */ static void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib, void* heap) { @@ -392,6 +462,29 @@ static void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib, void* heap) } +/* free all members of Pkcs7Cert linked list */ +static int wc_PKCS7_FreeCertSet(PKCS7* pkcs7) +{ + Pkcs7Cert* curr = NULL; + Pkcs7Cert* next = NULL; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + curr = pkcs7->certList; + pkcs7->certList = NULL; + + while (curr != NULL) { + next = curr->next; + curr->next = NULL; + XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + curr = next; + } + + return 0; +} + + /* releases any memory allocated by a PKCS7 initializer */ void wc_PKCS7_Free(PKCS7* pkcs7) { @@ -1099,6 +1192,7 @@ static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, return ret; } + /* build PKCS#7 signedData content type */ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, const byte* hashBuf, word32 hashSz, byte* output, word32* outputSz, @@ -1119,6 +1213,9 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x05}; + Pkcs7Cert* certPtr = NULL; + word32 certSetSz = 0; + word32 signerInfoSz = 0; word32 totalSz, total2Sz; int idx = 0, ret = 0; @@ -1131,7 +1228,6 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, if (pkcs7 == NULL || pkcs7->contentSz == 0 || pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 || - pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0 || output == NULL || outputSz == NULL || *outputSz == 0 || hashSz == 0 || hashBuf == NULL) { return BAD_FUNC_ARG; @@ -1279,8 +1375,16 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet); signerInfoSz += esd->signerInfoSetSz; - esd->certsSetSz = SetImplicit(ASN_SET, 0, pkcs7->singleCertSz, - esd->certsSet); + /* certificates [0] IMPLICIT CertificateSet */ + /* get total certificates size */ + certPtr = pkcs7->certList; + while (certPtr != NULL) { + certSetSz += certPtr->derSz; + certPtr = certPtr->next; + } + certPtr = NULL; + + esd->certsSetSz = SetImplicit(ASN_SET, 0, certSetSz, esd->certsSet); esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId, oidHashType, 0); @@ -1292,7 +1396,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz + esd->contentInfoSeqSz + pkcs7->contentTypeSz + esd->innerContSeqSz + esd->innerOctetsSz + pkcs7->contentSz; - total2Sz = esd->certsSetSz + pkcs7->singleCertSz + signerInfoSz; + total2Sz = esd->certsSetSz + certSetSz + signerInfoSz; esd->innerSeqSz = SetSequence(totalSz + total2Sz, esd->innerSeq); totalSz += esd->innerSeqSz; @@ -1351,10 +1455,20 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, idx += pkcs7->contentSz; output2 = output; } + + /* certificates */ XMEMCPY(output2 + idx, esd->certsSet, esd->certsSetSz); idx += esd->certsSetSz; - XMEMCPY(output2 + idx, pkcs7->singleCert, pkcs7->singleCertSz); - idx += pkcs7->singleCertSz; + certPtr = pkcs7->certList; + while (certPtr != NULL) { + XMEMCPY(output2 + idx, certPtr->der, certPtr->derSz); + idx += certPtr->derSz; + certPtr = certPtr->next; + } + ret = wc_PKCS7_FreeCertSet(pkcs7); + if (ret != 0) + return ret; + XMEMCPY(output2 + idx, esd->signerInfoSet, esd->signerInfoSetSz); idx += esd->signerInfoSetSz; XMEMCPY(output2 + idx, esd->signerInfoSeq, esd->signerInfoSeqSz); @@ -1517,14 +1631,17 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, byte* hash, word32 hashSz) { - int ret = 0; - word32 scratch = 0; + int ret = 0, i; + word32 scratch = 0, verified = 0; #ifdef WOLFSSL_SMALL_STACK byte* digest; RsaKey* key; + DecodedCert* dCert; #else byte digest[MAX_PKCS7_DIGEST_SZ]; RsaKey key[1]; + DecodedCert stack_dCert; + DecodedCert* dCert = &stack_dCert; #endif if (pkcs7 == NULL || sig == NULL || hash == NULL) { @@ -1534,7 +1651,6 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, #ifdef WOLFSSL_SMALL_STACK digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (digest == NULL) return MEMORY_E; @@ -1543,35 +1659,67 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } + + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_DCERT); + if (dCert == NULL) { + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } #endif XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); - ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } + /* loop over certs received in certificates set, try to find one + * that will validate signature */ + for (i = 0; i < MAX_PKCS7_CERTS; i++) { - if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key, - pkcs7->publicKeySz) < 0) { - WOLFSSL_MSG("ASN RSA key decode error"); + verified = 0; + scratch = 0; + + if (pkcs7->certSz[i] == 0) + continue; + + ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap); + /* not verifying, only using this to extract public key */ + ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); + if (ret < 0) { + WOLFSSL_MSG("ASN RSA cert parse error"); + FreeDecodedCert(dCert); + wc_FreeRsaKey(key); + continue; + } + + if (wc_RsaPublicKeyDecode(dCert->publicKey, &scratch, key, + dCert->pubKeySize) < 0) { + WOLFSSL_MSG("ASN RSA key decode error"); + FreeDecodedCert(dCert); + wc_FreeRsaKey(key); + continue; + } + + ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, key); + FreeDecodedCert(dCert); wc_FreeRsaKey(key); -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return PUBLIC_KEY_E; + + if (((int)hashSz == ret) && (XMEMCMP(digest, hash, ret) == 0)) { + /* found signer that successfully verified signature */ + verified = 1; + break; + } } - ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, key); - - wc_FreeRsaKey(key); - - if (((int)hashSz != ret) || (XMEMCMP(digest, hash, ret) != 0)) { + if (verified == 0) { ret = SIG_VERIFY_E; } @@ -1592,14 +1740,18 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, byte* hash, word32 hashSz) { - int ret = 0; + int ret = 0, i; int res = 0; + int verified = 0; #ifdef WOLFSSL_SMALL_STACK byte* digest; ecc_key* key; + DecodedCert* dCert; #else byte digest[MAX_PKCS7_DIGEST_SZ]; ecc_key key[1]; + DecodedCert stack_dCert; + DecodedCert* dCert = &stack_dCert; #endif word32 idx = 0; @@ -1609,7 +1761,6 @@ static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, #ifdef WOLFSSL_SMALL_STACK digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (digest == NULL) return MEMORY_E; @@ -1618,35 +1769,67 @@ static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } + + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_DCERT); + if (dCert == NULL) { + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } #endif XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); - ret = wc_ecc_init_ex(key, pkcs7->heap, pkcs7->devId); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } + /* loop over certs received in certificates set, try to find one + * that will validate signature */ + for (i = 0; i < MAX_PKCS7_CERTS; i++) { - if (wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, key, - pkcs7->publicKeySz) < 0) { - WOLFSSL_MSG("ASN ECDSA key decode error"); + verified = 0; + + if (pkcs7->certSz[i] == 0) + continue; + + ret = wc_ecc_init_ex(key, pkcs7->heap, pkcs7->devId); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap); + /* not verifying, only using this to extract public key */ + ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); + if (ret < 0) { + WOLFSSL_MSG("ASN ECC cert parse error"); + FreeDecodedCert(dCert); + wc_ecc_free(key); + continue; + } + + if (wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, key, + pkcs7->publicKeySz) < 0) { + WOLFSSL_MSG("ASN ECC key decode error"); + FreeDecodedCert(dCert); + wc_ecc_free(key); + continue; + } + + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key); + + FreeDecodedCert(dCert); wc_ecc_free(key); -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return PUBLIC_KEY_E; + + if (ret == 0 && res == 1) { + /* found signer that successfully verified signature */ + verified = 1; + break; + } } - ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key); - - wc_ecc_free(key); - - if (ret == 0 && res != 1) { + if (verified == 0) { ret = SIG_VERIFY_E; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 64d35de6d..b35d0769f 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -8501,12 +8501,20 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) #ifdef WOLFSSL_CERT_EXT static const char* clientKeyPub = CERT_ROOT "client-keyPub.der"; #endif - #ifdef WOLFSSL_CERT_GEN + #if defined(WOLFSSL_CERT_GEN) || defined(HAVE_PKCS7) static const char* rsaCaKeyFile = CERT_ROOT "ca-key.der"; + #ifdef WOLFSSL_CERT_GEN static const char* rsaCaCertFile = CERT_ROOT "ca-cert.pem"; - #ifdef WOLFSSL_ALT_NAMES + #endif + #if defined(WOLFSSL_ALT_NAMES) || defined(HAVE_PKCS7) static const char* rsaCaCertDerFile = CERT_ROOT "ca-cert.der"; #endif + #ifdef HAVE_PKCS7 + static const char* rsaServerCertDerFile = + CERT_ROOT "server-cert.der"; + static const char* rsaServerKeyDerFile = + CERT_ROOT "server-key.der"; + #endif #endif #endif /* !NO_RSA */ #ifndef NO_DH @@ -18647,21 +18655,37 @@ exit: /* Loads certs and keys for use with PKCS7 tests, from either files * or buffers. * - * rsaCert - output buffer for RSA cert - * rsaCertSz - IN/OUT size of output buffer, size of RSA cert - * rsaPrivKey - output buffer for RSA private key - * rsaPrivKeySz - IN/OUT size of output buffer, size of RSA key - * eccCert - output buffer for ECC cert - * eccCertSz - IN/OUT size of output buffer, size of ECC cert - * eccPrivKey - output buffer for ECC private key - * eccPrivKeySz - IN/OUT size of output buffer, size of ECC private key + * rsaClientCertBuf - output buffer for RSA client cert + * rsaClientCertBufSz - IN/OUT size of output buffer, size of RSA client cert + * rsaClientPrivKeyBuf - output buffer for RSA client private key + * rsaClientPrivKeyBufSz - IN/OUT size of output buffer, size of RSA client key + * + * rsaServerCertBuf - output buffer for RSA server cert + * rsaServerCertBufSz - IN/OUT size of output buffer, size of RSA server cert + * rsaServerPrivKeyBuf - output buffer for RSA server private key + * rsaServerPrivKeyBufSz - IN/OUT size of output buffer, size of RSA server key + * + * rsaCaCertBuf - output buffer for RSA CA cert + * rsaCaCertBufSz - IN/OUT size of output buffer, size of RSA ca cert + * rsaCaPrivKeyBuf - output buffer for RSA CA private key + * rsaCaPrivKeyBufSz - IN/OUT size of output buffer, size of RSA CA key + * + * eccClientCertBuf - output buffer for ECC cert + * eccClientCertBufSz - IN/OUT size of output buffer, size of ECC cert + * eccClientPrivKeyBuf - output buffer for ECC private key + * eccClientPrivKeyBufSz - IN/OUT size of output buffer, size of ECC private key * * Returns 0 on success, negative on error */ -static int pkcs7_load_certs_keys(byte* rsaCert, word32* rsaCertSz, - byte* rsaPrivKey, word32* rsaPrivKeySz, - byte* eccCert, word32* eccCertSz, - byte* eccPrivKey, word32* eccPrivKeySz) +static int pkcs7_load_certs_keys( + byte* rsaClientCertBuf, word32* rsaClientCertBufSz, + byte* rsaClientPrivKeyBuf, word32* rsaClientPrivKeyBufSz, + byte* rsaServerCertBuf, word32* rsaServerCertBufSz, + byte* rsaServerPrivKeyBuf, word32* rsaServerPrivKeyBufSz, + byte* rsaCaCertBuf, word32* rsaCaCertBufSz, + byte* rsaCaPrivKeyBuf, word32* rsaCaPrivKeyBufSz, + byte* eccClientCertBuf, word32* eccClientCertBufSz, + byte* eccClientPrivKeyBuf, word32* eccClientPrivKeyBufSz) { #ifndef NO_FILESYSTEM FILE* certFile; @@ -18669,14 +18693,14 @@ static int pkcs7_load_certs_keys(byte* rsaCert, word32* rsaCertSz, #endif #ifndef NO_RSA - if (rsaCert == NULL || rsaCertSz == NULL || - rsaPrivKey == NULL || rsaPrivKeySz == NULL) + if (rsaClientCertBuf == NULL || rsaClientCertBufSz == NULL || + rsaClientPrivKeyBuf == NULL || rsaClientPrivKeyBufSz == NULL) return BAD_FUNC_ARG; #endif #ifdef HAVE_ECC - if (eccCert == NULL || eccCertSz == NULL || - eccPrivKey == NULL || eccPrivKeySz == NULL) + if (eccClientCertBuf == NULL || eccClientCertBufSz == NULL || + eccClientPrivKeyBuf == NULL || eccClientPrivKeyBufSz == NULL) return BAD_FUNC_ARG; #endif @@ -18684,45 +18708,159 @@ static int pkcs7_load_certs_keys(byte* rsaCert, word32* rsaCertSz, #ifndef NO_RSA #ifdef USE_CERT_BUFFERS_1024 - if (*rsaCertSz < (word32)sizeof_client_cert_der_1024) + if (*rsaClientCertBufSz < (word32)sizeof_client_cert_der_1024) return -9204; - XMEMCPY(rsaCert, client_cert_der_1024, sizeof_client_cert_der_1024); - *rsaCertSz = sizeof_client_cert_der_1024; -#elif defined(USE_CERT_BUFFERS_2048) - if (*rsaCertSz < (word32)sizeof_client_cert_der_2048) - return -9205; + XMEMCPY(rsaClientCertBuf, client_cert_der_1024, + sizeof_client_cert_der_1024); + *rsaClientCertBufSz = sizeof_client_cert_der_1024; - XMEMCPY(rsaCert, client_cert_der_2048, sizeof_client_cert_der_2048); - *rsaCertSz = sizeof_client_cert_der_2048; + if (rsaServerCertBuf != NULL) { + if (*rsaServerCertBufSz < (word32)sizeof_server_cert_der_1024) + return -9205; + + XMEMCPY(rsaServerCertBuf, server_cert_der_1024, + sizeof_server_cert_der_1024); + *rsaServerCertBufSz = sizeof_server_cert_der_1024; + } + + if (rsaCaCertBuf != NULL) { + if (*rsaCaCertBufSz < (word32)sizeof_ca_cert_der_1024) + return -9206; + + XMEMCPY(rsaCaCertBuf, ca_cert_der_1024, sizeof_ca_cert_der_1024); + *rsaCaCertBufSz = sizeof_ca_cert_der_1024; + } +#elif defined(USE_CERT_BUFFERS_2048) + if (*rsaClientCertBufSz < (word32)sizeof_client_cert_der_2048) + return -9207; + + XMEMCPY(rsaClientCertBuf, client_cert_der_2048, + sizeof_client_cert_der_2048); + *rsaClientCertBufSz = sizeof_client_cert_der_2048; + + if (rsaServerCertBuf != NULL) { + if (*rsaServerCertBufSz < (word32)sizeof_server_cert_der_2048) + return -9208; + + XMEMCPY(rsaServerCertBuf, server_cert_der_2048, + sizeof_server_cert_der_2048); + *rsaServerCertBufSz = sizeof_server_cert_der_2048; + } + + if (rsaCaCertBuf != NULL) { + if (*rsaCaCertBufSz < (word32)sizeof_ca_cert_der_2048) + return -9209; + + XMEMCPY(rsaCaCertBuf, ca_cert_der_2048, sizeof_ca_cert_der_2048); + *rsaCaCertBufSz = sizeof_ca_cert_der_2048; + } #else certFile = fopen(clientCert, "rb"); if (!certFile) - return -9206; + return -9210; - *rsaCertSz = (word32)fread(rsaCert, 1, *rsaCertSz, certFile); + *rsaClientCertBufSz = (word32)fread(rsaClientCertBuf, 1, + *rsaClientCertBufSz, certFile); fclose(certFile); + + if (rsaServerCertBuf != NULL) { + certFile = fopen(rsaServerCertDerFile, "rb"); + if (!certFile) + return -9211; + + *rsaServerCertBufSz = (word32)fread(rsaServerCertBuf, 1, + *rsaServerCertBufSz, certFile); + fclose(certFile); + } + + if (rsaCaCertBuf != NULL) { + certFile = fopen(rsaCaCertDerFile, "rb"); + if (!certFile) + return -9212; + + *rsaCaCertBufSz = (word32)fread(rsaCaCertBuf, 1, *rsaCaCertBufSz, + certFile); + fclose(certFile); + } #endif #ifdef USE_CERT_BUFFERS_1024 - if (*rsaPrivKeySz < (word32)sizeof_client_key_der_1024) - return -9207; + if (*rsaClientPrivKeyBufSz < (word32)sizeof_client_key_der_1024) + return -9213; - XMEMCPY(rsaPrivKey, client_key_der_1024, sizeof_client_key_der_1024); - *rsaPrivKeySz = sizeof_client_key_der_1024; + XMEMCPY(rsaClientPrivKeyBuf, client_key_der_1024, + sizeof_client_key_der_1024); + *rsaClientPrivKeyBufSz = sizeof_client_key_der_1024; + + if (rsaServerPrivKeyBuf != NULL) { + if (*rsaServerPrivKeyBufSz < (word32)sizeof_server_key_der_1024) + return -9214; + + XMEMCPY(rsaServerPrivKeyBuf, server_key_der_1024, + sizeof_server_key_der_1024); + *rsaServerPrivKeyBufSz = sizeof_server_key_der_1024; + } + + if (rsaCaPrivKeyBuf != NULL) { + if (*rsaCaPrivKeyBufSz < (word32)sizeof_ca_key_der_1024) + return -9215; + + XMEMCPY(rsaCaPrivKeyBuf, ca_key_der_1024, sizeof_ca_key_der_1024); + *rsaCaPrivKeyBufSz = sizeof_ca_key_der_1024; + } #elif defined(USE_CERT_BUFFERS_2048) - if (*rsaPrivKeySz < (word32)sizeof_client_key_der_2048) - return -9208; + if (*rsaClientPrivKeyBufSz < (word32)sizeof_client_key_der_2048) + return -9216; - XMEMCPY(rsaPrivKey, client_key_der_2048, sizeof_client_key_der_2048); - *rsaPrivKeySz = sizeof_client_key_der_2048; + XMEMCPY(rsaClientPrivKeyBuf, client_key_der_2048, + sizeof_client_key_der_2048); + *rsaClientPrivKeyBufSz = sizeof_client_key_der_2048; + + if (rsaServerPrivKeyBuf != NULL) { + if (*rsaServerPrivKeyBufSz < (word32)sizeof_server_key_der_2048) + return -9217; + + XMEMCPY(rsaServerPrivKeyBuf, server_key_der_2048, + sizeof_server_key_der_2048); + *rsaServerPrivKeyBufSz = sizeof_server_key_der_2048; + } + + if (rsaCaPrivKeyBuf != NULL) { + if (*rsaCaPrivKeyBufSz < (word32)sizeof_ca_key_der_2048) + return -9218; + + XMEMCPY(rsaCaPrivKeyBuf, ca_key_der_2048, sizeof_ca_key_der_2048); + *rsaCaPrivKeyBufSz = sizeof_ca_key_der_2048; + } #else keyFile = fopen(clientKey, "rb"); if (!keyFile) - return -9209; + return -9219; - *rsaPrivKeySz = (word32)fread(rsaPrivKey, 1, *rsaPrivKeySz, keyFile); + *rsaClientPrivKeyBufSz = (word32)fread(rsaClientPrivKeyBuf, 1, + *rsaClientPrivKeyBufSz, keyFile); fclose(keyFile); + + if (rsaServerPrivKeyBuf != NULL) { + keyFile = fopen(rsaServerKeyDerFile, "rb"); + if (!keyFile) + return -9220; + + *rsaServerPrivKeyBufSz = (word32)fread(rsaServerPrivKeyBuf, 1, + *rsaServerPrivKeyBufSz, keyFile); + fclose(keyFile); + } + + if (rsaCaPrivKeyBuf != NULL) { + keyFile = fopen(rsaCaKeyFile, "rb"); + if (!keyFile) + return -9221; + + *rsaCaPrivKeyBufSz = (word32)fread(rsaCaPrivKeyBuf, 1, + *rsaCaPrivKeyBufSz, keyFile); + fclose(keyFile); + } #endif /* USE_CERT_BUFFERS */ #endif /* NO_RSA */ @@ -18731,47 +18869,57 @@ static int pkcs7_load_certs_keys(byte* rsaCert, word32* rsaCertSz, #ifdef HAVE_ECC #ifdef USE_CERT_BUFFERS_256 - if (*eccCertSz < (word32)sizeof_cliecc_cert_der_256) + if (*eccClientCertBufSz < (word32)sizeof_cliecc_cert_der_256) return -9210; - XMEMCPY(eccCert, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); - *eccCertSz = sizeof_cliecc_cert_der_256; + XMEMCPY(eccClientCertBuf, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); + *eccClientCertBufSz = sizeof_cliecc_cert_der_256; #else certFile = fopen(eccClientCert, "rb"); if (!certFile) return -9211; - *eccCertSz = (word32)fread(eccCert, 1, *eccCertSz, certFile); + *eccClientCertBufSz = (word32)fread(eccClientCertBuf, 1, + *eccClientCertBufSz, certFile); fclose(certFile); #endif /* USE_CERT_BUFFERS_256 */ #ifdef USE_CERT_BUFFERS_256 - if (*eccPrivKeySz < (word32)sizeof_ecc_clikey_der_256) + if (*eccClientPrivKeyBufSz < (word32)sizeof_ecc_clikey_der_256) return -9212; - XMEMCPY(eccPrivKey, ecc_clikey_der_256, sizeof_ecc_clikey_der_256); - *eccPrivKeySz = sizeof_ecc_clikey_der_256; + XMEMCPY(eccClientPrivKeyBuf, ecc_clikey_der_256, sizeof_ecc_clikey_der_256); + *eccClientPrivKeyBufSz = sizeof_ecc_clikey_der_256; #else keyFile = fopen(eccClientKey, "rb"); if (!keyFile) return -9213; - *eccPrivKeySz = (word32)fread(eccPrivKey, 1, *eccPrivKeySz, keyFile); + *eccClientPrivKeyBufSz = (word32)fread(eccClientPrivKeyBuf, 1, + *eccClientPrivKeyBufSz, keyFile); fclose(keyFile); #endif /* USE_CERT_BUFFERS_256 */ #endif /* HAVE_ECC */ #ifdef NO_RSA - (void)rsaCert; - (void)rsaCertSz; - (void)rsaPrivKey; - (void)rsaPrivKeySz; + (void)rsaClientCertBuf; + (void)rsaClientCertBufSz; + (void)rsaClientPrivKeyBuf; + (void)rsaClientPrivKeyBufSz; + (void)rsaServerCertBuf; + (void)rsaServerCertBufSz; + (void)rsaServerPrivKeyBuf; + (void)rsaServerPrivKeyBufSz; + (void)rsaCaCertBuf; + (void)rsaCaCertBufSz; + (void)rsaCaPrivKeyBuf; + (void)rsaCaPrivKeyBufSz; #endif #ifndef HAVE_ECC - (void)eccCert; - (void)eccCertSz; - (void)eccPrivKey; - (void)eccPrivKeySz; + (void)eccClientCertBuf; + (void)eccClientCertBufSz; + (void)eccClientPrivKeyBuf; + (void)eccClientPrivKeyBufSz; #endif #ifndef NO_FILESYSTEM (void)certFile; @@ -19030,7 +19178,8 @@ int pkcs7enveloped_test(void) #endif /* HAVE_ECC */ ret = pkcs7_load_certs_keys(rsaCert, &rsaCertSz, rsaPrivKey, - &rsaPrivKeySz, eccCert, &eccCertSz, + &rsaPrivKeySz, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, eccCert, &eccCertSz, eccPrivKey, &eccPrivKeySz); if (ret < 0) { #ifndef NO_RSA @@ -19407,6 +19556,8 @@ typedef struct { word32 privateKeySz; byte* cert; size_t certSz; + byte* caCert; + size_t caCertSz; PKCS7Attrib* signedAttribs; word32 signedAttribsSz; const char* outFileName; @@ -19417,10 +19568,15 @@ typedef struct { } pkcs7SignedVector; -static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, - byte* rsaPrivKey, word32 rsaPrivKeySz, - byte* eccCert, word32 eccCertSz, - byte* eccPrivKey, word32 eccPrivKeySz) +static int pkcs7signed_run_vectors( + byte* rsaClientCertBuf, word32 rsaClientCertBufSz, + byte* rsaClientPrivKeyBuf, word32 rsaClientPrivKeyBufSz, + byte* rsaServerCertBuf, word32 rsaServerCertBufSz, + byte* rsaServerPrivKeyBuf, word32 rsaServerPrivKeyBufSz, + byte* rsaCaCertBuf, word32 rsaCaCertBufSz, + byte* rsaCaPrivKeyBuf, word32 rsaCaPrivKeyBufSz, + byte* eccClientCertBuf, word32 eccClientCertBufSz, + byte* eccClientPrivKeyBuf, word32 eccClientPrivKeyBufSz) { int ret, testSz, i; int encodedSz; @@ -19474,55 +19630,71 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, #ifndef NO_RSA #ifndef NO_SHA /* RSA with SHA */ - {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, - rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHAh, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_RSA_SHA.der", 0, NULL, 0, 0}, /* RSA with SHA, no signed attributes */ - {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, - rsaCert, rsaCertSz, NULL, 0, + {data, (word32)sizeof(data), SHAh, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, + NULL, 0, NULL, 0, "pkcs7signedData_RSA_SHA_noattr.der", 0, NULL, 0, 0}, #endif #ifdef WOLFSSL_SHA224 /* RSA with SHA224 */ - {data, (word32)sizeof(data), SHA224h, RSAk, rsaPrivKey, rsaPrivKeySz, - rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA224h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_RSA_SHA224.der", 0, NULL, 0, 0}, #endif #ifndef NO_SHA256 /* RSA with SHA256 */ - {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, - rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_RSA_SHA256.der", 0, NULL, 0, 0}, /* RSA with SHA256 and SubjectKeyIdentifier in SignerIdentifier */ - {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, - rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_RSA_SHA256_SKID.der", 0, NULL, 0, SID_SUBJECT_KEY_IDENTIFIER}, /* RSA with SHA256 and custom contentType */ - {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, - rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_RSA_SHA256_custom_contentType.der", 0, customContentType, sizeof(customContentType), 0}, /* RSA with SHA256 and FirmwarePkgData contentType */ - {data, (word32)sizeof(data), SHA256h, RSAk, rsaPrivKey, rsaPrivKeySz, - rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_RSA_SHA256_firmwarePkgData.der", FIRMWARE_PKG_DATA, NULL, 0, 0}, + + /* RSA with SHA256 using server cert and ca cert */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaServerPrivKeyBuf, + rsaServerPrivKeyBufSz, rsaServerCertBuf, rsaServerCertBufSz, + rsaCaCertBuf, rsaCaCertBufSz, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA256_with_ca_cert.der", 0, NULL, 0, 0}, #endif #if defined(WOLFSSL_SHA384) /* RSA with SHA384 */ - {data, (word32)sizeof(data), SHA384h, RSAk, rsaPrivKey, rsaPrivKeySz, - rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA384h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_RSA_SHA384.der", 0, NULL, 0, 0}, #endif #if defined(WOLFSSL_SHA512) /* RSA with SHA512 */ - {data, (word32)sizeof(data), SHA512h, RSAk, rsaPrivKey, rsaPrivKeySz, - rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA512h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_RSA_SHA512.der", 0, NULL, 0, 0}, #endif #endif /* NO_RSA */ @@ -19530,55 +19702,64 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, #ifdef HAVE_ECC #ifndef NO_SHA /* ECDSA with SHA */ - {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, - eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHAh, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_ECDSA_SHA.der", 0, NULL, 0, 0}, /* ECDSA with SHA, no signed attributes */ - {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, - eccCert, eccCertSz, NULL, 0, + {data, (word32)sizeof(data), SHAh, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, + NULL, 0, NULL, 0, "pkcs7signedData_ECDSA_SHA_noattr.der", 0, NULL, 0, 0}, #endif #ifdef WOLFSSL_SHA224 /* ECDSA with SHA224 */ - {data, (word32)sizeof(data), SHA224h, ECDSAk, eccPrivKey, eccPrivKeySz, - eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA224h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_ECDSA_SHA224.der", 0, NULL, 0, 0}, #endif #ifndef NO_SHA256 /* ECDSA with SHA256 */ - {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, - eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_ECDSA_SHA256.der", 0, NULL, 0, 0}, /* ECDSA with SHA256 and SubjectKeyIdentifier in SigherIdentifier */ - {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, - eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_ECDSA_SHA256_SKID.der", 0, NULL, 0, SID_SUBJECT_KEY_IDENTIFIER}, /* ECDSA with SHA256 and custom contentType */ - {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, - eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_ECDSA_SHA256_custom_contentType.der", 0, customContentType, sizeof(customContentType), 0}, /* ECDSA with SHA256 and FirmwarePkgData contentType */ - {data, (word32)sizeof(data), SHA256h, ECDSAk, eccPrivKey, eccPrivKeySz, - eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_ECDSA_SHA256_firmwarePkgData.der", FIRMWARE_PKG_DATA, NULL, 0, 0}, #endif #ifdef WOLFSSL_SHA384 /* ECDSA with SHA384 */ - {data, (word32)sizeof(data), SHA384h, ECDSAk, eccPrivKey, eccPrivKeySz, - eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA384h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_ECDSA_SHA384.der", 0, NULL, 0, 0}, #endif #ifdef WOLFSSL_SHA512 /* ECDSA with SHA512 */ - {data, (word32)sizeof(data), SHA512h, ECDSAk, eccPrivKey, eccPrivKeySz, - eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + {data, (word32)sizeof(data), SHA512h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_ECDSA_SHA512.der", 0, NULL, 0, 0}, #endif #endif /* HAVE_ECC */ @@ -19623,6 +19804,17 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, return -9417; } + /* load CA certificate, if present */ + if (testVectors[i].caCert != NULL) { + ret = wc_PKCS7_AddCertificate(pkcs7, testVectors[i].caCert, + (word32)testVectors[i].caCertSz); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9418; + } + } + pkcs7->rng = &rng; pkcs7->content = (byte*)testVectors[i].content; pkcs7->contentSz = testVectors[i].contentSz; @@ -19642,7 +19834,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9418; + return -9419; } } @@ -19654,7 +19846,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9419; + return -9420; } } @@ -19667,7 +19859,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9420; + return -9421; } } @@ -19690,7 +19882,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9421; + return -9422; } wc_ShaUpdate(&sha, pkcs7->publicKey, pkcs7->publicKeySz); wc_ShaFinal(&sha, digest); @@ -19700,7 +19892,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9422; + return -9423; } wc_Sha256Update(&sha, pkcs7->publicKey, pkcs7->publicKeySz); wc_Sha256Final(&sha, digest); @@ -19716,7 +19908,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (encodedSz < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9423; + return -9424; } #ifdef PKCS7_OUTPUT_TEST_BUNDLES @@ -19725,14 +19917,14 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (!file) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9424; + return -9425; } ret = (int)fwrite(out, 1, encodedSz, file); fclose(file); if (ret != (int)encodedSz) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9425; + return -9426; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ @@ -19740,23 +19932,23 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); if (pkcs7 == NULL) - return -9426; + return -9427; wc_PKCS7_InitWithCert(pkcs7, NULL, 0); ret = wc_PKCS7_VerifySignedData(pkcs7, out, outSz); if (ret < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9427; + return -9428; } /* verify contentType extracted successfully for custom content types */ if (testVectors[i].contentTypeSz > 0) { if (pkcs7->contentTypeSz != testVectors[i].contentTypeSz) { - return -9428; + return -9429; } else if (XMEMCMP(pkcs7->contentType, testVectors[i].contentType, pkcs7->contentTypeSz) != 0) { - return -9429; + return -9430; } } @@ -19764,7 +19956,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9430; + return -9431; } { @@ -19774,7 +19966,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, #else byte buf[(WC_SHA256_DIGEST_SIZE + 1) * 2 + 1]; #endif - byte* oidPt = transIdOid + 2; /* skip object id tag and size */ + byte* oidPt = transIdOid + 2; /* skip object id tag and size */ int oidSz = (int)sizeof(transIdOid) - 2; int bufSz = 0; @@ -19783,13 +19975,13 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, NULL, (word32*)&bufSz) != LENGTH_ONLY_E) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9431; + return -9432; } if (bufSz > (int)sizeof(buf)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9432; + return -9433; } bufSz = wc_PKCS7_GetAttributeValue(pkcs7, oidPt, oidSz, @@ -19798,7 +19990,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, (testVectors[i].signedAttribs == NULL && bufSz > 0)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9433; + return -9434; } } @@ -19807,7 +19999,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, if (!file) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9434; + return -9435; } ret = (int)fwrite(pkcs7->singleCert, 1, pkcs7->singleCertSz, file); fclose(file); @@ -19829,12 +20021,28 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, (void)eccPrivKeySz; #endif #ifdef NO_RSA - (void)rsaCert; - (void)rsaCertSz; - (void)rsaPrivKey; - (void)rsaPrivKeySz; + (void)rsaClientCertBuf; + (void)rsaClientCertBufSz; + (void)rsaClientPrivKeyBuf; + (void)rsaClientPrivKeyBufSz; + (void)rsaServerCertBuf; + (void)rsaServerCertBufSz; + (void)rsaServerPrivKeyBuf; + (void)rsaServerPrivKeyBufSz; + (void)rsaCaCertBuf; + (void)rsaCaCertBufSz; + (void)rsaCaPrivKeyBuf; + (void)rsaCaPrivKeyBufSz; #endif + (void)rsaServerCertBuf; + (void)rsaServerCertBufSz; + (void)rsaServerPrivKeyBuf; + (void)rsaServerPrivKeyBufSz; + (void)rsaCaCertBuf; + (void)rsaCaCertBufSz; + (void)rsaCaPrivKeyBuf; + (void)rsaCaPrivKeyBufSz; return ret; } @@ -19843,73 +20051,130 @@ int pkcs7signed_test(void) { int ret = 0; - byte* rsaCert = NULL; - byte* eccCert = NULL; - byte* rsaPrivKey = NULL; - byte* eccPrivKey = NULL; + byte* rsaClientCertBuf = NULL; + byte* rsaServerCertBuf = NULL; + byte* rsaCaCertBuf = NULL; + byte* eccClientCertBuf = NULL; + byte* rsaClientPrivKeyBuf = NULL; + byte* rsaServerPrivKeyBuf = NULL; + byte* rsaCaPrivKeyBuf = NULL; + byte* eccClientPrivKeyBuf = NULL; - word32 rsaCertSz = 0; - word32 eccCertSz = 0; - word32 rsaPrivKeySz = 0; - word32 eccPrivKeySz = 0; + word32 rsaClientCertBufSz = 0; + word32 rsaServerCertBufSz = 0; + word32 rsaCaCertBufSz = 0; + word32 eccClientCertBufSz = 0; + word32 rsaClientPrivKeyBufSz = 0; + word32 rsaServerPrivKeyBufSz = 0; + word32 rsaCaPrivKeyBufSz = 0; + word32 eccClientPrivKeyBufSz = 0; #ifndef NO_RSA /* read client RSA cert and key in DER format */ - rsaCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (rsaCert == NULL) + rsaClientCertBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (rsaClientCertBuf == NULL) return -9500; - rsaPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (rsaPrivKey == NULL) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + rsaClientPrivKeyBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (rsaClientPrivKeyBuf == NULL) { + XFREE(rsaClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -9501; } - rsaCertSz = FOURK_BUF; - rsaPrivKeySz = FOURK_BUF; + rsaClientCertBufSz = FOURK_BUF; + rsaClientPrivKeyBufSz = FOURK_BUF; + + /* read server RSA cert and key in DER format */ + rsaServerCertBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (rsaServerCertBuf == NULL) + return -9502; + + rsaServerPrivKeyBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (rsaServerPrivKeyBuf == NULL) { + XFREE(rsaServerCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -9503; + } + + rsaServerCertBufSz = FOURK_BUF; + rsaServerPrivKeyBufSz = FOURK_BUF; + + /* read CA RSA cert and key in DER format, for use with server cert */ + rsaCaCertBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (rsaCaCertBuf == NULL) + return -9504; + + rsaCaPrivKeyBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (rsaCaPrivKeyBuf == NULL) { + XFREE(rsaCaCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -9505; + } + + rsaCaCertBufSz = FOURK_BUF; + rsaCaPrivKeyBufSz = FOURK_BUF; #endif /* NO_RSA */ #ifdef HAVE_ECC /* read client ECC cert and key in DER format */ - eccCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (eccCert == NULL) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -9502; + eccClientCertBuf = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (eccClientCertBuf == NULL) { + XFREE(rsaClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -9506; } - eccPrivKey =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (eccPrivKey == NULL) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -9503; + eccClientPrivKeyBuf =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (eccClientPrivKeyBuf == NULL) { + XFREE(rsaClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -9507; } - eccCertSz = FOURK_BUF; - eccPrivKeySz = FOURK_BUF; + eccClientCertBufSz = FOURK_BUF; + eccClientPrivKeyBufSz = FOURK_BUF; #endif /* HAVE_ECC */ - ret = pkcs7_load_certs_keys(rsaCert, &rsaCertSz, rsaPrivKey, - &rsaPrivKeySz, eccCert, &eccCertSz, - eccPrivKey, &eccPrivKeySz); + ret = pkcs7_load_certs_keys(rsaClientCertBuf, &rsaClientCertBufSz, + rsaClientPrivKeyBuf, &rsaClientPrivKeyBufSz, + rsaServerCertBuf, &rsaServerCertBufSz, + rsaServerPrivKeyBuf, &rsaServerPrivKeyBufSz, + rsaCaCertBuf, &rsaCaCertBufSz, + rsaCaPrivKeyBuf, &rsaCaPrivKeyBufSz, + eccClientCertBuf, &eccClientCertBufSz, + eccClientPrivKeyBuf, &eccClientPrivKeyBufSz); if (ret < 0) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return ret; } - ret = pkcs7signed_run_vectors(rsaCert, (word32)rsaCertSz, - rsaPrivKey, (word32)rsaPrivKeySz, - eccCert, (word32)eccCertSz, - eccPrivKey, (word32)eccPrivKeySz); + ret = pkcs7signed_run_vectors(rsaClientCertBuf, (word32)rsaClientCertBufSz, + rsaClientPrivKeyBuf, (word32)rsaClientPrivKeyBufSz, + rsaServerCertBuf, (word32)rsaServerCertBufSz, + rsaServerPrivKeyBuf, (word32)rsaServerPrivKeyBufSz, + rsaCaCertBuf, (word32)rsaCaCertBufSz, + rsaCaPrivKeyBuf, (word32)rsaCaPrivKeyBufSz, + eccClientCertBuf, (word32)eccClientCertBufSz, + eccClientPrivKeyBuf, (word32)eccClientPrivKeyBufSz); - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaServerCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaServerPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaCaCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaCaPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return ret; } diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 83460c9b1..b07ea087a 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -102,6 +102,7 @@ typedef struct PKCS7DecodedAttrib { word32 valueSz; } PKCS7DecodedAttrib; +typedef struct Pkcs7Cert Pkcs7Cert; /* Public Structure Warning: * Existing members must not be changed to maintain backwards compatibility! @@ -161,7 +162,8 @@ typedef struct PKCS7 { int sidType; /* SignerIdentifier type to use, of type Pkcs7_SignerIdentifier_Types, default to SID_ISSUER_AND_SERIAL_NUMBER */ - byte issuerSubjKeyId[KEYID_SIZE]; /* SubjectKeyIdentifier of singleCert */ + byte issuerSubjKeyId[KEYID_SIZE]; /* SubjectKeyIdentifier of singleCert */ + Pkcs7Cert* certList; /* certificates list for SignedData set */ /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ } PKCS7; @@ -169,7 +171,8 @@ typedef struct PKCS7 { WOLFSSL_API PKCS7* wc_PKCS7_New(void* heap, int devId); WOLFSSL_API int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId); -WOLFSSL_API int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz); +WOLFSSL_API int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* der, word32 derSz); +WOLFSSL_API int wc_PKCS7_AddCertificate(PKCS7* pkcs7, byte* der, word32 derSz); WOLFSSL_API void wc_PKCS7_Free(PKCS7* pkcs7); WOLFSSL_API int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid, From 1f8c4c2613ca363595b884738e14cad7653c65cb Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 31 Aug 2018 14:38:19 -0600 Subject: [PATCH 11/56] merge CMS changes with master --- wolfcrypt/src/pkcs7.c | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 3a37fc7e2..aa4b82e20 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -842,26 +842,11 @@ static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) * * return 0 on success, negative on error */ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, - const byte* contentTypeOid, word32 contentTypeOidSz, const byte* contentType, word32 contentTypeSz, + const byte* contentTypeOid, word32 contentTypeOidSz, const byte* messageDigestOid, word32 messageDigestOidSz, const byte* signingTimeOid, word32 signingTimeOidSz) { - /* contentType OID (1.2.840.113549.1.9.3) */ - byte contentTypeOid[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, - 0x09, 0x03 }; - - /* messageDigest OID (1.2.840.113549.1.9.4) */ - byte messageDigestOid[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x04 }; - - /* signingTime OID () */ - byte signingTimeOid[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x05}; - int hashSz; #ifdef NO_ASN_TIME @@ -891,16 +876,16 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); cannedAttribs[0].oid = contentTypeOid; - cannedAttribs[0].oidSz = sizeof(contentTypeOid); + cannedAttribs[0].oidSz = contentTypeOidSz; cannedAttribs[0].value = contentType; cannedAttribs[0].valueSz = contentTypeSz; cannedAttribs[1].oid = messageDigestOid; - cannedAttribs[1].oidSz = sizeof(messageDigestOid); + cannedAttribs[1].oidSz = messageDigestOidSz; cannedAttribs[1].value = esd->contentDigest; cannedAttribs[1].valueSz = hashSz + 2; /* ASN.1 heading */ #ifndef NO_ASN_TIME cannedAttribs[2].oid = signingTimeOid; - cannedAttribs[2].oidSz = sizeof(signingTimeOid); + cannedAttribs[2].oidSz = signingTimeOidSz; cannedAttribs[2].value = (byte*)signingTime; cannedAttribs[2].valueSz = signingTimeSz; #endif @@ -1337,7 +1322,10 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, /* build up signed attributes */ ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, pkcs7->contentType, - pkcs7->contentTypeSz); + pkcs7->contentTypeSz, + contentTypeOid, sizeof(contentTypeOid), + messageDigestOid, sizeof(messageDigestOid), + signingTimeOid, sizeof(signingTimeOid)); if (ret < 0) { return MEMORY_E; } @@ -2356,13 +2344,13 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, /* Get the inner ContentInfo contentType */ { - localIdx = idx; + word32 tmpIdx = idx; if (GetASNObjectId(pkiMsg, &idx, &length, pkiMsgSz) != 0) return ASN_PARSE_E; - contentType = pkiMsg + localIdx; - contentTypeSz = length + (idx - localIdx); + contentType = pkiMsg + tmpIdx; + contentTypeSz = length + (idx - tmpIdx); idx += length; } From ec07fe492ea33bfdd8c2f880e7a561d966abecfc Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 31 Aug 2018 14:44:47 -0600 Subject: [PATCH 12/56] misc CMS fixes from review and valgrind --- wolfcrypt/src/asn.c | 10 ++-- wolfcrypt/src/pkcs7.c | 120 +++++++++++++++++++++++------------------- wolfcrypt/test/test.c | 2 + 3 files changed, 74 insertions(+), 58 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 84f9da44a..802760c73 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -4894,17 +4894,17 @@ int GetAsnTimeString(byte* buf, word32 len) /* Note ASN_UTC_TIME_SIZE and ASN_GENERALIZED_TIME_SIZE include space for * the null terminator. ASN encoded values leave off the terminator. */ - if (ts->tm_year >= 50 && ts->tm_year < 150){ + if (ts->tm_year >= 50 && ts->tm_year < 150) { /* UTC Time */ char utc_str[ASN_UTC_TIME_SIZE]; - data_len = ASN_UTC_TIME_SIZE -1 + 2; + data_len = ASN_UTC_TIME_SIZE - 1 + 2; if (len < data_len) return BUFFER_E; - if (ts->tm_year >= 50 && ts->tm_year < 100){ + if (ts->tm_year >= 50 && ts->tm_year < 100) { year = ts->tm_year; - } else if (ts->tm_year >= 100 && ts->tm_year < 150){ + } else if (ts->tm_year >= 100 && ts->tm_year < 150) { year = ts->tm_year - 100; } mon = ts->tm_mon + 1; @@ -4922,7 +4922,7 @@ int GetAsnTimeString(byte* buf, word32 len) } else { /* GeneralizedTime */ char gt_str[ASN_GENERALIZED_TIME_SIZE]; - data_len = ASN_GENERALIZED_TIME_SIZE + 1; + data_len = ASN_GENERALIZED_TIME_SIZE - 1 + 2; if (len < data_len) return BUFFER_E; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index aa4b82e20..93d45992d 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -306,6 +306,29 @@ typedef struct Pkcs7Cert { } Pkcs7Cert; +/* free all members of Pkcs7Cert linked list */ +static void wc_PKCS7_FreeCertSet(PKCS7* pkcs7) +{ + Pkcs7Cert* curr = NULL; + Pkcs7Cert* next = NULL; + + if (pkcs7 == NULL) + return; + + curr = pkcs7->certList; + pkcs7->certList = NULL; + + while (curr != NULL) { + next = curr->next; + curr->next = NULL; + XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + curr = next; + } + + return; +} + + /* Init PKCS7 struct with recipient cert, decode into DecodedCert * NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) @@ -352,6 +375,9 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) cert->derSz = derCertSz; cert->next = NULL; + /* free existing cert list if existing */ + wc_PKCS7_FreeCertSet(pkcs7); + /* add recipient to cert list */ if (pkcs7->certList == NULL) { pkcs7->certList = cert; @@ -462,29 +488,6 @@ static void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib, void* heap) } -/* free all members of Pkcs7Cert linked list */ -static int wc_PKCS7_FreeCertSet(PKCS7* pkcs7) -{ - Pkcs7Cert* curr = NULL; - Pkcs7Cert* next = NULL; - - if (pkcs7 == NULL) - return BAD_FUNC_ARG; - - curr = pkcs7->certList; - pkcs7->certList = NULL; - - while (curr != NULL) { - next = curr->next; - curr->next = NULL; - XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - curr = next; - } - - return 0; -} - - /* releases any memory allocated by a PKCS7 initializer */ void wc_PKCS7_Free(PKCS7* pkcs7) { @@ -492,6 +495,7 @@ void wc_PKCS7_Free(PKCS7* pkcs7) return; wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); + wc_PKCS7_FreeCertSet(pkcs7); #ifdef ASN_BER_TO_DER if (pkcs7->der != NULL) @@ -500,12 +504,12 @@ void wc_PKCS7_Free(PKCS7* pkcs7) if (pkcs7->contentDynamic != NULL) XFREE(pkcs7->contentDynamic, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->contentTypeSz = 0; + if (pkcs7->isDynamic) { pkcs7->isDynamic = 0; XFREE(pkcs7, pkcs7->heap, DYNAMIC_TYPE_PKCS7); } - - pkcs7->contentTypeSz = 0; } @@ -845,21 +849,21 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, const byte* contentType, word32 contentTypeSz, const byte* contentTypeOid, word32 contentTypeOidSz, const byte* messageDigestOid, word32 messageDigestOidSz, - const byte* signingTimeOid, word32 signingTimeOidSz) + const byte* signingTimeOid, word32 signingTimeOidSz, + byte* signingTime, word32 signingTimeSz) { - int hashSz; + int hashSz, timeSz; #ifdef NO_ASN_TIME PKCS7Attrib cannedAttribs[2]; #else PKCS7Attrib cannedAttribs[3]; - byte signingTime[MAX_TIME_STRING_SZ]; - int signingTimeSz; #endif word32 cannedAttribsCount; if (pkcs7 == NULL || esd == NULL || contentType == NULL || - messageDigestOid == NULL) { + contentTypeOid == NULL || messageDigestOid == NULL || + signingTimeOid == NULL) { return BAD_FUNC_ARG; } @@ -868,9 +872,12 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, return hashSz; #ifndef NO_ASN_TIME - signingTimeSz = GetAsnTimeString(signingTime, sizeof(signingTime)); - if (signingTimeSz < 0) - return signingTimeSz; + if (signingTime == NULL || signingTimeSz == 0) + return BAD_FUNC_ARG; + + timeSz = GetAsnTimeString(signingTime, signingTimeSz); + if (timeSz < 0) + return timeSz; #endif cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); @@ -886,8 +893,8 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, #ifndef NO_ASN_TIME cannedAttribs[2].oid = signingTimeOid; cannedAttribs[2].oidSz = signingTimeOidSz; - cannedAttribs[2].value = (byte*)signingTime; - cannedAttribs[2].valueSz = signingTimeSz; + cannedAttribs[2].value = signingTime; + cannedAttribs[2].valueSz = timeSz; #endif esd->signedAttribsCount += cannedAttribsCount; @@ -1103,9 +1110,9 @@ static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, word32 flatSignedAttribsSz, ESD* esd) { - int ret; + int ret = 0; #ifdef HAVE_ECC - int hashSz; + int hashSz = 0; #endif word32 digestInfoSz = MAX_PKCS7_DIGEST_SZ; #ifdef WOLFSSL_SMALL_STACK @@ -1124,6 +1131,7 @@ static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, return MEMORY_E; } #endif + XMEMSET(digestInfo, 0, digestInfoSz); ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs, flatSignedAttribsSz, esd, digestInfo, @@ -1211,6 +1219,8 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, byte signedDataOid[MAX_OID_SZ]; word32 signedDataOidSz; + byte signingTime[MAX_TIME_STRING_SZ]; + if (pkcs7 == NULL || pkcs7->contentSz == 0 || pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 || output == NULL || outputSz == NULL || *outputSz == 0 || hashSz == 0 || @@ -1325,9 +1335,10 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, pkcs7->contentTypeSz, contentTypeOid, sizeof(contentTypeOid), messageDigestOid, sizeof(messageDigestOid), - signingTimeOid, sizeof(signingTimeOid)); + signingTimeOid, sizeof(signingTimeOid), + signingTime, sizeof(signingTime)); if (ret < 0) { - return MEMORY_E; + return ret; } flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap, @@ -1453,9 +1464,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, idx += certPtr->derSz; certPtr = certPtr->next; } - ret = wc_PKCS7_FreeCertSet(pkcs7); - if (ret != 0) - return ret; + wc_PKCS7_FreeCertSet(pkcs7); XMEMCPY(output2 + idx, esd->signerInfoSet, esd->signerInfoSetSz); idx += esd->signerInfoSetSz; @@ -1697,13 +1706,16 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, } ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, key); + FreeDecodedCert(dCert); wc_FreeRsaKey(key); - if (((int)hashSz == ret) && (XMEMCMP(digest, hash, ret) == 0)) { - /* found signer that successfully verified signature */ - verified = 1; - break; + if ((ret > 0) && (hashSz == (word32)ret)) { + if (XMEMCMP(digest, hash, hashSz) == 0) { + /* found signer that successfully verified signature */ + verified = 1; + break; + } } } @@ -1851,7 +1863,7 @@ static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib, const byte* hashBuf, word32 hashBufSz) { int ret = 0, digIdx = 0; - word32 attribSetSz, hashSz; + word32 attribSetSz = 0, hashSz = 0; byte attribSet[MAX_SET_SZ]; byte digest[WC_MAX_DIGEST_SIZE]; byte digestInfoSeq[MAX_SEQ_SZ]; @@ -1982,9 +1994,9 @@ static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib, * * return 0 on success, negative on error */ static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig, - word32 sigSz, byte* signedAttrib, - word32 signedAttribSz, - const byte* hashBuf, word32 hashSz) + word32 sigSz, byte* signedAttrib, + word32 signedAttribSz, + const byte* hashBuf, word32 hashSz) { int ret = 0; word32 plainDigestSz = 0, pkcs7DigestSz; @@ -1998,15 +2010,17 @@ static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig, if (pkcs7 == NULL) return BAD_FUNC_ARG; + /* build hash to verify against */ + pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ; #ifdef WOLFSSL_SMALL_STACK - pkcs7Digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, + pkcs7Digest = (byte*)XMALLOC(pkcs7DigestSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); if (pkcs7Digest == NULL) return MEMORY_E; #endif - /* build hash to verify against */ - pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ; + XMEMSET(pkcs7Digest, 0, pkcs7DigestSz); + ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib, signedAttribSz, pkcs7Digest, &pkcs7DigestSz, &plainDigest, diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index b35d0769f..4688442b7 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19772,6 +19772,8 @@ static int pkcs7signed_run_vectors( if (out == NULL) return -9413; + XMEMSET(out, 0, outSz); + ret = wc_PKCS7_PadData((byte*)data, sizeof(data), out, outSz, 16); if (ret < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); From dbb5bb75708180319d9fcca46845d77816fcf73b Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 12 Sep 2018 13:23:35 -0600 Subject: [PATCH 13/56] add CMS EnvelopedData KEKRecipientInfo support --- .gitignore | 1 + Makefile.am | 1 + wolfcrypt/src/asn.c | 11 +- wolfcrypt/src/pkcs7.c | 1280 +++++++++++++++++++++++++++---------- wolfcrypt/test/test.c | 142 +++- wolfssl/wolfcrypt/asn.h | 2 +- wolfssl/wolfcrypt/pkcs7.h | 50 +- 7 files changed, 1105 insertions(+), 382 deletions(-) diff --git a/.gitignore b/.gitignore index 5fc8e74b6..07184013c 100644 --- a/.gitignore +++ b/.gitignore @@ -115,6 +115,7 @@ pkcs7signedData_ECDSA_SHA384.der pkcs7signedData_ECDSA_SHA512.der pkcs7envelopedDataDES3.der pkcs7envelopedDataAES128CBC.der +pkcs7envelopedDataAES128CBC_KEKRI.der pkcs7envelopedDataAES192CBC.der pkcs7envelopedDataAES256CBC.der diff diff --git a/Makefile.am b/Makefile.am index 47b084047..c91d70032 100644 --- a/Makefile.am +++ b/Makefile.am @@ -56,6 +56,7 @@ CLEANFILES+= cert.der \ pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der \ pkcs7envelopedDataDES3.der \ pkcs7envelopedDataAES128CBC.der \ + pkcs7envelopedDataAES128CBC_KEKRI.der \ pkcs7envelopedDataAES192CBC.der \ pkcs7envelopedDataAES256CBC.der \ pkcs7signedData_RSA_SHA.der \ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 802760c73..e6f5323ad 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -4863,10 +4863,12 @@ int GetTimeString(byte* date, int format, char* buf, int len) #if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7) -/* set current time string, either UTC or GeneralizedTime */ -int GetAsnTimeString(byte* buf, word32 len) +/* Set current time string, either UTC or GeneralizedTime. + * (void*) tm should be a pointer to time_t, output is placed in buf. + * + * Return time string length placed in buf on success, negative on error */ +int GetAsnTimeString(void* currTime, byte* buf, word32 len) { - time_t currTime; struct tm* ts = NULL; struct tm* tmpTime = NULL; #if defined(NEED_TMP_TIME) @@ -4884,8 +4886,7 @@ int GetAsnTimeString(byte* buf, word32 len) if (buf == NULL || len == 0) return BAD_FUNC_ARG; - currTime = XTIME(0); - ts = (struct tm *)XGMTIME(&currTime, tmpTime); + ts = (struct tm *)XGMTIME(currTime, tmpTime); if (ts == NULL){ WOLFSSL_MSG("failed to get time data."); return ASN_TIME_E; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 93d45992d..932834a23 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -306,6 +306,14 @@ typedef struct Pkcs7Cert { } Pkcs7Cert; +/* Linked list of ASN.1 encoded RecipientInfos */ +typedef struct Pkcs7EncodedRecip { + byte recip[MAX_RECIP_SZ]; + word32 recipSz; + Pkcs7EncodedRecip* next; +} Pkcs7EncodedRecip; + + /* free all members of Pkcs7Cert linked list */ static void wc_PKCS7_FreeCertSet(PKCS7* pkcs7) { @@ -329,6 +337,53 @@ static void wc_PKCS7_FreeCertSet(PKCS7* pkcs7) } +/* Get total size of all recipients in recipient list. + * + * Returns total size of recipients, or negative upon error */ +static int wc_PKCS7_GetRecipientListSize(PKCS7* pkcs7) +{ + int totalSz = 0; + Pkcs7EncodedRecip* tmp = NULL; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + tmp = pkcs7->recipList; + + while (tmp != NULL) { + printf("DEBUG: tmp = %p\n", tmp); + printf("DEBUG: tmp->recipSz = %d\n", tmp->recipSz); + totalSz += tmp->recipSz; + tmp = tmp->next; + } + + return totalSz; +} + + +/* free all members of Pkcs7EncodedRecip linked list */ +static void wc_PKCS7_FreeEncodedRecipientSet(PKCS7* pkcs7) +{ + Pkcs7EncodedRecip* curr = NULL; + Pkcs7EncodedRecip* next = NULL; + + if (pkcs7 == NULL) + return; + + curr = pkcs7->recipList; + pkcs7->recipList = NULL; + + while (curr != NULL) { + next = curr->next; + curr->next = NULL; + XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + curr = next; + } + + return; +} + + /* Init PKCS7 struct with recipient cert, decode into DecodedCert * NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) @@ -378,7 +433,7 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) /* free existing cert list if existing */ wc_PKCS7_FreeCertSet(pkcs7); - /* add recipient to cert list */ + /* add cert to list */ if (pkcs7->certList == NULL) { pkcs7->certList = cert; } else { @@ -412,6 +467,9 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) /* default to IssuerAndSerialNumber for SignerIdentifier */ pkcs7->sidType = SID_ISSUER_AND_SERIAL_NUMBER; + /* free existing recipient list if existing */ + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + FreeDecodedCert(dCert); #ifdef WOLFSSL_SMALL_STACK @@ -504,6 +562,11 @@ void wc_PKCS7_Free(PKCS7* pkcs7) if (pkcs7->contentDynamic != NULL) XFREE(pkcs7->contentDynamic, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->cek != NULL) { + ForceZero(pkcs7->cek, pkcs7->cekSz); + XFREE(pkcs7->cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + pkcs7->contentTypeSz = 0; if (pkcs7->isDynamic) { @@ -853,6 +916,7 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, byte* signingTime, word32 signingTimeSz) { int hashSz, timeSz; + time_t tm; #ifdef NO_ASN_TIME PKCS7Attrib cannedAttribs[2]; @@ -875,7 +939,8 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, if (signingTime == NULL || signingTimeSz == 0) return BAD_FUNC_ARG; - timeSz = GetAsnTimeString(signingTime, signingTimeSz); + tm = XTIME(0); + timeSz = GetAsnTimeString(&tm, signingTime, signingTimeSz); if (timeSz < 0) return timeSz; #endif @@ -2735,6 +2800,65 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) } +/* Generate random content encryption key, store into pkcs7->cek and + * pkcs7->cekSz. + * + * pkcs7 - pointer to initialized PKCS7 structure + * len - length of key to be generated + * + * Returns 0 on success, negative upon error */ +static int PKCS7_GenerateContentEncryptionKey(PKCS7* pkcs7, word32 len) +{ + int ret; + WC_RNG rng; + byte* tmpKey; + + if (pkcs7 == NULL || len == 0) + return BAD_FUNC_ARG; + + /* if key already exists, don't need to re-generate */ + if (pkcs7->cek != NULL && pkcs7->cekSz != 0) { + + /* if key exists, but is different size, return error */ + if (pkcs7->cekSz != len) { + WOLFSSL_MSG("Random content-encryption key size is inconsistent " + "between CMS recipients"); + return WC_KEY_SIZE_E; + } + + return 0; + } + + /* allocate space for cek */ + tmpKey = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (tmpKey == NULL) + return MEMORY_E; + + XMEMSET(tmpKey, 0, len); + + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + XFREE(tmpKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + ret = wc_RNG_GenerateBlock(&rng, tmpKey, len); + if (ret != 0) { + wc_FreeRng(&rng); + XFREE(tmpKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* store into PKCS7, memory freed during final cleanup */ + pkcs7->cek = tmpKey; + pkcs7->cekSz = len; + + wc_FreeRng(&rng); + + return 0; +} + + #ifdef HAVE_ECC /* KARI == KeyAgreeRecipientInfo (key agreement) */ @@ -2761,9 +2885,9 @@ typedef struct WC_PKCS7_KARI { /* wrap CEK (content encryption key) with KEK, 0 on success, < 0 on error */ -static int wc_PKCS7_KariKeyWrap(byte* cek, word32 cekSz, byte* kek, - word32 kekSz, byte* out, word32 outSz, - int keyWrapAlgo, int direction) +static int wc_PKCS7_KeyWrap(byte* cek, word32 cekSz, byte* kek, + word32 kekSz, byte* out, word32 outSz, + int keyWrapAlgo, int direction) { int ret; @@ -2999,13 +3123,13 @@ static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, /* create ephemeral ECC key, places ecc_key in kari->senderKey, * DER encoded in kari->senderKeyExport. return 0 on success, * negative on error */ -static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, WC_RNG* rng) +static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari) { int ret; + WC_RNG rng; if (kari == NULL || kari->decoded == NULL || - kari->recipKey == NULL || kari->recipKey->dp == NULL || - rng == NULL) + kari->recipKey == NULL || kari->recipKey->dp == NULL) return BAD_FUNC_ARG; kari->senderKeyExport = (byte*)XMALLOC(kari->decoded->pubKeySize, @@ -3016,21 +3140,36 @@ static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari, WC_RNG* rng) kari->senderKeyExportSz = kari->decoded->pubKeySize; ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId); - if (ret != 0) + if (ret != 0) { + XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); return ret; + } kari->senderKeyInit = 1; - ret = wc_ecc_make_key_ex(rng, kari->recipKey->dp->size, - kari->senderKey, kari->recipKey->dp->id); - if (ret != 0) + ret = wc_InitRng_ex(&rng, kari->heap, kari->devId); + if (ret != 0) { + XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); return ret; + } + + ret = wc_ecc_make_key_ex(&rng, kari->recipKey->dp->size, + kari->senderKey, kari->recipKey->dp->id); + if (ret != 0) { + XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + return ret; + } + + wc_FreeRng(&rng); /* dump generated key to X.963 DER for output in CMS bundle */ ret = wc_ecc_export_x963(kari->senderKey, kari->senderKeyExport, &kari->senderKeyExportSz); - if (ret != 0) + if (ret != 0) { + XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); return ret; + } return 0; } @@ -3233,15 +3372,22 @@ static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, } -/* create ASN.1 formatted KeyAgreeRecipientInfo (kari) for use with ECDH, - * return sequence size or negative on error */ -static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert, - word32 certSz, int keyAgreeAlgo, int blockKeySz, - int keyWrapAlgo, int keyEncAlgo, WC_RNG* rng, - byte* contentKeyPlain, byte* contentKeyEnc, - int* keyEncSz, byte* out, word32 outSz) +/* Encode and add CMS EnvelopedData KARI (KeyAgreeRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, + int keyWrapOID, int keyAgreeOID, byte* ukm, + word32 ukmSz) { - int ret = 0, idx = 0; + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + WC_PKCS7_KARI* kari = NULL; + + word32 idx = 0; + word32 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + + int ret = 0; int keySz, direction = 0; /* ASN.1 layout */ @@ -3282,14 +3428,41 @@ static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert, int encryptedKeyOctetSz = 0; byte encryptedKeyOctet[MAX_OCTET_STR_SZ]; - WC_PKCS7_KARI* kari; +#ifdef WOLFSSL_SMALL_STACK + byte* encryptedKey; + + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedKey == NULL) { + return MEMORY_E; + } +#else + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; +#endif + + /* allocate and init memory for recipient */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (recip == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); /* only supports ECDSA for now */ - if (keyAgreeAlgo != ECDSAk) + if (pkcs7->publicKeyOID != ECDSAk) { + WOLFSSL_MSG("CMS KARI only supports ECDSA key types"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return BAD_FUNC_ARG; + } /* set direction based on keyWrapAlgo */ - switch (keyWrapAlgo) { + switch (keyWrapOID) { #ifndef NO_AES #ifdef WOLFSSL_AES_128 case AES128_WRAP: @@ -3305,17 +3478,26 @@ static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert, #endif default: WOLFSSL_MSG("Unsupported key wrap algorithm"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return BAD_KEYWRAP_ALG_E; } kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_ENCODE); - if (kari == NULL) + if (kari == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return MEMORY_E; + } /* set user keying material if available */ - if ((pkcs7->ukmSz > 0) && (pkcs7->ukm != NULL)) { - kari->ukm = pkcs7->ukm; - kari->ukmSz = pkcs7->ukmSz; + if (ukmSz > 0 && ukm != NULL) { + kari->ukm = ukm; + kari->ukmSz = ukmSz; kari->ukmOwner = 0; } @@ -3323,38 +3505,54 @@ static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert, ret = wc_PKCS7_KariParseRecipCert(kari, cert, certSz, NULL, 0); if (ret != 0) { wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } /* generate sender ephemeral ECC key */ - ret = wc_PKCS7_KariGenerateEphemeralKey(kari, rng); + ret = wc_PKCS7_KariGenerateEphemeralKey(kari); if (ret != 0) { wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } /* generate KEK (key encryption key) */ - ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapAlgo, keyEncAlgo); + ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, keyAgreeOID); if (ret != 0) { wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } /* encrypt CEK with KEK */ - keySz = wc_PKCS7_KariKeyWrap(contentKeyPlain, blockKeySz, kari->kek, - kari->kekSz, contentKeyEnc, *keyEncSz, keyWrapAlgo, - direction); + keySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kari->kek, + kari->kekSz, encryptedKey, encryptedKeySz, + keyWrapOID, direction); if (keySz <= 0) { wc_PKCS7_KariFree(kari); - return ret; +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return keySz; } - *keyEncSz = (word32)keySz; + encryptedKeySz = (word32)keySz; /* Start of RecipientEncryptedKeys */ /* EncryptedKey */ - encryptedKeyOctetSz = SetOctetString(*keyEncSz, encryptedKeyOctet); - totalSz += (encryptedKeyOctetSz + *keyEncSz); + encryptedKeyOctetSz = SetOctetString(encryptedKeySz, encryptedKeyOctet); + totalSz += (encryptedKeyOctetSz + encryptedKeySz); /* SubjectKeyIdentifier */ subjKeyIdOctetSz = SetOctetString(KEYID_SIZE, subjKeyIdOctet); @@ -3387,11 +3585,11 @@ static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert, /* Start of KeyEncryptionAlgorithmIdentifier */ /* KeyWrapAlgorithm */ - keyWrapAlgSz = SetAlgoID(keyWrapAlgo, keyWrapAlg, oidKeyWrapType, 0); + keyWrapAlgSz = SetAlgoID(keyWrapOID, keyWrapAlg, oidKeyWrapType, 0); totalSz += keyWrapAlgSz; /* KeyEncryptionAlgorithmIdentifier */ - keyEncryptAlgoIdSz = SetAlgoID(keyEncAlgo, keyEncryptAlgoId, + keyEncryptAlgoIdSz = SetAlgoID(keyAgreeOID, keyEncryptAlgoId, oidCmsKeyAgreeType, keyWrapAlgSz); totalSz += keyEncryptAlgoIdSz; @@ -3429,62 +3627,82 @@ static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert, kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq); totalSz += kariSeqSz; - if ((word32)totalSz > outSz) { + if (totalSz > MAX_RECIP_SZ) { WOLFSSL_MSG("KeyAgreeRecipientInfo output buffer too small"); wc_PKCS7_KariFree(kari); - +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return BUFFER_E; } - XMEMCPY(out + idx, kariSeq, kariSeqSz); + XMEMCPY(recip->recip + idx, kariSeq, kariSeqSz); idx += kariSeqSz; - XMEMCPY(out + idx, ver, verSz); + XMEMCPY(recip->recip + idx, ver, verSz); idx += verSz; - XMEMCPY(out + idx, origIdOrKeySeq, origIdOrKeySeqSz); + XMEMCPY(recip->recip + idx, origIdOrKeySeq, origIdOrKeySeqSz); idx += origIdOrKeySeqSz; - XMEMCPY(out + idx, origPubKeySeq, origPubKeySeqSz); + XMEMCPY(recip->recip + idx, origPubKeySeq, origPubKeySeqSz); idx += origPubKeySeqSz; - XMEMCPY(out + idx, origAlgId, origAlgIdSz); + XMEMCPY(recip->recip + idx, origAlgId, origAlgIdSz); idx += origAlgIdSz; - XMEMCPY(out + idx, origPubKeyStr, origPubKeyStrSz); + XMEMCPY(recip->recip + idx, origPubKeyStr, origPubKeyStrSz); idx += origPubKeyStrSz; /* ephemeral public key */ - XMEMCPY(out + idx, kari->senderKeyExport, kari->senderKeyExportSz); + XMEMCPY(recip->recip + idx, kari->senderKeyExport, kari->senderKeyExportSz); idx += kari->senderKeyExportSz; if (kari->ukmSz > 0) { - XMEMCPY(out + idx, ukmExplicitSeq, ukmExplicitSz); + XMEMCPY(recip->recip + idx, ukmExplicitSeq, ukmExplicitSz); idx += ukmExplicitSz; - XMEMCPY(out + idx, ukmOctetStr, ukmOctetSz); + XMEMCPY(recip->recip + idx, ukmOctetStr, ukmOctetSz); idx += ukmOctetSz; - XMEMCPY(out + idx, kari->ukm, kari->ukmSz); + XMEMCPY(recip->recip + idx, kari->ukm, kari->ukmSz); idx += kari->ukmSz; } - XMEMCPY(out + idx, keyEncryptAlgoId, keyEncryptAlgoIdSz); + XMEMCPY(recip->recip + idx, keyEncryptAlgoId, keyEncryptAlgoIdSz); idx += keyEncryptAlgoIdSz; - XMEMCPY(out + idx, keyWrapAlg, keyWrapAlgSz); + XMEMCPY(recip->recip + idx, keyWrapAlg, keyWrapAlgSz); idx += keyWrapAlgSz; - XMEMCPY(out + idx, recipEncKeysSeq, recipEncKeysSeqSz); + XMEMCPY(recip->recip + idx, recipEncKeysSeq, recipEncKeysSeqSz); idx += recipEncKeysSeqSz; - XMEMCPY(out + idx, recipEncKeySeq, recipEncKeySeqSz); + XMEMCPY(recip->recip + idx, recipEncKeySeq, recipEncKeySeqSz); idx += recipEncKeySeqSz; - XMEMCPY(out + idx, recipKeyIdSeq, recipKeyIdSeqSz); + XMEMCPY(recip->recip + idx, recipKeyIdSeq, recipKeyIdSeqSz); idx += recipKeyIdSeqSz; - XMEMCPY(out + idx, subjKeyIdOctet, subjKeyIdOctetSz); + XMEMCPY(recip->recip + idx, subjKeyIdOctet, subjKeyIdOctetSz); idx += subjKeyIdOctetSz; /* subject key id */ - XMEMCPY(out + idx, kari->decoded->extSubjKeyId, KEYID_SIZE); + XMEMCPY(recip->recip + idx, kari->decoded->extSubjKeyId, KEYID_SIZE); idx += KEYID_SIZE; - XMEMCPY(out + idx, encryptedKeyOctet, encryptedKeyOctetSz); + XMEMCPY(recip->recip + idx, encryptedKeyOctet, encryptedKeyOctetSz); idx += encryptedKeyOctetSz; /* encrypted CEK */ - XMEMCPY(out + idx, contentKeyEnc, *keyEncSz); - idx += *keyEncSz; + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + /* store recipient size */ + recip->recipSz = idx; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } return idx; } @@ -3493,15 +3711,20 @@ static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert, #ifndef NO_RSA -/* create ASN.1 formatted RecipientInfo structure, returns sequence size */ -static int wc_CreateRecipientInfo(const byte* cert, word32 certSz, - int keyEncAlgo, int blockKeySz, - WC_RNG* rng, byte* contentKeyPlain, - byte* contentKeyEnc, int* keyEncSz, - byte* out, word32 outSz, void* heap) +/* Encode and add CMS EnvelopedData KTRI (KeyTransRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz) { + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + WC_RNG rng; word32 idx = 0; - int ret = 0, totalSz = 0; + word32 encryptedKeySz = 0; + + int ret = 0, blockKeySz; int verSz, issuerSz, snSz, keyEncAlgSz; int issuerSeqSz, recipSeqSz, issuerSerialSeqSz; int encKeyOctetStrSz; @@ -3513,41 +3736,95 @@ static int wc_CreateRecipientInfo(const byte* cert, word32 certSz, byte encKeyOctetStr[MAX_OCTET_STR_SZ]; #ifdef WOLFSSL_SMALL_STACK - byte *serial; - byte *keyAlgArray; - + byte* serial; + byte* keyAlgArray; + byte* encryptedKey; RsaKey* pubKey; DecodedCert* decoded; - serial = (byte*)XMALLOC(MAX_SN_SZ, heap, DYNAMIC_TYPE_TMP_BUFFER); - keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, heap, DYNAMIC_TYPE_TMP_BUFFER); - decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap, - DYNAMIC_TYPE_TMP_BUFFER); + serial = (byte*)XMALLOC(MAX_SN_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_TPM_BUFFER); + decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); - if (decoded == NULL || serial == NULL || keyAlgArray == NULL) { - if (serial) XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); - if (keyAlgArray) XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); - if (decoded) XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (decoded == NULL || serial == NULL || + encryptedKey == NULL || keyAlgArray == NULL) { + if (serial) + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (keyAlgArray) + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedKey) + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (decoded) + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } - #else byte serial[MAX_SN_SZ]; byte keyAlgArray[MAX_ALGO_SZ]; + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; RsaKey pubKey[1]; DecodedCert decoded[1]; #endif - InitDecodedCert(decoded, (byte*)cert, certSz, heap); + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + XMEMSET(encryptedKey, 0, encryptedKeySz); + + /* allocate recipient struct */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (recip == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + + /* get key size for content-encryption key based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* generate random content encryption key, if needed */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + InitDecodedCert(decoded, (byte*)cert, certSz, pkcs7->heap); ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0); if (ret < 0) { FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } @@ -3559,10 +3836,12 @@ static int wc_CreateRecipientInfo(const byte* cert, word32 certSz, WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length"); FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return -1; } issuerSz = decoded->issuerRawLen; @@ -3572,36 +3851,43 @@ static int wc_CreateRecipientInfo(const byte* cert, word32 certSz, WOLFSSL_MSG("DecodedCert missing serial number"); FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return -1; } - snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial, MAX_SN_SZ); + snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial, + MAX_SN_SZ); issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz, issuerSerialSeq); /* KeyEncryptionAlgorithmIdentifier, only support RSA now */ - if (keyEncAlgo != RSAk) { + if (pkcs7->publicKeyOID != RSAk) { FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ALGO_ID_E; } - keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, oidKeyType, 0); + keyEncAlgSz = SetAlgoID(pkcs7->publicKeyOID, keyAlgArray, oidKeyType, 0); if (keyEncAlgSz == 0) { FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return BAD_FUNC_ARG; } @@ -3609,107 +3895,152 @@ static int wc_CreateRecipientInfo(const byte* cert, word32 certSz, pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_TMP_BUFFER); if (pubKey == NULL) { FreeDecodedCert(decoded); - XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return MEMORY_E; } #endif /* EncryptedKey */ - ret = wc_InitRsaKey_ex(pubKey, heap, INVALID_DEVID); + ret = wc_InitRsaKey_ex(pubKey, pkcs7->heap, INVALID_DEVID); if (ret != 0) { FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } if (wc_RsaPublicKeyDecode(decoded->publicKey, &idx, pubKey, - decoded->pubKeySize) < 0) { + decoded->pubKeySize) < 0) { WOLFSSL_MSG("ASN RSA key decode error"); wc_FreeRsaKey(pubKey); FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return PUBLIC_KEY_E; } - *keyEncSz = wc_RsaPublicEncrypt(contentKeyPlain, blockKeySz, contentKeyEnc, - MAX_ENCRYPTED_KEY_SZ, pubKey, rng); + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + wc_FreeRsaKey(pubKey); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + + ret = wc_RsaPublicEncrypt(pkcs7->cek, pkcs7->cekSz, encryptedKey, + encryptedKeySz, pubKey, &rng); wc_FreeRsaKey(pubKey); + wc_FreeRng(&rng); #ifdef WOLFSSL_SMALL_STACK - XFREE(pubKey, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - if (*keyEncSz < 0) { + if (ret < 0) { WOLFSSL_MSG("RSA Public Encrypt failed"); FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return *keyEncSz; + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; } + encryptedKeySz = ret; - encKeyOctetStrSz = SetOctetString(*keyEncSz, encKeyOctetStr); + encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); /* RecipientInfo */ recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz + issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz + - *keyEncSz, recipSeq); + encryptedKeySz, recipSeq); if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz + - keyEncAlgSz + encKeyOctetStrSz + *keyEncSz > (int)outSz) { + keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) { WOLFSSL_MSG("RecipientInfo output buffer too small"); FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); 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; + idx = 0; + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + XMEMCPY(recip->recip + idx, ver, verSz); + idx += verSz; + XMEMCPY(recip->recip + idx, issuerSerialSeq, issuerSerialSeqSz); + idx += issuerSerialSeqSz; + XMEMCPY(recip->recip + idx, issuerSeq, issuerSeqSz); + idx += issuerSeqSz; + XMEMCPY(recip->recip + idx, decoded->issuerRaw, issuerSz); + idx += issuerSz; + XMEMCPY(recip->recip + idx, serial, snSz); + idx += snSz; + XMEMCPY(recip->recip + idx, keyAlgArray, keyEncAlgSz); + idx += keyEncAlgSz; + XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); + idx += encKeyOctetStrSz; + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return totalSz; + /* store recipient size */ + recip->recipSz = idx; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + return idx; } + #endif /* !NO_RSA */ @@ -3990,6 +4321,193 @@ int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, } +/* Encode and add CMS EnvelopedData KEKRI (KEKRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * pkcs7 - pointer to initialized PKCS7 structure + * keyWrapOID - OID sum of key wrap algorithm identifier + * kek - key encryption key + * kekSz - size of kek, bytes + * keyID - key-encryption key identifier, pre-distributed to endpoints + * keyIDSz - size of keyID, bytes + * timePtr - pointer to "time_t", which is typically "long" (OPTIONAL) + * otherOID - ASN.1 encoded OID of other attribute (OPTIONAL) + * otherOIDSz - size of otherOID, bytes (OPTIONAL) + * other - other attribute (OPTIONAL) + * otherSz - size of other (OPTIONAL) + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, + word32 kekSz, byte* keyId, word32 keyIdSz, + void* timePtr, byte* otherOID, + word32 otherOIDSz, byte* other, word32 otherSz) +{ + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + byte recipSeq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + byte kekIdSeq[MAX_SEQ_SZ]; + byte kekIdOctetStr[MAX_OCTET_STR_SZ]; + byte genTime[ASN_GENERALIZED_TIME_SIZE]; + byte otherAttSeq[MAX_SEQ_SZ]; + byte encAlgoId[MAX_ALGO_SZ]; + byte encKeyOctetStr[MAX_OCTET_STR_SZ]; +#ifdef WOLFSSL_SMALL_STACK + byte* encryptedKey; +#else + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; +#endif + + int blockKeySz = 0, ret = 0; + word32 idx = 0; + word32 totalSz = 0; + word32 recipSeqSz = 0, verSz = 0; + word32 kekIdSeqSz = 0, kekIdOctetStrSz = 0; + word32 otherAttSeqSz = 0, encAlgoIdSz = 0, encKeyOctetStrSz = 0; + word32 encryptedKeySz; + + int timeSz = 0; + time_t* tm = NULL; + + if (pkcs7 == NULL || kek == NULL || keyId == NULL) + return BAD_FUNC_ARG; + + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (recip == NULL) + return MEMORY_E; + + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + + /* get key size for content-encryption key based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockKeySz; + } + + /* generate random content encryption key, if needed */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* EncryptedKey */ +#ifdef WOLFSSL_SMALL_STACK + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedKey == NULL) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } +#endif + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + XMEMSET(encryptedKey, 0, encryptedKeySz); + + encryptedKeySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kek, kekSz, + encryptedKey, encryptedKeySz, keyWrapOID, + AES_ENCRYPTION); + if (encryptedKeySz <= 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return encryptedKeySz; + } + + encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); + totalSz += (encKeyOctetStrSz + encryptedKeySz); + + /* KeyEncryptionAlgorithmIdentifier */ + encAlgoIdSz = SetAlgoID(keyWrapOID, encAlgoId, oidKeyWrapType, 0); + totalSz += encAlgoIdSz; + + /* KEKIdentifier: keyIdentifier */ + kekIdOctetStrSz = SetOctetString(keyIdSz, kekIdOctetStr); + totalSz += (kekIdOctetStrSz + keyIdSz); + + /* KEKIdentifier: GeneralizedTime (OPTIONAL) */ + if (timePtr != NULL) { + tm = (time_t*)timePtr; + timeSz = GetAsnTimeString(tm, genTime, sizeof(genTime)); + if (timeSz < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return timeSz; + } + totalSz += timeSz; + } + + /* KEKIdentifier: OtherKeyAttribute SEQ (OPTIONAL) */ + if (other != NULL && otherSz > 0) { + otherAttSeqSz = SetSequence(otherOIDSz + otherSz, otherAttSeq); + totalSz += otherAttSeqSz + otherOIDSz + otherSz; + } + + /* KEKIdentifier SEQ */ + kekIdSeqSz = SetSequence(kekIdOctetStrSz + keyIdSz + timeSz + + otherAttSeqSz + otherOIDSz + otherSz, kekIdSeq); + totalSz += kekIdSeqSz; + + /* version */ + verSz = SetMyVersion(4, ver, 0); + totalSz += verSz; + + /* KEKRecipientInfo SEQ */ + recipSeqSz = SetImplicit(ASN_SEQUENCE, 2, totalSz, recipSeq); + totalSz += recipSeqSz; + + if (totalSz > MAX_RECIP_SZ) { + WOLFSSL_MSG("CMS Recipient output buffer too small"); + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + XMEMCPY(recip->recip + idx, ver, verSz); + idx += verSz; + XMEMCPY(recip->recip + idx, kekIdSeq, kekIdSeqSz); + idx += kekIdSeqSz; + XMEMCPY(recip->recip + idx, kekIdOctetStr, kekIdOctetStrSz); + idx += kekIdOctetStrSz; + XMEMCPY(recip->recip + idx, keyId, keyIdSz); + idx += keyIdSz; + if (timePtr != NULL) { + XMEMCPY(recip->recip + idx, genTime, timeSz); + idx += timeSz; + } + if (other != NULL && otherSz > 0) { + XMEMCPY(recip->recip + idx, otherAttSeq, otherAttSeqSz); + idx += otherAttSeqSz; + XMEMCPY(recip->recip + idx, otherOID, otherOIDSz); + idx += otherOIDSz; + XMEMCPY(recip->recip + idx, other, otherSz); + idx += otherSz; + } + XMEMCPY(recip->recip + idx, encAlgoId, encAlgoIdSz); + idx += encAlgoIdSz; + XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); + idx += encKeyOctetStrSz; + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; + + /* store recipient size */ + recip->recipSz = idx; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while(lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + return idx; +} + + /* build PKCS#7 envelopedData content type, return enveloped size */ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) { @@ -4006,22 +4524,12 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) byte ver[MAX_VERSION_SZ]; WC_RNG rng; - int contentKeyEncSz, blockSz, blockKeySz; - byte contentKeyPlain[MAX_CONTENT_KEY_LEN]; -#ifdef WOLFSSL_SMALL_STACK - byte* contentKeyEnc; -#else - byte contentKeyEnc[MAX_ENCRYPTED_KEY_SZ]; -#endif + int blockSz, blockKeySz; byte* plain; byte* encryptedContent; + Pkcs7EncodedRecip* tmpRecip = NULL; int recipSz, recipSetSz; -#ifdef WOLFSSL_SMALL_STACK - byte* recip; -#else - byte recip[MAX_RECIP_SZ]; -#endif byte recipSet[MAX_SET_SZ]; int encContentOctetSz, encContentSeqSz, contentTypeSz; @@ -4033,9 +4541,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) byte ivOctetString[MAX_OCTET_STR_SZ]; byte encContentOctet[MAX_OCTET_STR_SZ]; - if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || - pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL || - pkcs7->publicKeyOID == 0) + if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0) return BAD_FUNC_ARG; if (output == NULL || outputSz == 0) @@ -4067,95 +4573,69 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) verSz = SetMyVersion(0, ver, 0); } + /* generate random content encryption key */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret != 0) { + return ret; + } + + /* build RecipientInfo, only if user manually set singleCert and size */ + if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) { + switch (pkcs7->publicKeyOID) { + #ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert, + pkcs7->singleCertSz); + break; + #endif + #ifdef HAVE_ECC + case ECDSAk: + ret = wc_PKCS7_AddRecipient_KARI(pkcs7, pkcs7->singleCert, + pkcs7->singleCertSz, + pkcs7->keyWrapOID, + pkcs7->keyAgreeOID, pkcs7->ukm, + pkcs7->ukmSz); + break; + #endif + + default: + WOLFSSL_MSG("Unsupported RecipientInfo public key type"); + return BAD_FUNC_ARG; + }; + + if (ret < 0) { + WOLFSSL_MSG("Failed to create RecipientInfo"); + return ret; + } + } + + recipSz = wc_PKCS7_GetRecipientListSize(pkcs7); + if (recipSz < 0) { + return ret; + + } else if (recipSz == 0) { + WOLFSSL_MSG("You must add at least one CMS recipient"); + return PKCS7_RECIP_E; + } + recipSetSz = SetSet(recipSz, recipSet); + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); if (ret != 0) return ret; - ret = wc_RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz); - if (ret != 0) { - wc_FreeRng(&rng); - return ret; - } - -#ifdef WOLFSSL_SMALL_STACK - recip = (byte*)XMALLOC(MAX_RECIP_SZ, pkcs7->heap, - DYNAMIC_TYPE_PKCS7); - contentKeyEnc = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, - DYNAMIC_TYPE_PKCS7); - if (contentKeyEnc == NULL || recip == NULL) { - if (recip) XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - if (contentKeyEnc) XFREE(contentKeyEnc, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - wc_FreeRng(&rng); - return MEMORY_E; - } -#endif - contentKeyEncSz = MAX_ENCRYPTED_KEY_SZ; - - /* build RecipientInfo, only handle 1 for now */ - switch (pkcs7->publicKeyOID) { -#ifndef NO_RSA - case RSAk: - recipSz = wc_CreateRecipientInfo(pkcs7->singleCert, - pkcs7->singleCertSz, - pkcs7->publicKeyOID, - blockKeySz, &rng, contentKeyPlain, - contentKeyEnc, &contentKeyEncSz, recip, - MAX_RECIP_SZ, pkcs7->heap); - break; -#endif -#ifdef HAVE_ECC - case ECDSAk: - recipSz = wc_CreateKeyAgreeRecipientInfo(pkcs7, pkcs7->singleCert, - pkcs7->singleCertSz, - pkcs7->publicKeyOID, - blockKeySz, pkcs7->keyWrapOID, - pkcs7->keyAgreeOID, &rng, - contentKeyPlain, contentKeyEnc, - &contentKeyEncSz, recip, MAX_RECIP_SZ); - break; -#endif - - default: - WOLFSSL_MSG("Unsupported RecipientInfo public key type"); - return BAD_FUNC_ARG; - }; - - ForceZero(contentKeyEnc, MAX_ENCRYPTED_KEY_SZ); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(contentKeyEnc, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - - if (recipSz < 0) { - WOLFSSL_MSG("Failed to create RecipientInfo"); - wc_FreeRng(&rng); -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return recipSz; - } - recipSetSz = SetSet(recipSz, recipSet); - /* generate IV for block cipher */ ret = wc_PKCS7_GenerateIV(pkcs7, &rng, tmpIv, blockSz); wc_FreeRng(&rng); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif + if (ret != 0) return ret; - } /* EncryptedContentInfo */ ret = wc_SetContentType(pkcs7->contentOID, contentType, sizeof(contentType)); - if (ret < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif + if (ret < 0) return ret; - } + contentTypeSz = ret; /* allocate encrypted content buffer and PKCS#7 padding */ @@ -4165,8 +4645,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) encryptedOutSz = pkcs7->contentSz + padSz; - plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, - DYNAMIC_TYPE_PKCS7); + plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (plain == NULL) return MEMORY_E; @@ -4181,9 +4660,6 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) DYNAMIC_TYPE_PKCS7); if (encryptedContent == NULL) { XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif return MEMORY_E; } @@ -4198,23 +4674,17 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (contentEncAlgoSz == 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif return BAD_FUNC_ARG; } /* encrypt content */ - ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, contentKeyPlain, - blockKeySz, tmpIv, blockSz, plain, encryptedOutSz, + ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek, + pkcs7->cekSz, tmpIv, blockSz, plain, encryptedOutSz, encryptedContent); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif return ret; } @@ -4248,9 +4718,6 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) WOLFSSL_MSG("Pkcs7_encrypt output buffer too small"); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif return BUFFER_E; } @@ -4266,8 +4733,14 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) idx += verSz; XMEMCPY(output + idx, recipSet, recipSetSz); idx += recipSetSz; - XMEMCPY(output + idx, recip, recipSz); - idx += recipSz; + /* copy in recipients from list */ + tmpRecip = pkcs7->recipList; + while (tmpRecip != NULL) { + XMEMCPY(output + idx, tmpRecip->recip, tmpRecip->recipSz); + idx += tmpRecip->recipSz; + tmpRecip = tmpRecip->next; + } + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); XMEMCPY(output + idx, encContentSeq, encContentSeqSz); idx += encContentSeqSz; XMEMCPY(output + idx, contentType, contentTypeSz); @@ -4283,21 +4756,15 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) XMEMCPY(output + idx, encryptedContent, encryptedOutSz); idx += encryptedOutSz; - ForceZero(contentKeyPlain, MAX_CONTENT_KEY_LEN); - XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#ifdef WOLFSSL_SMALL_STACK - XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return idx; } #ifndef NO_RSA /* decode KeyTransRecipientInfo (ktri), return 0 on success, <0 on error */ -static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, +static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { @@ -4799,9 +5266,87 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, #endif /* HAVE_ECC */ +/* decode ASN.1 KEKRecipientInfo (kekri), return 0 on success, + * < 0 on error */ +static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + int length, keySz, dateLen; + byte* keyId = NULL; + const byte* datePtr = NULL; + byte dateFormat; + word32 keyIdSz, kekIdSz, keyWrapOID; + + /* remove KEKIdentifier */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + kekIdSz = length; + + if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* save keyIdentifier and length */ + keyId = pkiMsg; + keyIdSz = length; + *idx += keyIdSz; + + /* may have OPTIONAL GeneralizedTime */ + if ((*idx < kekIdSz) && (pkiMsg[*idx] == ASN_GENERALIZED_TIME)) { + if (wc_GetDateInfo(pkiMsg + *idx, pkiMsgSz, &datePtr, &dateFormat, + &dateLen) != 0) { + return ASN_PARSE_E; + } + *idx += (dateLen + 1); + } + + /* may have OPTIONAL OtherKeyAttribute */ + if ((*idx < kekIdSz) && (pkiMsg[*idx] == + (ASN_SEQUENCE | ASN_CONSTRUCTED))) { + + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* skip it */ + *idx += length; + } + + /* get KeyEncryptionAlgorithmIdentifier */ + if (GetAlgoId(pkiMsg, idx, &keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get EncryptedKey */ + if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* decrypt CEK with KEK */ + keySz = wc_PKCS7_KeyWrap(pkiMsg + *idx, length, pkcs7->privateKey, + pkcs7->privateKeySz, decryptedKey, *decryptedKeySz, + keyWrapOID, AES_DECRYPTION); + if (keySz <= 0) + return keySz; + + *decryptedKeySz = (word32)keySz; + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + *idx += length; + + (void)keyId; + return 0; +} + + /* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success, * < 0 on error */ -static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, +static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { @@ -4934,9 +5479,9 @@ static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, } /* decrypt CEK with KEK */ - keySz = wc_PKCS7_KariKeyWrap(encryptedKey, encryptedKeySz, kari->kek, - kari->kekSz, decryptedKey, *decryptedKeySz, - keyWrapOID, direction); + keySz = wc_PKCS7_KeyWrap(encryptedKey, encryptedKeySz, kari->kek, + kari->kekSz, decryptedKey, *decryptedKeySz, + keyWrapOID, direction); if (keySz <= 0) { wc_PKCS7_KariFree(kari); #ifdef WOLFSSL_SMALL_STACK @@ -4967,7 +5512,7 @@ static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, /* decode ASN.1 RecipientInfos SET, return 0 on success, < 0 on error */ -static int wc_PKCS7_DecodeRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, +static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { @@ -5000,7 +5545,7 @@ static int wc_PKCS7_DecodeRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, #ifndef NO_RSA /* found ktri */ - ret = wc_PKCS7_DecodeKtri(pkcs7, pkiMsg, pkiMsgSz, idx, + ret = wc_PKCS7_DecryptKtri(pkcs7, pkiMsg, pkiMsgSz, idx, decryptedKey, decryptedKeySz, recipFound); if (ret != 0) @@ -5013,6 +5558,7 @@ static int wc_PKCS7_DecodeRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, /* kari is IMPLICIT[1] */ *idx = savedIdx; if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + (*idx)++; if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -5027,13 +5573,36 @@ static int wc_PKCS7_DecodeRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, return ASN_VERSION_E; /* found kari */ - ret = wc_PKCS7_DecodeKari(pkcs7, pkiMsg, pkiMsgSz, idx, + ret = wc_PKCS7_DecryptKari(pkcs7, pkiMsg, pkiMsgSz, idx, decryptedKey, decryptedKeySz, recipFound); if (ret != 0) return ret; - } - else { + + /* kekri is IMPLICIT[2] */ + } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | + ASN_CONTEXT_SPECIFIC | 2)) { + (*idx)++; + + if (GetLength(pkiMsg, idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { + *idx = savedIdx; + break; + } + + if (version != 4) + return ASN_VERSION_E; + + /* found kekri */ + ret = wc_PKCS7_DecryptKekri(pkcs7, pkiMsg, pkiMsgSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + + } else { /* failed to find RecipientInfo, restore idx and continue */ *idx = savedIdx; break; @@ -5048,13 +5617,108 @@ static int wc_PKCS7_DecodeRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, } +/* Parse encoded EnvelopedData bundle up to RecipientInfo set. + * + * return size of RecipientInfo SET on success, negative upon error */ +static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* pkiMsg, + word32 pkiMsgSz, word32* idx) +{ + int version, length; + word32 contentType; + + if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || idx == NULL) + return BAD_FUNC_ARG; + + /* read past ContentInfo, verify type is envelopedData */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (length == 0 && pkiMsg[(*idx)-1] == 0x80) { +#ifdef ASN_BER_TO_DER + word32 len = 0; + + ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); + if (ret != LENGTH_ONLY_E) + return ret; + pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->der == NULL) + return MEMORY_E; + ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); + if (ret < 0) + return ret; + + pkiMsg = pkcs7->der; + pkiMsgSz = len; + *idx = 0; + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; +#else + return BER_INDEF_E; +#endif + } + + if (wc_GetContentType(pkiMsg, idx, &contentType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (contentType != ENVELOPED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData"); + return PKCS7_OID_E; + } + + if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* remove EnvelopedData and version */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* TODO :: make this more accurate */ + if ((pkcs7->publicKeyOID == RSAk && version != 0) + #ifdef HAVE_ECC + || (pkcs7->publicKeyOID == ECDSAk && version != 2) + #endif + ) { + WOLFSSL_MSG("PKCS#7 envelopedData needs to be of version 0"); + return ASN_VERSION_E; + } + + /* remove RecipientInfo set, get length of set */ + if (GetSet(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + return length; +} + + +/* Import secret/private key into a PKCS7 structure. Used for setting + * the secret key for decryption a EnvelopedData KEKRI RecipientInfo. + * + * Returns 0 on success, negative upon error */ +WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz) +{ + if (pkcs7 == NULL || key == NULL || keySz == 0) + return BAD_FUNC_ARG; + + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + + return 0; +} + + /* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz) { int recipFound = 0; - int ret, version, length; + int ret, length; word32 idx = 0; word32 contentType, encOID; word32 decryptedKeySz; @@ -5072,76 +5736,16 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, byte* encryptedContent = NULL; int explicitOctet; - if (pkcs7 == NULL || pkcs7->singleCert == NULL || - pkcs7->singleCertSz == 0) + if (pkcs7 == NULL) return BAD_FUNC_ARG; if (pkiMsg == NULL || pkiMsgSz == 0 || output == NULL || outputSz == 0) return BAD_FUNC_ARG; - /* read past ContentInfo, verify type is envelopedData */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (length == 0 && pkiMsg[idx-1] == 0x80) { -#ifdef ASN_BER_TO_DER - word32 len = 0; - - ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); - if (ret != LENGTH_ONLY_E) - return ret; - pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - if (pkcs7->der == NULL) - return MEMORY_E; - ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); - if (ret < 0) - return ret; - - pkiMsg = pkcs7->der; - pkiMsgSz = len; - idx = 0; - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; -#else - return BER_INDEF_E; -#endif - } - - if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (contentType != ENVELOPED_DATA) { - WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData"); - return PKCS7_OID_E; - } - - if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) - return ASN_PARSE_E; - - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* remove EnvelopedData and version */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* TODO :: make this more accurate */ - if ((pkcs7->publicKeyOID == RSAk && version != 0) - #ifdef HAVE_ECC - || (pkcs7->publicKeyOID == ECDSAk && version != 2) - #endif - ) { - WOLFSSL_MSG("PKCS#7 envelopedData needs to be of version 0"); - return ASN_VERSION_E; - } - - /* walk through RecipientInfo set, find correct recipient */ - if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; + length = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, &idx); + if (length < 0) + return length; #ifdef WOLFSSL_SMALL_STACK decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, @@ -5151,7 +5755,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, #endif decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; - ret = wc_PKCS7_DecodeRecipientInfos(pkcs7, pkiMsg, pkiMsgSz, &idx, + ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, pkiMsg, pkiMsgSz, &idx, decryptedKey, &decryptedKeySz, &recipFound); if (ret != 0) { diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 4688442b7..b494c945b 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -18942,6 +18942,18 @@ typedef struct { word32 privateKeySz; byte* optionalUkm; word32 optionalUkmSz; + + /* KEKRI specific */ + byte* secretKey; /* key, only for kekri RecipientInfo types */ + word32 secretKeySz; /* size of secretKey, bytes */ + byte* secretKeyId; /* key identifier */ + word32 secretKeyIdSz; /* size of key identifier, bytes */ + void* timePtr; /* time_t pointer */ + byte* otherAttrOID; /* OPTIONAL, other attribute OID */ + word32 otherAttrOIDSz; /* size of otherAttrOID, bytes */ + byte* otherAttr; /* OPTIONAL, other attribute, ASN.1 encoded */ + word32 otherAttrSz; /* size of otherAttr, bytes */ + const char* outFileName; } pkcs7EnvelopedVector; @@ -18973,27 +18985,44 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, }; #endif /* NO_AES */ +#if !defined(NO_AES) && !defined(NO_SHA) && defined(WOLFSSL_AES_128) + /* encryption key for kekri recipient types */ + byte secretKey[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + }; + + /* encryption key identifier */ + byte secretKeyId[] = { + 0x02,0x02,0x03,0x04 + }; +#endif + const pkcs7EnvelopedVector testVectors[] = { /* key transport key encryption technique */ #ifndef NO_RSA #ifndef NO_DES3 {data, (word32)sizeof(data), DATA, DES3b, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataDES3.der"}, + rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, + NULL, 0, "pkcs7envelopedDataDES3.der"}, #endif #ifndef NO_AES #ifdef WOLFSSL_AES_128 {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataAES128CBC.der"}, + rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, + NULL, 0, "pkcs7envelopedDataAES128CBC.der"}, #endif #ifdef WOLFSSL_AES_192 {data, (word32)sizeof(data), DATA, AES192CBCb, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataAES192CBC.der"}, + rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, + NULL, 0, "pkcs7envelopedDataAES192CBC.der"}, #endif #ifdef WOLFSSL_AES_256 {data, (word32)sizeof(data), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, "pkcs7envelopedDataAES256CBC.der"}, + rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, + NULL, 0, "pkcs7envelopedDataAES256CBC.der"}, #endif #endif /* NO_AES */ #endif @@ -19004,31 +19033,42 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, dhSinglePass_stdDH_sha1kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, NULL, 0, + eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, "pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der"}, #endif #if !defined(NO_SHA256) && defined(WOLFSSL_AES_256) {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, NULL, 0, + eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der"}, #endif /* NO_SHA256 && WOLFSSL_AES_256 */ #if defined(WOLFSSL_SHA512) && defined(WOLFSSL_AES_256) {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, NULL, 0, + eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der"}, /* with optional user keying material (ukm) */ {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, optionalUkm, sizeof(optionalUkm), + eccPrivKeySz, optionalUkm, sizeof(optionalUkm), NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der"}, #endif /* WOLFSSL_SHA512 && WOLFSSL_AES_256 */ #endif /* NO_AES */ #endif + + /* kekri (KEKRecipientInfo) recipient types */ +#ifndef NO_AES + #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) + {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, 0, + NULL, 0, NULL, 0, NULL, 0, secretKey, sizeof(secretKey), + secretKeyId, sizeof(secretKeyId), NULL, NULL, 0, NULL, 0, + "pkcs7envelopedDataAES128CBC_KEKRI.der"}, + #endif +#endif }; testSz = sizeof(testVectors) / sizeof(pkcs7EnvelopedVector); @@ -19044,23 +19084,61 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (pkcs7 == NULL) return -9214; - ret = wc_PKCS7_InitWithCert(pkcs7, testVectors[i].cert, - (word32)testVectors[i].certSz); - if (ret != 0) { - wc_PKCS7_Free(pkcs7); - return -9215; - } + if (testVectors[i].secretKey != NULL) { + /* KEKRI recipient type */ - pkcs7->content = (byte*)testVectors[i].content; - pkcs7->contentSz = testVectors[i].contentSz; - pkcs7->contentOID = testVectors[i].contentOID; - pkcs7->encryptOID = testVectors[i].encryptOID; - pkcs7->keyWrapOID = testVectors[i].keyWrapOID; - pkcs7->keyAgreeOID = testVectors[i].keyAgreeOID; - pkcs7->privateKey = testVectors[i].privateKey; - pkcs7->privateKeySz = testVectors[i].privateKeySz; - pkcs7->ukm = testVectors[i].optionalUkm; - pkcs7->ukmSz = testVectors[i].optionalUkmSz; + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -9215; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + + ret = wc_PKCS7_AddRecipient_KEKRI(pkcs7, testVectors[i].keyWrapOID, + testVectors[i].secretKey, testVectors[i].secretKeySz, + testVectors[i].secretKeyId, testVectors[i].secretKeyIdSz, + testVectors[i].timePtr, testVectors[i].otherAttrOID, + testVectors[i].otherAttrOIDSz, testVectors[i].otherAttr, + testVectors[i].otherAttrSz); + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -9216; + } + + /* set key, for decryption */ + ret = wc_PKCS7_SetKey(pkcs7, testVectors[i].secretKey, + testVectors[i].secretKeySz); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -9217; + } + + } else { + /* KTRI or KARI recipient types */ + + ret = wc_PKCS7_InitWithCert(pkcs7, testVectors[i].cert, + (word32)testVectors[i].certSz); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -9218; + } + + pkcs7->keyWrapOID = testVectors[i].keyWrapOID; + pkcs7->keyAgreeOID = testVectors[i].keyAgreeOID; + pkcs7->privateKey = testVectors[i].privateKey; + pkcs7->privateKeySz = testVectors[i].privateKeySz; + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + } /* encode envelopedData */ envelopedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, enveloped, @@ -19068,36 +19146,39 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (envelopedSz <= 0) { printf("DEBUG: i = %d, envelopedSz = %d\n", i, envelopedSz); wc_PKCS7_Free(pkcs7); - return -9216; + return -9219; } /* decode envelopedData */ + printf("CHRIS: Trying to decode: %s\n", testVectors[i].outFileName); decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, enveloped, envelopedSz, decoded, sizeof(decoded)); if (decodedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9217; + return -9220; } /* test decode result */ if (XMEMCMP(decoded, data, sizeof(data)) != 0){ wc_PKCS7_Free(pkcs7); - return -9218; + return -9221; } + (void)decoded; + (void)decodedSz; #ifdef PKCS7_OUTPUT_TEST_BUNDLES /* output pkcs7 envelopedData for external testing */ pkcs7File = fopen(testVectors[i].outFileName, "wb"); if (!pkcs7File) { wc_PKCS7_Free(pkcs7); - return -9219; + return -9222; } ret = (int)fwrite(enveloped, 1, envelopedSz, pkcs7File); fclose(pkcs7File); if (ret != envelopedSz) { wc_PKCS7_Free(pkcs7); - return -9220; + return -9223; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ @@ -19110,6 +19191,8 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, (void)eccCertSz; (void)eccPrivKey; (void)eccPrivKeySz; + (void)secretKey; + (void)secretKeyId; #endif #ifdef NO_RSA (void)rsaCert; @@ -19117,7 +19200,6 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, (void)rsaPrivKey; (void)rsaPrivKeySz; #endif - return 0; } diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index a026d8787..17f6239e1 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -992,7 +992,7 @@ typedef struct tm wolfssl_tm; WOLFSSL_LOCAL int GetTimeString(byte* date, int format, char* buf, int len); #endif #if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7) -WOLFSSL_LOCAL int GetAsnTimeString(byte* buf, word32 len); +WOLFSSL_LOCAL int GetAsnTimeString(void* currTime, byte* buf, word32 len); #endif WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format, wolfssl_tm* certTime, int* idx); diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index b07ea087a..daf36cd8c 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -48,7 +48,7 @@ /* Max number of certificates that PKCS7 structure can parse */ #ifndef MAX_PKCS7_CERTS -#define MAX_PKCS7_CERTS 4 + #define MAX_PKCS7_CERTS 4 #endif /* PKCS#7 content types, ref RFC 2315 (Section 14) */ @@ -86,6 +86,15 @@ enum Pkcs7_SignerIdentifier_Types { SID_SUBJECT_KEY_IDENTIFIER = 1 }; +/* CMS/PKCS#7 RecipientInfo types, RFC 5652, Section 6.2 */ +enum Pkcs7_RecipientInfo_Types { + PKCS7_KTRI = 0, + PKCS7_KARI = 1, + PKCS7_KEKRI = 2, + PKCS7_PWRI = 3, + PKCS7_ORI = 4 +}; + typedef struct PKCS7Attrib { const byte* oid; word32 oidSz; @@ -103,6 +112,7 @@ typedef struct PKCS7DecodedAttrib { } PKCS7DecodedAttrib; typedef struct Pkcs7Cert Pkcs7Cert; +typedef struct Pkcs7EncodedRecip Pkcs7EncodedRecip; /* Public Structure Warning: * Existing members must not be changed to maintain backwards compatibility! @@ -164,6 +174,9 @@ typedef struct PKCS7 { SID_ISSUER_AND_SERIAL_NUMBER */ byte issuerSubjKeyId[KEYID_SIZE]; /* SubjectKeyIdentifier of singleCert */ Pkcs7Cert* certList; /* certificates list for SignedData set */ + Pkcs7EncodedRecip* recipList; /* recipients list */ + byte* cek; /* content encryption key, random, dynamic */ + word32 cekSz; /* size of cek, bytes */ /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ } PKCS7; @@ -177,8 +190,19 @@ WOLFSSL_API void wc_PKCS7_Free(PKCS7* pkcs7); WOLFSSL_API int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid, word32 oidSz, byte* out, word32* outSz); + +WOLFSSL_API int wc_PKCS7_SetSignerIdentifierType(PKCS7* pkcs7, int type); +WOLFSSL_API int wc_PKCS7_SetContentType(PKCS7* pkcs7, byte* contentType, + word32 sz); +WOLFSSL_API int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz); +WOLFSSL_API int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, + word32 blockSz); + +/* CMS/PKCS#7 Data */ WOLFSSL_API int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz); + +/* CMS/PKCS#7 SignedData */ WOLFSSL_API int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz); WOLFSSL_API int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf, @@ -190,19 +214,28 @@ WOLFSSL_API int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, WOLFSSL_API int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf, word32 hashSz, byte* pkiMsgHead, word32 pkiMsgHeadSz, byte* pkiMsgFoot, word32 pkiMsgFootSz); + +/* CMS/PKCS#7 EnvelopedData */ +WOLFSSL_API int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, + word32 certSz); +WOLFSSL_API int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, + word32 certSz, int keyWrapOID, + int keyAgreeOID, byte* ukm, + word32 ukmSz); +WOLFSSL_API int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, + byte* kek, word32 kekSz, + byte* keyID, word32 keyIdSz, + void* timePtr, byte* otherOID, + word32 otherOIDSz, byte* other, + word32 otherSz); WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz); +WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz); WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz); -WOLFSSL_API int wc_PKCS7_SetSignerIdentifierType(PKCS7* pkcs7, int type); -WOLFSSL_API int wc_PKCS7_SetContentType(PKCS7* pkcs7, byte* contentType, - word32 sz); -WOLFSSL_API int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz); -WOLFSSL_API int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, - word32 blockSz); - +/* CMS/PKCS#7 EncryptedData */ #ifndef NO_PKCS7_ENCRYPTED_DATA WOLFSSL_API int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz); @@ -211,6 +244,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 outputSz); #endif /* NO_PKCS7_ENCRYPTED_DATA */ +/* CMS/PKCS#7 CompressedData */ #ifdef HAVE_LIBZ WOLFSSL_API int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz); From 13b30a6a21eee13b7c5399997e1d0dc332432c36 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 14 Sep 2018 15:41:48 -0600 Subject: [PATCH 14/56] add CMS EnvelopedData PasswordRecipientInfo support --- .gitignore | 1 + Makefile.am | 1 + wolfcrypt/src/asn.c | 10 + wolfcrypt/src/pkcs7.c | 740 ++++++++++++++++++++++++++++++++++++-- wolfcrypt/test/test.c | 96 ++++- wolfssl/wolfcrypt/asn.h | 14 +- wolfssl/wolfcrypt/pkcs7.h | 10 +- 7 files changed, 823 insertions(+), 49 deletions(-) diff --git a/.gitignore b/.gitignore index 07184013c..8608049b7 100644 --- a/.gitignore +++ b/.gitignore @@ -116,6 +116,7 @@ pkcs7signedData_ECDSA_SHA512.der pkcs7envelopedDataDES3.der pkcs7envelopedDataAES128CBC.der pkcs7envelopedDataAES128CBC_KEKRI.der +pkcs7envelopedDataAES128CBC_PWRI.der pkcs7envelopedDataAES192CBC.der pkcs7envelopedDataAES256CBC.der diff diff --git a/Makefile.am b/Makefile.am index c91d70032..2b7864979 100644 --- a/Makefile.am +++ b/Makefile.am @@ -57,6 +57,7 @@ CLEANFILES+= cert.der \ pkcs7envelopedDataDES3.der \ pkcs7envelopedDataAES128CBC.der \ pkcs7envelopedDataAES128CBC_KEKRI.der \ + pkcs7envelopedDataAES128CBC_PWRI.der \ pkcs7envelopedDataAES192CBC.der \ pkcs7envelopedDataAES256CBC.der \ pkcs7signedData_RSA_SHA.der \ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index e6f5323ad..1ab2059d3 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1242,6 +1242,10 @@ static word32 SetBitString16Bit(word16 val, byte* output) #ifdef WOLFSSL_AES_256 static const byte wrapAes256Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 45}; #endif +#ifdef HAVE_PKCS7 +/* From RFC 3211 */ +static const byte wrapPwriKekOid[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3,9}; +#endif /* cmsKeyAgreeType */ #ifndef NO_SHA @@ -1741,6 +1745,12 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) *oidSz = sizeof(wrapAes256Oid); break; #endif + #ifdef HAVE_PKCS7 + case PWRI_KEK_WRAP: + oid = wrapPwriKekOid; + *oidSz = sizeof(wrapPwriKekOid); + break; + #endif } break; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 932834a23..1836e4ede 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -41,6 +41,9 @@ #ifdef HAVE_LIBZ #include #endif +#ifndef NO_PWDBASED + #include +#endif #ifdef NO_INLINE #include #else @@ -89,6 +92,13 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) 0x01, 0x09, 0x10, 0x01, 0x09 }; #endif +#ifndef NO_PWDBASED + const byte pwriKek[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x03, 0x09 }; + const byte pbkdf2[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x05, 0x0C }; +#endif + int idSz, idx = 0; word32 typeSz = 0; const byte* typeName = 0; @@ -142,6 +152,18 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) typeName = firmwarePkgData; break; +#ifndef NO_PWDBASED + case PWRI_KEK_WRAP: + typeSz = sizeof(pwriKek); + typeName = pwriKek; + break; + + case PBKDF2_OID: + typeSz = sizeof(pbkdf2); + typeName = pbkdf2; + break; +#endif + default: WOLFSSL_MSG("Unknown PKCS#7 Type"); return 0; @@ -351,8 +373,6 @@ static int wc_PKCS7_GetRecipientListSize(PKCS7* pkcs7) tmp = pkcs7->recipList; while (tmp != NULL) { - printf("DEBUG: tmp = %p\n", tmp); - printf("DEBUG: tmp->recipSz = %d\n", tmp->recipSz); totalSz += tmp->recipSz; tmp = tmp->next; } @@ -2859,31 +2879,6 @@ static int PKCS7_GenerateContentEncryptionKey(PKCS7* pkcs7, word32 len) } -#ifdef HAVE_ECC - -/* KARI == KeyAgreeRecipientInfo (key agreement) */ -typedef struct WC_PKCS7_KARI { - DecodedCert* decoded; /* decoded recip cert */ - void* heap; /* user heap, points to PKCS7->heap */ - int devId; /* device ID for HW based private key */ - ecc_key* recipKey; /* recip key (pub | priv) */ - ecc_key* senderKey; /* sender key (pub | priv) */ - byte* senderKeyExport; /* sender ephemeral key DER */ - byte* kek; /* key encryption key */ - byte* ukm; /* OPTIONAL user keying material */ - byte* sharedInfo; /* ECC-CMS-SharedInfo ASN.1 encoded blob */ - word32 senderKeyExportSz; /* size of sender ephemeral key DER */ - word32 kekSz; /* size of key encryption key */ - word32 ukmSz; /* size of user keying material */ - word32 sharedInfoSz; /* size of ECC-CMS-SharedInfo encoded */ - byte ukmOwner; /* do we own ukm buffer? 1:yes, 0:no */ - byte direction; /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */ - byte decodedInit : 1; /* indicates decoded was initialized */ - byte recipKeyInit : 1; /* indicates recipKey was initialized */ - byte senderKeyInit : 1; /* indicates senderKey was initialized */ -} WC_PKCS7_KARI; - - /* wrap CEK (content encryption key) with KEK, 0 on success, < 0 on error */ static int wc_PKCS7_KeyWrap(byte* cek, word32 cekSz, byte* kek, word32 kekSz, byte* out, word32 outSz, @@ -2939,6 +2934,31 @@ static int wc_PKCS7_KeyWrap(byte* cek, word32 cekSz, byte* kek, } +#ifdef HAVE_ECC + +/* KARI == KeyAgreeRecipientInfo (key agreement) */ +typedef struct WC_PKCS7_KARI { + DecodedCert* decoded; /* decoded recip cert */ + void* heap; /* user heap, points to PKCS7->heap */ + int devId; /* device ID for HW based private key */ + ecc_key* recipKey; /* recip key (pub | priv) */ + ecc_key* senderKey; /* sender key (pub | priv) */ + byte* senderKeyExport; /* sender ephemeral key DER */ + byte* kek; /* key encryption key */ + byte* ukm; /* OPTIONAL user keying material */ + byte* sharedInfo; /* ECC-CMS-SharedInfo ASN.1 encoded blob */ + word32 senderKeyExportSz; /* size of sender ephemeral key DER */ + word32 kekSz; /* size of key encryption key */ + word32 ukmSz; /* size of user keying material */ + word32 sharedInfoSz; /* size of ECC-CMS-SharedInfo encoded */ + byte ukmOwner; /* do we own ukm buffer? 1:yes, 0:no */ + byte direction; /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */ + byte decodedInit : 1; /* indicates decoded was initialized */ + byte recipKeyInit : 1; /* indicates recipKey was initialized */ + byte senderKeyInit : 1; /* indicates senderKey was initialized */ +} WC_PKCS7_KARI; + + /* allocate and create new WC_PKCS7_KARI struct, * returns struct pointer on success, NULL on failure */ static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) @@ -4321,6 +4341,477 @@ int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, } +#ifndef NO_PWDBASED + + +static int wc_PKCS7_GenerateKEK_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, + byte* salt, word32 saltSz, int kdfOID, + int prfOID, int iterations, byte* out, + word32 outSz) +{ + int ret; + + if (pkcs7 == NULL || passwd == NULL || salt == NULL || out == NULL) + return BAD_FUNC_ARG; + + switch (kdfOID) { + + case PBKDF2_OID: + + ret = wc_PBKDF2(out, passwd, pLen, salt, saltSz, iterations, + outSz, prfOID); + if (ret != 0) { + return ret; + } + + break; + + default: + WOLFSSL_MSG("Unsupported KDF OID"); + return PKCS7_OID_E; + } + + return 0; +} + + +/* RFC3211 (Section 2.3.1) key wrap algorithm (id-alg-PWRI-KEK). + * + * Returns output size on success, negative upon error */ +static int wc_PKCS7_PwriKek_KeyWrap(PKCS7* pkcs7, const byte* kek, word32 kekSz, + const byte* cek, word32 cekSz, + byte* out, word32 *outSz, + const byte* iv, word32 ivSz, int algID) +{ + WC_RNG rng; + int blockSz, outLen, ret; + word32 padSz; + byte* lastBlock; + + if (kek == NULL || cek == NULL || iv == NULL || outSz == NULL) + return BAD_FUNC_ARG; + + /* get encryption algorithm block size */ + blockSz = wc_PKCS7_GetOIDBlockSize(algID); + if (blockSz < 0) + return blockSz; + + /* get pad bytes needed to block boundary */ + padSz = blockSz - ((4 + cekSz) % blockSz); + outLen = 4 + cekSz + padSz; + + /* must be at least two blocks long */ + if (outLen < 2 * blockSz) + padSz += blockSz; + + /* if user set out to NULL, give back required length */ + if (out == NULL) { + *outSz = outLen; + return LENGTH_ONLY_E; + } + + /* verify output buffer is large enough */ + if (*outSz < (word32)outLen) + return BUFFER_E; + + out[0] = cekSz; + out[1] = ~cek[0]; + out[2] = ~cek[1]; + out[3] = ~cek[2]; + XMEMCPY(out + 4, cek, cekSz); + + /* random padding of size padSz */ + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) + return ret; + + ret = wc_RNG_GenerateBlock(&rng, out + 4 + cekSz, padSz); + + if (ret == 0) { + /* encrypt, normal */ + ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, (byte*)iv, + ivSz, out, outLen, out); + } + + if (ret == 0) { + /* encrypt again, using last ciphertext block as IV */ + lastBlock = out + (((outLen / blockSz) - 1) * blockSz); + ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, lastBlock, + blockSz, out, outLen, out); + } + + if (ret == 0) { + *outSz = outLen; + } else { + outLen = ret; + } + + wc_FreeRng(&rng); + + return outLen; +} + + +/* RFC3211 (Section 2.3.2) key unwrap algorithm (id-alg-PWRI-KEK). + * + * Returns cek size on success, negative upon error */ +static int wc_PKCS7_PwriKek_KeyUnWrap(PKCS7* pkcs7, const byte* kek, + word32 kekSz, const byte* in, word32 inSz, + byte* out, word32 outSz, const byte* iv, + word32 ivSz, int algID) +{ + int blockSz, cekLen, ret; + byte* tmpIv = NULL; + byte* lastBlock = NULL; + byte* outTmp = NULL; + + if (pkcs7 == NULL || kek == NULL || in == NULL || + out == NULL || iv == NULL) { + return BAD_FUNC_ARG; + } + + outTmp = (byte*)XMALLOC(inSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (outTmp == NULL) + return MEMORY_E; + + /* get encryption algorithm block size */ + blockSz = wc_PKCS7_GetOIDBlockSize(algID); + if (blockSz < 0) { + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return blockSz; + } + + /* input needs to be blockSz multiple and at least 2 * blockSz */ + if (((inSz % blockSz) != 0) || (inSz < (2 * (word32)blockSz))) { + WOLFSSL_MSG("PWRI-KEK unwrap input must of block size and >= 2 " + "times block size"); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } + + /* use block out[n-1] as IV to decrypt block out[n] */ + lastBlock = (byte*)in + inSz - blockSz; + tmpIv = lastBlock - blockSz; + + /* decrypt last block */ + ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, tmpIv, blockSz, + lastBlock, blockSz, outTmp + inSz - blockSz); + + if (ret == 0) { + /* using last decrypted block as IV, decrypt [0 ... n-1] blocks */ + lastBlock = outTmp + inSz - blockSz; + ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, lastBlock, + blockSz, (byte*)in, inSz - blockSz, + outTmp); + } + + if (ret == 0) { + /* decrypt using original kek and iv */ + ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, (byte*)iv, + ivSz, outTmp, inSz, outTmp); + } + + if (ret != 0) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + cekLen = outTmp[0]; + + /* verify length */ + if ((word32)cekLen > inSz) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } + + /* verify check bytes */ + if ((outTmp[1] ^ outTmp[4]) != 0xFF || + (outTmp[2] ^ outTmp[5]) != 0xFF || + (outTmp[3] ^ outTmp[6]) != 0xFF) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } + + if (outSz < (word32)cekLen) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BUFFER_E; + } + + XMEMCPY(out, outTmp + 4, outTmp[0]); + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return cekLen; +} + + +/* Encode and add CMS EnvelopedData PWRI (PasswordRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Return 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, + byte* salt, word32 saltSz, int kdfOID, + int hashOID, int iterations, int encryptOID) +{ + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + /* PasswordRecipientInfo */ + byte recipSeq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + word32 recipSeqSz, verSz; + + /* KeyDerivationAlgorithmIdentifier */ + byte kdfAlgoIdSeq[MAX_SEQ_SZ]; + byte kdfAlgoId[MAX_OID_SZ]; + byte kdfParamsSeq[MAX_SEQ_SZ]; /* PBKDF2-params */ + byte kdfSaltOctetStr[MAX_OCTET_STR_SZ]; /* salt OCTET STRING */ + byte kdfIterations[MAX_VERSION_SZ]; + word32 kdfAlgoIdSeqSz, kdfAlgoIdSz; + word32 kdfParamsSeqSz, kdfSaltOctetStrSz, kdfIterationsSz; + /* OPTIONAL: keyLength, not supported yet */ + /* OPTIONAL: prf AlgorithIdentifier, not supported yet */ + + /* KeyEncryptionAlgorithmIdentifier */ + byte keyEncAlgoIdSeq[MAX_SEQ_SZ]; + byte keyEncAlgoId[MAX_OID_SZ]; /* id-alg-PWRI-KEK */ + byte pwriEncAlgoId[MAX_ALGO_SZ]; + byte ivOctetString[MAX_OCTET_STR_SZ]; + word32 keyEncAlgoIdSeqSz, keyEncAlgoIdSz; + word32 pwriEncAlgoIdSz, ivOctetStringSz; + + /* EncryptedKey */ + byte encKeyOctetStr[MAX_OCTET_STR_SZ]; + word32 encKeyOctetStrSz; + + byte tmpIv[MAX_CONTENT_IV_SIZE]; + byte* encryptedKey = NULL; + byte* kek = NULL; + + int blockKeySz = 0, ret = 0; + word32 idx, totalSz = 0, encryptedKeySz; + + if (pkcs7 == NULL || passwd == NULL || pLen == 0 || + salt == NULL || saltSz == 0) { + return BAD_FUNC_ARG; + } + + /* get content-encryption key size, based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(encryptOID); + if (blockKeySz < 0) + return blockKeySz; + + /* generate random CEK */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) + return ret; + + /* generate random IV */ + ret = wc_PKCS7_GenerateIV(pkcs7, NULL, tmpIv, blockKeySz); + if (ret != 0) + return ret; + + /* allocate memory for RecipientInfo, KEK, encrypted key */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (recip == NULL) + return MEMORY_E; + + kek = (byte*)XMALLOC(blockKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (kek == NULL) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (encryptedKey == NULL) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + XMEMSET(kek, 0, blockKeySz); + XMEMSET(encryptedKey, 0, encryptedKeySz); + + /* generate KEK: expand password into KEK */ + ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, passwd, pLen, salt, saltSz, + kdfOID, hashOID, iterations, kek, + blockKeySz); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* generate encrypted key: encrypt CEK with KEK */ + ret = wc_PKCS7_PwriKek_KeyWrap(pkcs7, kek, blockKeySz, pkcs7->cek, + pkcs7->cekSz, encryptedKey, &encryptedKeySz, + tmpIv, blockKeySz, pkcs7->encryptOID); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + encryptedKeySz = ret; + + /* put together encrypted key OCTET STRING */ + encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); + totalSz += (encKeyOctetStrSz + encryptedKeySz); + + /* put together IV OCTET STRING */ + ivOctetStringSz = SetOctetString(blockKeySz, ivOctetString); + totalSz += (ivOctetStringSz + blockKeySz); + + /* set PWRIAlgorithms AlgorithmIdentifier, adding (ivOctetStringSz + + blockKeySz) for IV OCTET STRING */ + pwriEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, pwriEncAlgoId, + oidBlkType, ivOctetStringSz + blockKeySz); + totalSz += pwriEncAlgoIdSz; + + /* set KeyEncryptionAlgorithms OID */ + ret = wc_SetContentType(PWRI_KEK_WRAP, keyEncAlgoId, sizeof(keyEncAlgoId)); + if (ret <= 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + keyEncAlgoIdSz = ret; + totalSz += keyEncAlgoIdSz; + + /* KeyEncryptionAlgorithm SEQ */ + keyEncAlgoIdSeqSz = SetSequence(keyEncAlgoIdSz + pwriEncAlgoIdSz + + ivOctetStringSz + blockKeySz, + keyEncAlgoIdSeq); + totalSz += keyEncAlgoIdSeqSz; + + /* set KDF salt */ + kdfSaltOctetStrSz = SetOctetString(saltSz, kdfSaltOctetStr); + totalSz += (kdfSaltOctetStrSz + saltSz); + + /* set KDF iteration count */ + kdfIterationsSz = SetMyVersion(iterations, kdfIterations, 0); + totalSz += kdfIterationsSz; + + /* set KDF params SEQ */ + kdfParamsSeqSz = SetSequence(kdfSaltOctetStrSz + saltSz + kdfIterationsSz, + kdfParamsSeq); + totalSz += kdfParamsSeqSz; + + /* set KDF algo OID */ + ret = wc_SetContentType(kdfOID, kdfAlgoId, sizeof(kdfAlgoId)); + if (ret <= 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + kdfAlgoIdSz = ret; + totalSz += kdfAlgoIdSz; + + /* set KeyDerivationAlgorithmIdentifier EXPLICIT [0] SEQ */ + kdfAlgoIdSeqSz = SetExplicit(0, kdfAlgoIdSz + kdfParamsSeqSz + + kdfSaltOctetStrSz + saltSz + kdfIterationsSz, + kdfAlgoIdSeq); + totalSz += kdfAlgoIdSeqSz; + + /* set PasswordRecipientInfo CMSVersion, MUST be 0 */ + verSz = SetMyVersion(0, ver, 0); + totalSz += verSz; + + /* set PasswordRecipientInfo SEQ */ + recipSeqSz = SetImplicit(ASN_SEQUENCE, 3, totalSz, recipSeq); + totalSz += recipSeqSz; + + if (totalSz > MAX_RECIP_SZ) { + WOLFSSL_MSG("CMS Recipient output buffer too small"); + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + idx = 0; + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + XMEMCPY(recip->recip + idx, ver, verSz); + idx += verSz; + XMEMCPY(recip->recip + idx, kdfAlgoIdSeq, kdfAlgoIdSeqSz); + idx += kdfAlgoIdSeqSz; + XMEMCPY(recip->recip + idx, kdfAlgoId, kdfAlgoIdSz); + idx += kdfAlgoIdSz; + XMEMCPY(recip->recip + idx, kdfParamsSeq, kdfParamsSeqSz); + idx += kdfParamsSeqSz; + XMEMCPY(recip->recip + idx, kdfSaltOctetStr, kdfSaltOctetStrSz); + idx += kdfSaltOctetStrSz; + XMEMCPY(recip->recip + idx, salt, saltSz); + idx += saltSz; + XMEMCPY(recip->recip + idx, kdfIterations, kdfIterationsSz); + idx += kdfIterationsSz; + XMEMCPY(recip->recip + idx, keyEncAlgoIdSeq, keyEncAlgoIdSeqSz); + idx += keyEncAlgoIdSeqSz; + XMEMCPY(recip->recip + idx, keyEncAlgoId, keyEncAlgoIdSz); + idx += keyEncAlgoIdSz; + XMEMCPY(recip->recip + idx, pwriEncAlgoId, pwriEncAlgoIdSz); + idx += pwriEncAlgoIdSz; + XMEMCPY(recip->recip + idx, ivOctetString, ivOctetStringSz); + idx += ivOctetStringSz; + XMEMCPY(recip->recip + idx, tmpIv, blockKeySz); + idx += blockKeySz; + XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); + idx += encKeyOctetStrSz; + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; + + ForceZero(kek, blockKeySz); + ForceZero(encryptedKey, encryptedKeySz); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + /* store recipient size */ + recip->recipSz = idx; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + return idx; +} + +/* Import password and KDF settings into a PKCS7 structure. Used for setting + * the password info for decryption a EnvelopedData PWRI RecipientInfo. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen) +{ + if (pkcs7 == NULL || passwd == NULL || pLen == 0) + return BAD_FUNC_ARG; + + pkcs7->pass = passwd; + pkcs7->passSz = pLen; + + return 0; +} + +#endif /* NO_PWDBASED */ + + /* Encode and add CMS EnvelopedData KEKRI (KEKRecipientInfo) RecipientInfo * to CMS/PKCS#7 EnvelopedData structure. * @@ -4573,7 +5064,6 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) verSz = SetMyVersion(0, ver, 0); } - /* generate random content encryption key */ ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); if (ret != 0) { @@ -5266,6 +5756,177 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, #endif /* HAVE_ECC */ +/* decode ASN.1 PasswordRecipientInfo (pwri), return 0 on success, + * < 0 on error */ +static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + byte* salt; + byte* cek; + byte* kek; + + byte tmpIv[MAX_CONTENT_IV_SIZE]; + + int ret, length, saltSz, iterations, blockSz; + int hashOID = WC_SHA; /* default to SHA1 */ + word32 kdfAlgoId, pwriEncAlgoId, keyEncAlgoId, cekSz; + + /* remove KeyDerivationAlgorithmIdentifier */ + if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KeyDerivationAlgorithmIdentifier */ + if (wc_GetContentType(pkiMsg, idx, &kdfAlgoId, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KDF params SEQ */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KDF salt OCTET STRING */ + if ( (pkiMsgSz > ((*idx) + 1)) && + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &saltSz, pkiMsgSz) < 0) + return ASN_PARSE_E; + + salt = (byte*)XMALLOC(saltSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (salt == NULL) + return MEMORY_E; + + XMEMCPY(salt, pkiMsg + (*idx), saltSz); + *idx += saltSz; + + /* get KDF iterations */ + if (GetMyVersion(pkiMsg, idx, &iterations, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get KeyEncAlgoId SEQ */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get KeyEncAlgoId */ + if (wc_GetContentType(pkiMsg, idx, &keyEncAlgoId, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get pwriEncAlgoId */ + if (GetAlgoId(pkiMsg, idx, &pwriEncAlgoId, oidBlkType, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + blockSz = wc_PKCS7_GetOIDBlockSize(pwriEncAlgoId); + if (blockSz < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockSz; + } + + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ + if ( (pkiMsgSz > ((*idx) + 1)) && + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (length != blockSz) { + WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + XMEMCPY(tmpIv, pkiMsg + (*idx), length); + *idx += length; + + /* get EncryptedKey */ + if ( (pkiMsgSz < ((*idx) + 1)) || + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* allocate temporary space for decrypted key */ + cekSz = length; + cek = (byte*)XMALLOC(cekSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cek == NULL) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* generate KEK */ + kek = (byte*)XMALLOC(blockSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (kek == NULL) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, pkcs7->pass, pkcs7->passSz, + salt, saltSz, kdfAlgoId, hashOID, + iterations, kek, blockSz); + if (ret < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* decrypt CEK with KEK */ + ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, blockSz, pkiMsg + (*idx), + length, cek, cekSz, tmpIv, + blockSz, pwriEncAlgoId); + if (ret < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + cekSz = ret; + + if (*decryptedKeySz < cekSz) { + WOLFSSL_MSG("Decrypted key buffer too small for CEK"); + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + XMEMCPY(decryptedKey, cek, cekSz); + *decryptedKeySz = cekSz; + + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + *idx += length; + + return 0; +} + + /* decode ASN.1 KEKRecipientInfo (kekri), return 0 on success, * < 0 on error */ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, @@ -5602,6 +6263,29 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, if (ret != 0) return ret; + /* pwri is IMPLICIT[3] */ + } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | + ASN_CONTEXT_SPECIFIC | 3)) { + (*idx)++; + + if (GetLength(pkiMsg, idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { + *idx = savedIdx; + break; + } + + if (version != 0) + return ASN_VERSION_E; + + /* found pwri */ + ret = wc_PKCS7_DecryptPwri(pkcs7, pkiMsg, pkiMsgSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + } else { /* failed to find RecipientInfo, restore idx and continue */ *idx = savedIdx; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index b494c945b..3da92d000 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -18954,6 +18954,15 @@ typedef struct { byte* otherAttr; /* OPTIONAL, other attribute, ASN.1 encoded */ word32 otherAttrSz; /* size of otherAttr, bytes */ + /* PWRI specific */ + char* password; + word32 passwordSz; + byte* salt; + word32 saltSz; + int kdfOID; + int hashOID; + int kdfIterations; + const char* outFileName; } pkcs7EnvelopedVector; @@ -18998,6 +19007,14 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, }; #endif +#if !defined(NO_PWDBASED) + char password[] = "password"; + + byte salt[] = { + 0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12 + }; +#endif + const pkcs7EnvelopedVector testVectors[] = { /* key transport key encryption technique */ @@ -19005,24 +19022,24 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #ifndef NO_DES3 {data, (word32)sizeof(data), DATA, DES3b, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, "pkcs7envelopedDataDES3.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataDES3.der"}, #endif #ifndef NO_AES #ifdef WOLFSSL_AES_128 {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, "pkcs7envelopedDataAES128CBC.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES128CBC.der"}, #endif #ifdef WOLFSSL_AES_192 {data, (word32)sizeof(data), DATA, AES192CBCb, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, "pkcs7envelopedDataAES192CBC.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES192CBC.der"}, #endif #ifdef WOLFSSL_AES_256 {data, (word32)sizeof(data), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, "pkcs7envelopedDataAES256CBC.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC.der"}, #endif #endif /* NO_AES */ #endif @@ -19034,6 +19051,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, dhSinglePass_stdDH_sha1kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, + NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der"}, #endif @@ -19041,6 +19059,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, + NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der"}, #endif /* NO_SHA256 && WOLFSSL_AES_256 */ @@ -19048,13 +19067,14 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, + NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der"}, /* with optional user keying material (ukm) */ {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz, optionalUkm, sizeof(optionalUkm), NULL, 0, - NULL, 0, NULL, NULL, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der"}, #endif /* WOLFSSL_SHA512 && WOLFSSL_AES_256 */ #endif /* NO_AES */ @@ -19066,7 +19086,18 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, 0, NULL, 0, NULL, 0, NULL, 0, secretKey, sizeof(secretKey), secretKeyId, sizeof(secretKeyId), NULL, NULL, 0, NULL, 0, - "pkcs7envelopedDataAES128CBC_KEKRI.der"}, + NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES128CBC_KEKRI.der"}, + #endif +#endif + + /* pwri (PasswordRecipientInfo) recipient types */ +#if !defined(NO_PWDBASED) && !defined(NO_AES) + #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) + {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, + NULL, 0, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, password, (word32)XSTRLEN(password), + salt, sizeof(salt), PBKDF2_OID, WC_SHA, 5, + "pkcs7envelopedDataAES128CBC_PWRI.der"}, #endif #endif }; @@ -19105,6 +19136,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, testVectors[i].timePtr, testVectors[i].otherAttrOID, testVectors[i].otherAttrOIDSz, testVectors[i].otherAttr, testVectors[i].otherAttrSz); + if (ret < 0) { wc_PKCS7_Free(pkcs7); return -9216; @@ -19113,11 +19145,49 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, /* set key, for decryption */ ret = wc_PKCS7_SetKey(pkcs7, testVectors[i].secretKey, testVectors[i].secretKeySz); + if (ret != 0) { wc_PKCS7_Free(pkcs7); return -9217; } + } else if (testVectors[i].password != NULL) { + /* PWRI recipient type */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -9218; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + + ret = wc_PKCS7_AddRecipient_PWRI(pkcs7, + (byte*)testVectors[i].password, + testVectors[i].passwordSz, testVectors[i].salt, + testVectors[i].saltSz, testVectors[i].kdfOID, + testVectors[i].hashOID, testVectors[i].kdfIterations, + testVectors[i].encryptOID); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -9219; + } + + /* set password, for decryption */ + ret = wc_PKCS7_SetPassword(pkcs7, (byte*)testVectors[i].password, + testVectors[i].passwordSz); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -9220; + } + + } else { /* KTRI or KARI recipient types */ @@ -19125,7 +19195,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, (word32)testVectors[i].certSz); if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9218; + return -9221; } pkcs7->keyWrapOID = testVectors[i].keyWrapOID; @@ -19144,24 +19214,22 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, envelopedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, enveloped, sizeof(enveloped)); if (envelopedSz <= 0) { - printf("DEBUG: i = %d, envelopedSz = %d\n", i, envelopedSz); wc_PKCS7_Free(pkcs7); - return -9219; + return -9222; } /* decode envelopedData */ - printf("CHRIS: Trying to decode: %s\n", testVectors[i].outFileName); decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, enveloped, envelopedSz, decoded, sizeof(decoded)); if (decodedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9220; + return -9223; } /* test decode result */ if (XMEMCMP(decoded, data, sizeof(data)) != 0){ wc_PKCS7_Free(pkcs7); - return -9221; + return -9224; } (void)decoded; (void)decodedSz; @@ -19171,14 +19239,14 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7File = fopen(testVectors[i].outFileName, "wb"); if (!pkcs7File) { wc_PKCS7_Free(pkcs7); - return -9222; + return -9225; } ret = (int)fwrite(enveloped, 1, envelopedSz, pkcs7File); fclose(pkcs7File); if (ret != envelopedSz) { wc_PKCS7_Free(pkcs7); - return -9223; + return -9226; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 17f6239e1..20c986dcf 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -377,19 +377,22 @@ enum Key_Sum { }; -#ifndef NO_AES +#if !defined(NO_AES) || defined(HAVE_PKCS7) enum KeyWrap_Sum { #ifdef WOLFSSL_AES_128 - AES128_WRAP = 417, + AES128_WRAP = 417, #endif #ifdef WOLFSSL_AES_192 - AES192_WRAP = 437, + AES192_WRAP = 437, #endif #ifdef WOLFSSL_AES_256 - AES256_WRAP = 457 + AES256_WRAP = 457, +#endif +#ifdef HAVE_PKCS7 + PWRI_KEK_WRAP = 680 /*id-alg-PWRI-KEK, 1.2.840.113549.1.9.16.3.9 */ #endif }; -#endif /* !NO_AES */ +#endif /* !NO_AES || PKCS7 */ enum Key_Agree { dhSinglePass_stdDH_sha1kdf_scheme = 464, @@ -495,7 +498,6 @@ enum CompressAlg_Sum { }; #endif - enum VerifyType { NO_VERIFY = 0, VERIFY = 1, diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index daf36cd8c..ee1ea015d 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -177,6 +177,8 @@ typedef struct PKCS7 { Pkcs7EncodedRecip* recipList; /* recipients list */ byte* cek; /* content encryption key, random, dynamic */ word32 cekSz; /* size of cek, bytes */ + byte* pass; /* password, for PWRI decryption */ + word32 passSz; /* size of pass, bytes */ /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ } PKCS7; @@ -228,9 +230,15 @@ WOLFSSL_API int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, void* timePtr, byte* otherOID, word32 otherOIDSz, byte* other, word32 otherSz); +WOLFSSL_API int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, + word32 pLen, byte* salt, + word32 saltSz, int kdfOID, + int prfOID, int iterations, + int encryptOID); WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz); -WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz); +WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz); +WOLFSSL_API int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen); WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz); From 0b3930e24fb1a39095a4d58eb7804a867cf51ed0 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 14 Sep 2018 16:31:55 -0600 Subject: [PATCH 15/56] save and set PKCS7 isDynamic flag in wc_PKCS7_Init --- tests/api.c | 91 ++++++++++++++++++++++--------------------- wolfcrypt/src/pkcs7.c | 7 ++-- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/tests/api.c b/tests/api.c index 6a67eb115..d3f0ad366 100644 --- a/tests/api.c +++ b/tests/api.c @@ -15741,7 +15741,7 @@ static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void) static void test_wc_PKCS7_EncodeEncryptedData (void) { #if defined(HAVE_PKCS7) && !defined(NO_PKCS7_ENCRYPTED_DATA) - PKCS7 pkcs7; + PKCS7* pkcs7; byte* tmpBytePtr = NULL; byte encrypted[TWOK_BUF]; byte decoded[TWOK_BUF]; @@ -15808,64 +15808,65 @@ static void test_wc_PKCS7_EncodeEncryptedData (void) testSz = sizeof(testVectors) / sizeof(pkcs7EncryptedVector); for (i = 0; i < testSz; i++) { - AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, devId), 0); - pkcs7.content = (byte*)testVectors[i].content; - pkcs7.contentSz = testVectors[i].contentSz; - pkcs7.contentOID = testVectors[i].contentOID; - pkcs7.encryptOID = testVectors[i].encryptOID; - pkcs7.encryptionKey = testVectors[i].encryptionKey; - pkcs7.encryptionKeySz = testVectors[i].encryptionKeySz; - pkcs7.heap = HEAP_HINT; + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, devId), 0); + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->encryptionKey = testVectors[i].encryptionKey; + pkcs7->encryptionKeySz = testVectors[i].encryptionKeySz; + pkcs7->heap = HEAP_HINT; /* encode encryptedData */ - encryptedSz = wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted, + encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, sizeof(encrypted)); AssertIntGT(encryptedSz, 0); /* Decode encryptedData */ - decodedSz = wc_PKCS7_DecodeEncryptedData(&pkcs7, encrypted, encryptedSz, + decodedSz = wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz, decoded, sizeof(decoded)); AssertIntEQ(XMEMCMP(decoded, data, decodedSz), 0); /* Keep values for last itr. */ if (i < testSz - 1) { - wc_PKCS7_Free(&pkcs7); + wc_PKCS7_Free(pkcs7); } } printf(testingFmt, "wc_PKCS7_EncodeEncryptedData()"); AssertIntEQ(wc_PKCS7_EncodeEncryptedData(NULL, encrypted, sizeof(encrypted)),BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeEncryptedData(&pkcs7, NULL, + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, NULL, sizeof(encrypted)), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted, + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, 0), BAD_FUNC_ARG); /* Testing the struct. */ - tmpBytePtr = pkcs7.content; - pkcs7.content = NULL; - AssertIntEQ(wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted, + tmpBytePtr = pkcs7->content; + pkcs7->content = NULL; + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, sizeof(encrypted)), BAD_FUNC_ARG); - pkcs7.content = tmpBytePtr; - tmpWrd32 = pkcs7.contentSz; - pkcs7.contentSz = 0; - AssertIntEQ(wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted, + pkcs7->content = tmpBytePtr; + tmpWrd32 = pkcs7->contentSz; + pkcs7->contentSz = 0; + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, sizeof(encrypted)), BAD_FUNC_ARG); - pkcs7.contentSz = tmpWrd32; - tmpInt = pkcs7.encryptOID; - pkcs7.encryptOID = 0; - AssertIntEQ(wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted, + pkcs7->contentSz = tmpWrd32; + tmpInt = pkcs7->encryptOID; + pkcs7->encryptOID = 0; + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, sizeof(encrypted)), BAD_FUNC_ARG); - pkcs7.encryptOID = tmpInt; - tmpBytePtr = pkcs7.encryptionKey; - pkcs7.encryptionKey = NULL; - AssertIntEQ(wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted, + pkcs7->encryptOID = tmpInt; + tmpBytePtr = pkcs7->encryptionKey; + pkcs7->encryptionKey = NULL; + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, sizeof(encrypted)), BAD_FUNC_ARG); - pkcs7.encryptionKey = tmpBytePtr; - tmpWrd32 = pkcs7.encryptionKeySz; - pkcs7.encryptionKeySz = 0; - AssertIntEQ(wc_PKCS7_EncodeEncryptedData(&pkcs7, encrypted, + pkcs7->encryptionKey = tmpBytePtr; + tmpWrd32 = pkcs7->encryptionKeySz; + pkcs7->encryptionKeySz = 0; + AssertIntEQ(wc_PKCS7_EncodeEncryptedData(pkcs7, encrypted, sizeof(encrypted)), BAD_FUNC_ARG); - pkcs7.encryptionKeySz = tmpWrd32; + pkcs7->encryptionKeySz = tmpWrd32; printf(resultFmt, passed); @@ -15873,27 +15874,27 @@ static void test_wc_PKCS7_EncodeEncryptedData (void) AssertIntEQ(wc_PKCS7_DecodeEncryptedData(NULL, encrypted, encryptedSz, decoded, sizeof(decoded)), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_DecodeEncryptedData(&pkcs7, NULL, encryptedSz, + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(pkcs7, NULL, encryptedSz, decoded, sizeof(decoded)), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_DecodeEncryptedData(&pkcs7, encrypted, 0, + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, 0, decoded, sizeof(decoded)), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_DecodeEncryptedData(&pkcs7, encrypted, encryptedSz, + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz, NULL, sizeof(decoded)), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_DecodeEncryptedData(&pkcs7, encrypted, encryptedSz, + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz, decoded, 0), BAD_FUNC_ARG); /* Test struct fields */ - tmpBytePtr = pkcs7.encryptionKey; - pkcs7.encryptionKey = NULL; - AssertIntEQ(wc_PKCS7_DecodeEncryptedData(&pkcs7, encrypted, encryptedSz, + tmpBytePtr = pkcs7->encryptionKey; + pkcs7->encryptionKey = NULL; + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz, decoded, sizeof(decoded)), BAD_FUNC_ARG); - pkcs7.encryptionKey = tmpBytePtr; - pkcs7.encryptionKeySz = 0; - AssertIntEQ(wc_PKCS7_DecodeEncryptedData(&pkcs7, encrypted, encryptedSz, + pkcs7->encryptionKey = tmpBytePtr; + pkcs7->encryptionKeySz = 0; + AssertIntEQ(wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz, decoded, sizeof(decoded)), BAD_FUNC_ARG); printf(resultFmt, passed); - wc_PKCS7_Free(&pkcs7); + wc_PKCS7_Free(pkcs7); #endif } /* END test_wc_PKCS7_EncodeEncryptedData() */ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 1836e4ede..78e36c0b8 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -300,13 +300,17 @@ PKCS7* wc_PKCS7_New(void* heap, int devId) */ int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId) { + word16 isDynamic; + WOLFSSL_ENTER("wc_PKCS7_Init"); if (pkcs7 == NULL) { return BAD_FUNC_ARG; } + isDynamic = pkcs7->isDynamic; XMEMSET(pkcs7, 0, sizeof(PKCS7)); + pkcs7->isDynamic = isDynamic; #ifdef WOLFSSL_HEAP_TEST pkcs7->heap = (void*)WOLFSSL_HEAP_TEST; #else @@ -411,7 +415,6 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) int ret = 0; void* heap; int devId; - word16 isDynamic; Pkcs7Cert* cert; Pkcs7Cert* lastCert; @@ -421,11 +424,9 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) heap = pkcs7->heap; devId = pkcs7->devId; - isDynamic = pkcs7->isDynamic; ret = wc_PKCS7_Init(pkcs7, heap, devId); if (ret != 0) return ret; - pkcs7->isDynamic = isDynamic; if (derCert != NULL && derCertSz > 0) { #ifdef WOLFSSL_SMALL_STACK From 85e0c203ea1a7469cc936e427ad985af374845f2 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 14 Sep 2018 16:33:51 -0600 Subject: [PATCH 16/56] ignore pkcs7 test files --- .gitignore | 47 +++++++++++++++++++++++++++++++------------ wolfcrypt/test/test.c | 2 -- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 8608049b7..e997bb8e4 100644 --- a/.gitignore +++ b/.gitignore @@ -101,24 +101,45 @@ ecc-key.pem certreq.der certreq.pem pkcs7cert.der -pkcs7signedData_RSA_SHA.der -pkcs7signedData_RSA_SHA_noattr.der -pkcs7signedData_RSA_SHA224.der -pkcs7signedData_RSA_SHA256.der -pkcs7signedData_RSA_SHA384.der -pkcs7signedData_RSA_SHA512.der -pkcs7signedData_ECDSA_SHA.der -pkcs7signedData_ECDSA_SHA_noattr.der -pkcs7signedData_ECDSA_SHA224.der -pkcs7signedData_ECDSA_SHA256.der -pkcs7signedData_ECDSA_SHA384.der -pkcs7signedData_ECDSA_SHA512.der -pkcs7envelopedDataDES3.der +pkcs7compressedData_data_zlib.der +pkcs7compressedData_firmwarePkgData_zlib.der +pkcs7encryptedDataAES128CBC.der +pkcs7encryptedDataAES192CBC.der +pkcs7encryptedDataAES256CBC.der +pkcs7encryptedDataAES256CBC_attribs.der +pkcs7encryptedDataAES256CBC_firmwarePkgData.der +pkcs7encryptedDataAES256CBC_multi_attribs.der +pkcs7encryptedDataDES.der +pkcs7encryptedDataDES3.der pkcs7envelopedDataAES128CBC.der +pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der pkcs7envelopedDataAES128CBC_KEKRI.der pkcs7envelopedDataAES128CBC_PWRI.der pkcs7envelopedDataAES192CBC.der pkcs7envelopedDataAES256CBC.der +pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der +pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der +pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der +pkcs7envelopedDataDES3.der +pkcs7signedData_ECDSA_SHA224.der +pkcs7signedData_ECDSA_SHA256_custom_contentType.der +pkcs7signedData_ECDSA_SHA256.der +pkcs7signedData_ECDSA_SHA256_firmwarePkgData.der +pkcs7signedData_ECDSA_SHA256_SKID.der +pkcs7signedData_ECDSA_SHA384.der +pkcs7signedData_ECDSA_SHA512.der +pkcs7signedData_ECDSA_SHA.der +pkcs7signedData_ECDSA_SHA_noattr.der +pkcs7signedData_RSA_SHA224.der +pkcs7signedData_RSA_SHA256_custom_contentType.der +pkcs7signedData_RSA_SHA256.der +pkcs7signedData_RSA_SHA256_firmwarePkgData.der +pkcs7signedData_RSA_SHA256_SKID.der +pkcs7signedData_RSA_SHA256_with_ca_cert.der +pkcs7signedData_RSA_SHA384.der +pkcs7signedData_RSA_SHA512.der +pkcs7signedData_RSA_SHA.der +pkcs7signedData_RSA_SHA_noattr.der diff sslSniffer/sslSnifferTest/tracefile.txt tracefile.txt diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 3da92d000..23983ecd8 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19231,8 +19231,6 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, wc_PKCS7_Free(pkcs7); return -9224; } - (void)decoded; - (void)decodedSz; #ifdef PKCS7_OUTPUT_TEST_BUNDLES /* output pkcs7 envelopedData for external testing */ From 794137c20c1077ff8b2b91219692dd51bf3f0f05 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Mon, 17 Sep 2018 16:10:56 -0600 Subject: [PATCH 17/56] add CMS EnvelopedData OtherRecipientInfo support --- .gitignore | 1 + Makefile.am | 1 + wolfcrypt/src/pkcs7.c | 210 ++++++++++++++++++++++++++++++++++++++ wolfcrypt/test/test.c | 148 ++++++++++++++++++++++++--- wolfssl/wolfcrypt/pkcs7.h | 34 +++++- 5 files changed, 376 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index e997bb8e4..477bcf0c9 100644 --- a/.gitignore +++ b/.gitignore @@ -115,6 +115,7 @@ pkcs7envelopedDataAES128CBC.der pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der pkcs7envelopedDataAES128CBC_KEKRI.der pkcs7envelopedDataAES128CBC_PWRI.der +pkcs7envelopedDataAES128CBC_ORI.der pkcs7envelopedDataAES192CBC.der pkcs7envelopedDataAES256CBC.der pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der diff --git a/Makefile.am b/Makefile.am index 2b7864979..8f01ce5aa 100644 --- a/Makefile.am +++ b/Makefile.am @@ -58,6 +58,7 @@ CLEANFILES+= cert.der \ pkcs7envelopedDataAES128CBC.der \ pkcs7envelopedDataAES128CBC_KEKRI.der \ pkcs7envelopedDataAES128CBC_PWRI.der \ + pkcs7envelopedDataAES128CBC_ORI.der \ pkcs7envelopedDataAES192CBC.der \ pkcs7envelopedDataAES256CBC.der \ pkcs7signedData_RSA_SHA.der \ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 78e36c0b8..fbd9dbae8 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -336,6 +336,7 @@ typedef struct Pkcs7Cert { typedef struct Pkcs7EncodedRecip { byte recip[MAX_RECIP_SZ]; word32 recipSz; + int recipType; Pkcs7EncodedRecip* next; } Pkcs7EncodedRecip; @@ -3713,6 +3714,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, /* store recipient size */ recip->recipSz = idx; + recip->recipType = PKCS7_KARI; /* add recipient to recip list */ if (pkcs7->recipList == NULL) { @@ -4047,6 +4049,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz) /* store recipient size */ recip->recipSz = idx; + recip->recipType = PKCS7_KTRI; /* add recipient to recip list */ if (pkcs7->recipList == NULL) { @@ -4342,6 +4345,97 @@ int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, } +/* Encode and add CMS EnvelopedData ORI (OtherRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Return 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb) +{ + int oriTypeLenSz, blockKeySz, ret; + word32 idx, recipSeqSz; + + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + byte recipSeq[MAX_SEQ_SZ]; + byte oriTypeLen[MAX_LENGTH_SZ]; + + byte oriType[MAX_ORI_TYPE_SZ]; + byte oriValue[MAX_ORI_VALUE_SZ]; + word32 oriTypeSz = MAX_ORI_TYPE_SZ; + word32 oriValueSz = MAX_ORI_VALUE_SZ; + + if (pkcs7 == NULL || oriEncryptCb == NULL) { + return BAD_FUNC_ARG; + } + + /* allocate memory for RecipientInfo, KEK, encrypted key */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (recip == NULL) + return MEMORY_E; + + /* get key size for content-encryption key based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockKeySz; + } + + /* generate random content encryption key, if needed */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* call user callback to encrypt CEK and get oriType and oriValue + values back */ + ret = oriEncryptCb(pkcs7, pkcs7->cek, pkcs7->cekSz, oriType, &oriTypeSz, + oriValue, &oriValueSz, pkcs7->oriEncryptCtx); + if (ret != 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + oriTypeLenSz = SetLength(oriTypeSz, oriTypeLen); + + recipSeqSz = SetImplicit(ASN_SEQUENCE, 4, 1 + oriTypeLenSz + oriTypeSz + + oriValueSz, recipSeq); + + idx = 0; + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + /* oriType */ + recip->recip[idx] = ASN_OBJECT_ID; + idx += 1; + XMEMCPY(recip->recip + idx, oriTypeLen, oriTypeLenSz); + idx += oriTypeLenSz; + XMEMCPY(recip->recip + idx, oriType, oriTypeSz); + idx += oriTypeSz; + /* oriValue, input MUST already be ASN.1 encoded */ + XMEMCPY(recip->recip + idx, oriValue, oriValueSz); + idx += oriValueSz; + + /* store recipient size */ + recip->recipSz = idx; + recip->recipType = PKCS7_ORI; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + return idx; +} + + #ifndef NO_PWDBASED @@ -4780,6 +4874,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, /* store recipient size */ recip->recipSz = idx; + recip->recipType = PKCS7_PWRI; /* add recipient to recip list */ if (pkcs7->recipList == NULL) { @@ -4984,6 +5079,7 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, /* store recipient size */ recip->recipSz = idx; + recip->recipType = PKCS7_KEKRI; /* add recipient to recip list */ if (pkcs7->recipList == NULL) { @@ -5757,6 +5853,108 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, #endif /* HAVE_ECC */ +int wc_PKCS7_SetOriEncryptCtx(PKCS7* pkcs7, void* ctx) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->oriEncryptCtx = ctx; + + return 0; +} + + +int wc_PKCS7_SetOriDecryptCtx(PKCS7* pkcs7, void* ctx) +{ + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->oriDecryptCtx = ctx; + + return 0; +} + + +int wc_PKCS7_SetOriDecryptCb(PKCS7* pkcs7, CallbackOriDecrypt cb) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->oriDecryptCb = cb; + + return 0; +} + + +/* Decrypt ASN.1 OtherRecipientInfo (ori), as defined by: + * + * OtherRecipientInfo ::= SEQUENCE { + * oriType OBJECT IDENTIFIER, + * oriValue ANY DEFINED BY oriType } + * + * pkcs7 - pointer to initialized PKCS7 structure + * pkiMsg - pointer to encoded CMS bundle + * pkiMsgSz - size of pkiMsg, bytes + * idx - [IN/OUT] pointer to index into pkiMsg + * decryptedKey - [OUT] output buf for decrypted content encryption key + * decryptedKeySz - [IN/OUT] size of buffer, size of decrypted key + * recipFound - [OUT] 1 if recipient has been found, 0 if not + * + * Return 0 on success, negative upon error. + */ +static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + int ret, seqSz, oriOIDSz; + word32 oriValueSz, tmpIdx; + + byte* oriValue; + byte oriOID[MAX_OID_SZ]; + + if (pkcs7->oriDecryptCb == NULL) { + WOLFSSL_MSG("You must register an ORI Decrypt callback"); + return BAD_FUNC_ARG; + } + + /* get OtherRecipientInfo sequence length */ + if (GetLength(pkiMsg, idx, &seqSz, pkiMsgSz) < 0) + return ASN_PARSE_E; + + tmpIdx = *idx; + + /* remove and store oriType OBJECT IDENTIFIER */ + if (GetASNObjectId(pkiMsg, idx, &oriOIDSz, pkiMsgSz) != 0) + return ASN_PARSE_E; + + XMEMCPY(oriOID, pkiMsg + *idx, oriOIDSz); + *idx += oriOIDSz; + + /* get oriValue, increment idx */ + oriValue = pkiMsg + *idx; + oriValueSz = seqSz - (*idx - tmpIdx); + *idx += oriValueSz; + + /* pass oriOID and oriValue to user callback, expect back + decryptedKey and size */ + ret = pkcs7->oriDecryptCb(pkcs7, oriOID, (word32)oriOIDSz, oriValue, + oriValueSz, decryptedKey, decryptedKeySz, + pkcs7->oriDecryptCtx); + + if (ret != 0 || decryptedKey == NULL || *decryptedKeySz == 0) { + /* decrypt operation failed */ + *recipFound = 0; + return PKCS7_RECIP_E; + } + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + + return 0; +} + + /* decode ASN.1 PasswordRecipientInfo (pwri), return 0 on success, * < 0 on error */ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, @@ -6287,6 +6485,18 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, if (ret != 0) return ret; + /* ori is IMPLICIT[4] */ + } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | + ASN_CONTEXT_SPECIFIC | 4)) { + (*idx)++; + + /* found ori */ + ret = wc_PKCS7_DecryptOri(pkcs7, pkiMsg, pkiMsgSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + } else { /* failed to find RecipientInfo, restore idx and continue */ *idx = savedIdx; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 23983ecd8..af17794fe 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -18963,10 +18963,89 @@ typedef struct { int hashOID; int kdfIterations; + /* ORI specific */ + int isOri; + const char* outFileName; } pkcs7EnvelopedVector; +static const byte asnDataOid[] = { + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01 +}; + +/* ORI encrypt callback, responsible for encrypting content-encryption key (CEK) + * and giving wolfCrypt the value for oriOID and oriValue to place in + * OtherRecipientInfo. + * + * Returns 0 on success, negative upon error. */ +static int myOriEncryptCb(PKCS7* pkcs7, byte* cek, word32 cekSz, byte* oriType, + word32* oriTypeSz, byte* oriValue, word32* oriValueSz, + void* ctx) +{ + int i; + + /* make sure buffers are large enough */ + if ((*oriValueSz < (2 + cekSz)) || (*oriTypeSz < sizeof(oriType))) + return -1; + + /* our simple encryption algorithm will be take the bitwise complement */ + oriValue[0] = 0x04; /*ASN OCTET STRING */ + oriValue[1] = (byte)cekSz; /* length */ + for (i = 0; i < (int)cekSz; i++) { + oriValue[2 + i] = ~cek[i]; + } + *oriValueSz = 2 + cekSz; + + /* set oriType to ASN.1 encoded data OID */ + XMEMCPY(oriType, asnDataOid, sizeof(asnDataOid)); + *oriTypeSz = sizeof(asnDataOid); + + (void)pkcs7; + (void)ctx; + + return 0; +} + + +/* ORI decrypt callback, responsible for providing a decrypted content + * encryption key (CEK) placed into decryptedKey and size placed into + * decryptedKeySz. oriOID and oriValue are given to the callback to help + * in decrypting the encrypted CEK. + * + * Returns 0 on success, negative upon error. */ +static int myOriDecryptCb(PKCS7* pkcs7, byte* oriType, word32 oriTypeSz, + byte* oriValue, word32 oriValueSz, byte* decryptedKey, + word32* decryptedKeySz, void* ctx) +{ + int i; + + /* make sure oriType matches what we expect */ + if (oriTypeSz != sizeof(asnDataOid)) + return -1; + + if (XMEMCMP(oriType, asnDataOid, sizeof(asnDataOid)) != 0) + return -1; + + /* make sure decrypted buffer is large enough */ + if (*decryptedKeySz < oriValueSz) + return -1; + + /* decrypt encrypted CEK using simple bitwise complement, + only for example */ + for (i = 0; i < (int)oriValueSz - 2; i++) { + decryptedKey[i] = ~oriValue[2 + i]; + } + + *decryptedKeySz = oriValueSz - 2; + + (void)pkcs7; + (void)ctx; + + return 0; +} + + static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, byte* rsaPrivKey, word32 rsaPrivKeySz, byte* eccCert, word32 eccCertSz, @@ -19022,24 +19101,28 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #ifndef NO_DES3 {data, (word32)sizeof(data), DATA, DES3b, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataDES3.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, + "pkcs7envelopedDataDES3.der"}, #endif #ifndef NO_AES #ifdef WOLFSSL_AES_128 {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES128CBC.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES128CBC.der"}, #endif #ifdef WOLFSSL_AES_192 {data, (word32)sizeof(data), DATA, AES192CBCb, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES192CBC.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES192CBC.der"}, #endif #ifdef WOLFSSL_AES_256 {data, (word32)sizeof(data), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES256CBC.der"}, #endif #endif /* NO_AES */ #endif @@ -19051,7 +19134,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, dhSinglePass_stdDH_sha1kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, - NULL, 0, NULL, 0, 0, 0, 0, + NULL, 0, NULL, 0, 0, 0, 0, 0, "pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der"}, #endif @@ -19059,7 +19142,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, - NULL, 0, NULL, 0, 0, 0, 0, + NULL, 0, NULL, 0, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der"}, #endif /* NO_SHA256 && WOLFSSL_AES_256 */ @@ -19067,14 +19150,14 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, - NULL, 0, NULL, 0, 0, 0, 0, + NULL, 0, NULL, 0, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der"}, /* with optional user keying material (ukm) */ {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz, optionalUkm, sizeof(optionalUkm), NULL, 0, - NULL, 0, NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der"}, #endif /* WOLFSSL_SHA512 && WOLFSSL_AES_256 */ #endif /* NO_AES */ @@ -19086,7 +19169,8 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, 0, NULL, 0, NULL, 0, NULL, 0, secretKey, sizeof(secretKey), secretKeyId, sizeof(secretKeyId), NULL, NULL, 0, NULL, 0, - NULL, 0, NULL, 0, 0, 0, 0, "pkcs7envelopedDataAES128CBC_KEKRI.der"}, + NULL, 0, NULL, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES128CBC_KEKRI.der"}, #endif #endif @@ -19096,10 +19180,15 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, password, (word32)XSTRLEN(password), - salt, sizeof(salt), PBKDF2_OID, WC_SHA, 5, + salt, sizeof(salt), PBKDF2_OID, WC_SHA, 5, 0, "pkcs7envelopedDataAES128CBC_PWRI.der"}, #endif #endif + + /* ori (OtherRecipientInfo) recipient types */ + {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, NULL, 0, NULL, 0, + NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, NULL, 0, NULL, + 0, 0, 0, 0, 1, "pkcs7envelopedDataAES128CBC_ORI.der"}, }; testSz = sizeof(testVectors) / sizeof(pkcs7EnvelopedVector); @@ -19187,6 +19276,33 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, return -9220; } + } else if (testVectors[i].isOri == 1) { + /* ORI recipient type */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -9221; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + + ret = wc_PKCS7_AddRecipient_ORI(pkcs7, myOriEncryptCb); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -9222; + } + + /* set decrypt callback for decryption */ + ret = wc_PKCS7_SetOriDecryptCb(pkcs7, myOriDecryptCb); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -9223; + } } else { /* KTRI or KARI recipient types */ @@ -19195,7 +19311,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, (word32)testVectors[i].certSz); if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9221; + return -9224; } pkcs7->keyWrapOID = testVectors[i].keyWrapOID; @@ -19215,7 +19331,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, sizeof(enveloped)); if (envelopedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9222; + return -9225; } /* decode envelopedData */ @@ -19223,13 +19339,13 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, decoded, sizeof(decoded)); if (decodedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9223; + return -9226; } /* test decode result */ if (XMEMCMP(decoded, data, sizeof(data)) != 0){ wc_PKCS7_Free(pkcs7); - return -9224; + return -9227; } #ifdef PKCS7_OUTPUT_TEST_BUNDLES @@ -19237,14 +19353,14 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7File = fopen(testVectors[i].outFileName, "wb"); if (!pkcs7File) { wc_PKCS7_Free(pkcs7); - return -9225; + return -9228; } ret = (int)fwrite(enveloped, 1, envelopedSz, pkcs7File); fclose(pkcs7File); if (ret != envelopedSz) { wc_PKCS7_Free(pkcs7); - return -9226; + return -9229; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index ee1ea015d..0adeb08cc 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -51,6 +51,13 @@ #define MAX_PKCS7_CERTS 4 #endif +#ifndef MAX_ORI_TYPE_SZ + #define MAX_ORI_TYPE_SZ MAX_OID_SZ +#endif +#ifndef MAX_ORI_VALUE_SZ + #define MAX_ORI_VALUE_SZ 512 +#endif + /* PKCS#7 content types, ref RFC 2315 (Section 14) */ enum PKCS7_TYPES { PKCS7_MSG = 650, /* 1.2.840.113549.1.7 */ @@ -113,6 +120,17 @@ typedef struct PKCS7DecodedAttrib { typedef struct Pkcs7Cert Pkcs7Cert; typedef struct Pkcs7EncodedRecip Pkcs7EncodedRecip; +typedef struct PKCS7 PKCS7; + +/* OtherRecipientInfo decrypt callback prototype */ +typedef int (*CallbackOriDecrypt)(PKCS7* pkcs7, byte* oriType, word32 oriTypeSz, + byte* oriValue, word32 oriValueSz, + byte* decryptedKey, word32* decryptedKeySz, + void* ctx); +typedef int (*CallbackOriEncrypt)(PKCS7* pkcs7, byte* cek, word32 cekSz, + byte* oriType, word32* oriTypeSz, + byte* oriValue, word32* oriValueSz, + void* ctx); /* Public Structure Warning: * Existing members must not be changed to maintain backwards compatibility! @@ -180,6 +198,11 @@ typedef struct PKCS7 { byte* pass; /* password, for PWRI decryption */ word32 passSz; /* size of pass, bytes */ + CallbackOriEncrypt oriEncryptCb; /* ORI encrypt callback */ + CallbackOriDecrypt oriDecryptCb; /* ORI decrypt callback */ + void* oriEncryptCtx; /* ORI encrypt user context ptr */ + void* oriDecryptCtx; /* ORI decrypt user context ptr */ + /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ } PKCS7; @@ -224,21 +247,28 @@ WOLFSSL_API int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, int keyWrapOID, int keyAgreeOID, byte* ukm, word32 ukmSz); + +WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz); WOLFSSL_API int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, word32 kekSz, byte* keyID, word32 keyIdSz, void* timePtr, byte* otherOID, word32 otherOIDSz, byte* other, word32 otherSz); + +WOLFSSL_API int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen); WOLFSSL_API int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, byte* salt, word32 saltSz, int kdfOID, int prfOID, int iterations, int encryptOID); +WOLFSSL_API int wc_PKCS7_SetOriEncryptCtx(PKCS7* pkcs7, void* ctx); +WOLFSSL_API int wc_PKCS7_SetOriDecryptCtx(PKCS7* pkcs7, void* ctx); +WOLFSSL_API int wc_PKCS7_SetOriDecryptCb(PKCS7* pkcs7, CallbackOriDecrypt cb); +WOLFSSL_API int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt cb); + WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz); -WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz); -WOLFSSL_API int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen); WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz); From 75349bbba5e6dce290ec61301a5927067415b4c7 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Tue, 18 Sep 2018 10:12:28 -0600 Subject: [PATCH 18/56] add support for SubjectKeyIdentifier to KTRI CMS RecipientInfo types --- .gitignore | 2 + Makefile.am | 2 + wolfcrypt/src/pkcs7.c | 295 +++++++++++++++++++++++++------------- wolfcrypt/test/test.c | 102 ++++++++----- wolfssl/wolfcrypt/pkcs7.h | 17 +-- 5 files changed, 277 insertions(+), 141 deletions(-) diff --git a/.gitignore b/.gitignore index 477bcf0c9..570a4406c 100644 --- a/.gitignore +++ b/.gitignore @@ -118,6 +118,8 @@ pkcs7envelopedDataAES128CBC_PWRI.der pkcs7envelopedDataAES128CBC_ORI.der pkcs7envelopedDataAES192CBC.der pkcs7envelopedDataAES256CBC.der +pkcs7envelopedDataAES256CBC_IANDS.der +pkcs7envelopedDataAES256CBC_SKID.der pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der diff --git a/Makefile.am b/Makefile.am index 8f01ce5aa..08a60d8b8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -61,6 +61,8 @@ CLEANFILES+= cert.der \ pkcs7envelopedDataAES128CBC_ORI.der \ pkcs7envelopedDataAES192CBC.der \ pkcs7envelopedDataAES256CBC.der \ + pkcs7envelopedDataAES256CBC_IANDS.der \ + pkcs7envelopedDataAES256CBC_SKID.der \ pkcs7signedData_RSA_SHA.der \ pkcs7signedData_RSA_SHA_noattr.der \ pkcs7signedData_RSA_SHA224.der \ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index fbd9dbae8..808e2c0b2 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -487,7 +487,7 @@ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) XMEMCPY(pkcs7->issuerSubjKeyId, dCert->extSubjKeyId, KEYID_SIZE); /* default to IssuerAndSerialNumber for SignerIdentifier */ - pkcs7->sidType = SID_ISSUER_AND_SERIAL_NUMBER; + pkcs7->sidType = CMS_ISSUER_AND_SERIAL_NUMBER; /* free existing recipient list if existing */ wc_PKCS7_FreeEncodedRecipientSet(pkcs7); @@ -1373,7 +1373,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, esd->contentInfoSeq); /* SignerIdentifier */ - if (pkcs7->sidType == SID_ISSUER_AND_SERIAL_NUMBER) { + if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { /* IssuerAndSerialNumber */ esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, esd->issuerSn, MAX_SN_SZ); @@ -1386,7 +1386,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, /* version MUST be 1 */ esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0); - } else if (pkcs7->sidType == SID_SUBJECT_KEY_IDENTIFIER) { + } else if (pkcs7->sidType == CMS_SKID) { /* SubjectKeyIdentifier */ esd->issuerSKIDSz = SetOctetString(KEYID_SIZE, esd->issuerSKID); esd->issuerSKIDSeqSz = SetExplicit(0, esd->issuerSKIDSz + KEYID_SIZE, @@ -1560,7 +1560,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, XMEMCPY(output2 + idx, esd->signerVersion, esd->signerVersionSz); idx += esd->signerVersionSz; /* SignerIdentifier */ - if (pkcs7->sidType == SID_ISSUER_AND_SERIAL_NUMBER) { + if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { /* IssuerAndSerialNumber */ XMEMCPY(output2 + idx, esd->issuerSnSeq, esd->issuerSnSeqSz); idx += esd->issuerSnSeqSz; @@ -1570,7 +1570,7 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, idx += pkcs7->issuerSz; XMEMCPY(output2 + idx, esd->issuerSn, esd->issuerSnSz); idx += esd->issuerSnSz; - } else if (pkcs7->sidType == SID_SUBJECT_KEY_IDENTIFIER) { + } else if (pkcs7->sidType == CMS_SKID) { /* SubjectKeyIdentifier */ XMEMCPY(output2 + idx, esd->issuerSKIDSeq, esd->issuerSKIDSeqSz); idx += esd->issuerSKIDSeqSz; @@ -3400,7 +3400,7 @@ static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, * Returns 0 on success, negative upon error */ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, int keyWrapOID, int keyAgreeOID, byte* ukm, - word32 ukmSz) + word32 ukmSz, int options) { Pkcs7EncodedRecip* recip = NULL; Pkcs7EncodedRecip* lastRecip = NULL; @@ -3727,6 +3727,8 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, lastRecip->next = recip; } + (void)options; + return idx; } @@ -3738,7 +3740,8 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, * to CMS/PKCS#7 EnvelopedData structure. * * Returns 0 on success, negative upon error */ -int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz) +int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, + int options) { Pkcs7EncodedRecip* recip = NULL; Pkcs7EncodedRecip* lastRecip = NULL; @@ -3748,9 +3751,10 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz) word32 encryptedKeySz = 0; int ret = 0, blockKeySz; - int verSz, issuerSz, snSz, keyEncAlgSz; - int issuerSeqSz, recipSeqSz, issuerSerialSeqSz; + int verSz = 0, issuerSz = 0, snSz = 0, keyEncAlgSz = 0; + int issuerSeqSz = 0, recipSeqSz = 0, issuerSerialSeqSz = 0; int encKeyOctetStrSz; + int sidType; byte ver[MAX_VERSION_SZ]; byte issuerSerialSeq[MAX_SEQ_SZ]; @@ -3758,6 +3762,10 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz) byte issuerSeq[MAX_SEQ_SZ]; byte encKeyOctetStr[MAX_OCTET_STR_SZ]; + byte issuerSKIDSeq[MAX_SEQ_SZ]; + byte issuerSKID[MAX_OCTET_STR_SZ]; + word32 issuerSKIDSeqSz = 0, issuerSKIDSz = 0; + #ifdef WOLFSSL_SMALL_STACK byte* serial; byte* keyAlgArray; @@ -3797,6 +3805,14 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz) encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; XMEMSET(encryptedKey, 0, encryptedKeySz); + /* allow options to override SubjectIdentifier type if set */ + sidType = pkcs7->sidType; + if (options & CMS_SKID) { + sidType = CMS_SKID; + } else if (options & CMS_ISSUER_AND_SERIAL_NUMBER) { + sidType = CMS_ISSUER_AND_SERIAL_NUMBER; + } + /* allocate recipient struct */ recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -3851,42 +3867,56 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz) return ret; } - /* version */ - verSz = SetMyVersion(0, ver, 0); + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { - /* IssuerAndSerialNumber */ - if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) { - WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length"); - FreeDecodedCert(decoded); + /* version, must be 0 for IssuerAndSerialNumber */ + verSz = SetMyVersion(0, ver, 0); + + /* IssuerAndSerialNumber */ + if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) { + WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length"); + FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return -1; - } - issuerSz = decoded->issuerRawLen; - issuerSeqSz = SetSequence(issuerSz, issuerSeq); + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return -1; + } + issuerSz = decoded->issuerRawLen; + issuerSeqSz = SetSequence(issuerSz, issuerSeq); - if (decoded->serialSz == 0) { - WOLFSSL_MSG("DecodedCert missing serial number"); - FreeDecodedCert(decoded); + if (decoded->serialSz == 0) { + WOLFSSL_MSG("DecodedCert missing serial number"); + FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return -1; - } - snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial, - MAX_SN_SZ); + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return -1; + } + snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial, + MAX_SN_SZ); - issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz, - issuerSerialSeq); + issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz, + issuerSerialSeq); + + } else if (sidType == CMS_SKID) { + + /* version, must be 2 for SubjectKeyIdentifier */ + verSz = SetMyVersion(2, ver, 0); + + issuerSKIDSz = SetOctetString(KEYID_SIZE, issuerSKID); + issuerSKIDSeqSz = SetExplicit(0, issuerSKIDSz + KEYID_SIZE, + issuerSKIDSeq); + } else { + return PKCS7_RECIP_E; + } /* KeyEncryptionAlgorithmIdentifier, only support RSA now */ if (pkcs7->publicKeyOID != RSAk) { @@ -4000,22 +4030,43 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz) encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); /* RecipientInfo */ - recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz + - issuerSz + snSz + keyEncAlgSz + encKeyOctetStrSz + - encryptedKeySz, recipSeq); + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz + + issuerSz + snSz + keyEncAlgSz + + encKeyOctetStrSz + encryptedKeySz, recipSeq); - if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz + - keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) { - WOLFSSL_MSG("RecipientInfo output buffer too small"); - FreeDecodedCert(decoded); + if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz + + keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) { + WOLFSSL_MSG("RecipientInfo output buffer too small"); + FreeDecodedCert(decoded); #ifdef WOLFSSL_SMALL_STACK - XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return BUFFER_E; + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + } else { + recipSeqSz = SetSequence(verSz + issuerSKIDSeqSz + issuerSKIDSz + + KEYID_SIZE + keyEncAlgSz + encKeyOctetStrSz + + encryptedKeySz, recipSeq); + + if (recipSeqSz + verSz + issuerSKIDSeqSz + issuerSKIDSz + KEYID_SIZE + + keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) { + WOLFSSL_MSG("RecipientInfo output buffer too small"); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } } idx = 0; @@ -4023,14 +4074,23 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz) idx += recipSeqSz; XMEMCPY(recip->recip + idx, ver, verSz); idx += verSz; - XMEMCPY(recip->recip + idx, issuerSerialSeq, issuerSerialSeqSz); - idx += issuerSerialSeqSz; - XMEMCPY(recip->recip + idx, issuerSeq, issuerSeqSz); - idx += issuerSeqSz; - XMEMCPY(recip->recip + idx, decoded->issuerRaw, issuerSz); - idx += issuerSz; - XMEMCPY(recip->recip + idx, serial, snSz); - idx += snSz; + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + XMEMCPY(recip->recip + idx, issuerSerialSeq, issuerSerialSeqSz); + idx += issuerSerialSeqSz; + XMEMCPY(recip->recip + idx, issuerSeq, issuerSeqSz); + idx += issuerSeqSz; + XMEMCPY(recip->recip + idx, decoded->issuerRaw, issuerSz); + idx += issuerSz; + XMEMCPY(recip->recip + idx, serial, snSz); + idx += snSz; + } else { + XMEMCPY(recip->recip + idx, issuerSKIDSeq, issuerSKIDSeqSz); + idx += issuerSKIDSeqSz; + XMEMCPY(recip->recip + idx, issuerSKID, issuerSKIDSz); + idx += issuerSKIDSz; + XMEMCPY(recip->recip + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE); + idx += KEYID_SIZE; + } XMEMCPY(recip->recip + idx, keyAlgArray, keyEncAlgSz); idx += keyEncAlgSz; XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); @@ -4257,12 +4317,13 @@ static int wc_PKCS7_GenerateIV(PKCS7* pkcs7, WC_RNG* rng, byte* iv, word32 ivSz) } -/* Set SignerIdentifier type to be used in SignedData encoding. Is either - * IssuerAndSerialNumber or SubjectKeyIdentifier. SignedData encoding - * defaults to using IssuerAndSerialNumber unless set with this function. +/* Set default SignerIdentifier type to be used. Is either + * IssuerAndSerialNumber or SubjectKeyIdentifier. Encoding defaults to using + * IssuerAndSerialNumber unless set with this function or explicitly + * overriden via options when adding RecipientInfo type. * * pkcs7 - pointer to initialized PKCS7 structure - * type - either SID_ISSUER_AND_SERIAL_NUMBER or SID_SUBJECT_KEY_IDENTIFIER + * type - either CMS_ISSUER_AND_SERIAL_NUMBER or CMS_SKID * * return 0 on success, negative upon error */ int wc_PKCS7_SetSignerIdentifierType(PKCS7* pkcs7, int type) @@ -4270,8 +4331,8 @@ int wc_PKCS7_SetSignerIdentifierType(PKCS7* pkcs7, int type) if (pkcs7 == NULL) return BAD_FUNC_ARG; - if (type != SID_ISSUER_AND_SERIAL_NUMBER && - type != SID_SUBJECT_KEY_IDENTIFIER) { + if (type != CMS_ISSUER_AND_SERIAL_NUMBER && + type != CMS_SKID) { return BAD_FUNC_ARG; } @@ -4349,7 +4410,8 @@ int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, * to CMS/PKCS#7 EnvelopedData structure. * * Return 0 on success, negative upon error */ -int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb) +int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb, + int options) { int oriTypeLenSz, blockKeySz, ret; word32 idx, recipSeqSz; @@ -4432,6 +4494,8 @@ int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb) lastRecip->next = recip; } + (void)options; + return idx; } @@ -4650,7 +4714,8 @@ static int wc_PKCS7_PwriKek_KeyUnWrap(PKCS7* pkcs7, const byte* kek, * Return 0 on success, negative upon error */ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, byte* salt, word32 saltSz, int kdfOID, - int hashOID, int iterations, int encryptOID) + int hashOID, int iterations, int encryptOID, + int options) { Pkcs7EncodedRecip* recip = NULL; Pkcs7EncodedRecip* lastRecip = NULL; @@ -4887,6 +4952,8 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, lastRecip->next = recip; } + (void)options; + return idx; } @@ -4927,7 +4994,8 @@ int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen) int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, word32 kekSz, byte* keyId, word32 keyIdSz, void* timePtr, byte* otherOID, - word32 otherOIDSz, byte* other, word32 otherSz) + word32 otherOIDSz, byte* other, word32 otherSz, + int options) { Pkcs7EncodedRecip* recip = NULL; Pkcs7EncodedRecip* lastRecip = NULL; @@ -5092,6 +5160,8 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, lastRecip->next = recip; } + (void)options; + return idx; } @@ -5173,7 +5243,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) #ifndef NO_RSA case RSAk: ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert, - pkcs7->singleCertSz); + pkcs7->singleCertSz, 0); break; #endif #ifdef HAVE_ECC @@ -5182,7 +5252,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) pkcs7->singleCertSz, pkcs7->keyWrapOID, pkcs7->keyAgreeOID, pkcs7->ukm, - pkcs7->ukmSz); + pkcs7->ukmSz, 0); break; #endif @@ -5356,7 +5426,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, word32* decryptedKeySz, int* recipFound) { int length, encryptedKeySz, ret; - int keySz; + int keySz, version, sidType; word32 encOID; word32 keyIdx; byte issuerHash[KEYID_SIZE]; @@ -5376,38 +5446,73 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, RsaKey privKey[1]; #endif - /* remove IssuerAndSerialNumber */ - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) return ASN_PARSE_E; - if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* if we found correct recipient, issuer hashes will match */ - if (XMEMCMP(issuerHash, pkcs7->issuerHash, KEYID_SIZE) == 0) { - *recipFound = 1; + if (version == 0) { + sidType = CMS_ISSUER_AND_SERIAL_NUMBER; + } else if (version == 2) { + sidType = CMS_SKID; + } else { + return ASN_VERSION_E; } + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + + /* remove IssuerAndSerialNumber */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* if we found correct recipient, issuer hashes will match */ + if (XMEMCMP(issuerHash, pkcs7->issuerHash, KEYID_SIZE) == 0) { + *recipFound = 1; + } + #ifdef WOLFSSL_SMALL_STACK - serialNum = (mp_int*)XMALLOC(sizeof(mp_int), pkcs7->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (serialNum == NULL) - return MEMORY_E; + serialNum = (mp_int*)XMALLOC(sizeof(mp_int), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (serialNum == NULL) + return MEMORY_E; #endif - if (GetInt(serialNum, pkiMsg, idx, pkiMsgSz) < 0) { + if (GetInt(serialNum, pkiMsg, idx, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + mp_clear(serialNum); + #ifdef WOLFSSL_SMALL_STACK XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return ASN_PARSE_E; + + } else { + + /* remove SubjectKeyIdentifier */ + if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* if we found correct recipient, SKID will match */ + if (XMEMCMP(pkiMsg + (*idx), pkcs7->issuerSubjKeyId, KEYID_SIZE) == 0) { + *recipFound = 1; + } + (*idx) += KEYID_SIZE; } - mp_clear(serialNum); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - if (GetAlgoId(pkiMsg, idx, &encOID, oidKeyType, pkiMsgSz) < 0) return ASN_PARSE_E; @@ -6395,14 +6500,6 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, * last good saved one */ if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) > 0) { - if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { - *idx = savedIdx; - break; - } - - if (version != 0) - return ASN_VERSION_E; - #ifndef NO_RSA /* found ktri */ ret = wc_PKCS7_DecryptKtri(pkcs7, pkiMsg, pkiMsgSz, idx, diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index af17794fe..2fcee72d3 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -18942,6 +18942,8 @@ typedef struct { word32 privateKeySz; byte* optionalUkm; word32 optionalUkmSz; + int ktriOptions; /* KTRI options flags */ + int kariOptions; /* KARI options flags */ /* KEKRI specific */ byte* secretKey; /* key, only for kekri RecipientInfo types */ @@ -18953,6 +18955,7 @@ typedef struct { word32 otherAttrOIDSz; /* size of otherAttrOID, bytes */ byte* otherAttr; /* OPTIONAL, other attribute, ASN.1 encoded */ word32 otherAttrSz; /* size of otherAttr, bytes */ + int kekriOptions; /* KEKRI options flags */ /* PWRI specific */ char* password; @@ -18962,9 +18965,11 @@ typedef struct { int kdfOID; int hashOID; int kdfIterations; + int pwriOptions; /* PWRI options flags */ /* ORI specific */ int isOri; + int oriOptions; /* ORI options flags */ const char* outFileName; } pkcs7EnvelopedVector; @@ -19100,29 +19105,41 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #ifndef NO_RSA #ifndef NO_DES3 {data, (word32)sizeof(data), DATA, DES3b, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, + rsaPrivKey, rsaPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, + 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, "pkcs7envelopedDataDES3.der"}, #endif #ifndef NO_AES #ifdef WOLFSSL_AES_128 {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, + rsaPrivKey, rsaPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, + 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, "pkcs7envelopedDataAES128CBC.der"}, #endif #ifdef WOLFSSL_AES_192 {data, (word32)sizeof(data), DATA, AES192CBCb, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, + rsaPrivKey, rsaPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, + 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, "pkcs7envelopedDataAES192CBC.der"}, #endif #ifdef WOLFSSL_AES_256 {data, (word32)sizeof(data), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, + rsaPrivKey, rsaPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, + 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC.der"}, + + /* explicitly using SKID for SubjectKeyIdentifier */ + {data, (word32)sizeof(data), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, CMS_SKID, 0, NULL, 0, NULL, 0, NULL, + NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, + "pkcs7envelopedDataAES256CBC_SKID.der"}, + + /* explicitly using IssuerAndSerialNumber for SubjectKeyIdentifier */ + {data, (word32)sizeof(data), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, CMS_ISSUER_AND_SERIAL_NUMBER, 0, + NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, + 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_IANDS.der"}, #endif #endif /* NO_AES */ #endif @@ -19133,31 +19150,31 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, dhSinglePass_stdDH_sha1kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, - NULL, 0, NULL, 0, 0, 0, 0, 0, + eccPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, + 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, "pkcs7envelopedDataAES128CBC_ECDH_SHA1KDF.der"}, #endif #if !defined(NO_SHA256) && defined(WOLFSSL_AES_256) {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, - NULL, 0, NULL, 0, 0, 0, 0, 0, + eccPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, + 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA256KDF.der"}, #endif /* NO_SHA256 && WOLFSSL_AES_256 */ #if defined(WOLFSSL_SHA512) && defined(WOLFSSL_AES_256) {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, - NULL, 0, NULL, 0, 0, 0, 0, 0, + eccPrivKeySz, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, + 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF.der"}, /* with optional user keying material (ukm) */ {data, (word32)sizeof(data), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, optionalUkm, sizeof(optionalUkm), NULL, 0, - NULL, 0, NULL, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, + eccPrivKeySz, optionalUkm, sizeof(optionalUkm), 0, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, "pkcs7envelopedDataAES256CBC_ECDH_SHA512KDF_ukm.der"}, #endif /* WOLFSSL_SHA512 && WOLFSSL_AES_256 */ #endif /* NO_AES */ @@ -19167,9 +19184,9 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #ifndef NO_AES #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) {data, (word32)sizeof(data), DATA, AES128CBCb, AES128_WRAP, 0, - NULL, 0, NULL, 0, NULL, 0, secretKey, sizeof(secretKey), + NULL, 0, NULL, 0, NULL, 0, 0, 0, secretKey, sizeof(secretKey), secretKeyId, sizeof(secretKeyId), NULL, NULL, 0, NULL, 0, - NULL, 0, NULL, 0, 0, 0, 0, 0, + 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, "pkcs7envelopedDataAES128CBC_KEKRI.der"}, #endif #endif @@ -19178,17 +19195,17 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #if !defined(NO_PWDBASED) && !defined(NO_AES) #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, - NULL, 0, NULL, 0, NULL, 0, NULL, 0, - NULL, 0, NULL, NULL, 0, NULL, 0, password, (word32)XSTRLEN(password), - salt, sizeof(salt), PBKDF2_OID, WC_SHA, 5, 0, - "pkcs7envelopedDataAES128CBC_PWRI.der"}, + NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, password, + (word32)XSTRLEN(password), salt, sizeof(salt), PBKDF2_OID, WC_SHA, 5, + 0, 0, 0, "pkcs7envelopedDataAES128CBC_PWRI.der"}, #endif #endif /* ori (OtherRecipientInfo) recipient types */ {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, NULL, 0, NULL, 0, - NULL, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, NULL, 0, NULL, - 0, 0, 0, 0, 1, "pkcs7envelopedDataAES128CBC_ORI.der"}, + NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, + NULL, 0, 0, 0, 0, 0, 1, 0, "pkcs7envelopedDataAES128CBC_ORI.der"}, }; testSz = sizeof(testVectors) / sizeof(pkcs7EnvelopedVector); @@ -19224,7 +19241,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, testVectors[i].secretKeyId, testVectors[i].secretKeyIdSz, testVectors[i].timePtr, testVectors[i].otherAttrOID, testVectors[i].otherAttrOIDSz, testVectors[i].otherAttr, - testVectors[i].otherAttrSz); + testVectors[i].otherAttrSz, testVectors[i].kekriOptions); if (ret < 0) { wc_PKCS7_Free(pkcs7); @@ -19260,7 +19277,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, testVectors[i].passwordSz, testVectors[i].salt, testVectors[i].saltSz, testVectors[i].kdfOID, testVectors[i].hashOID, testVectors[i].kdfIterations, - testVectors[i].encryptOID); + testVectors[i].encryptOID, testVectors[i].pwriOptions); if (ret < 0) { wc_PKCS7_Free(pkcs7); @@ -19289,7 +19306,8 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7->contentOID = testVectors[i].contentOID; pkcs7->encryptOID = testVectors[i].encryptOID; - ret = wc_PKCS7_AddRecipient_ORI(pkcs7, myOriEncryptCb); + ret = wc_PKCS7_AddRecipient_ORI(pkcs7, myOriEncryptCb, + testVectors[i].oriOptions); if (ret < 0) { wc_PKCS7_Free(pkcs7); @@ -19324,6 +19342,25 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7->encryptOID = testVectors[i].encryptOID; pkcs7->ukm = testVectors[i].optionalUkm; pkcs7->ukmSz = testVectors[i].optionalUkmSz; + + /* set SubjectIdentifier type for KTRI types */ + if (testVectors[i].ktriOptions & CMS_SKID) { + + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -9225; + } + } else if (testVectors[i].ktriOptions & + CMS_ISSUER_AND_SERIAL_NUMBER) { + + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, + CMS_ISSUER_AND_SERIAL_NUMBER); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -9225; + } + } } /* encode envelopedData */ @@ -19923,8 +19960,7 @@ static int pkcs7signed_run_vectors( {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA256_SKID.der", 0, NULL, 0, - SID_SUBJECT_KEY_IDENTIFIER}, + "pkcs7signedData_RSA_SHA256_SKID.der", 0, NULL, 0, CMS_SKID}, /* RSA with SHA256 and custom contentType */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, @@ -19995,8 +20031,7 @@ static int pkcs7signed_run_vectors( {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA256_SKID.der", 0, NULL, 0, - SID_SUBJECT_KEY_IDENTIFIER}, + "pkcs7signedData_ECDSA_SHA256_SKID.der", 0, NULL, 0, CMS_SKID}, /* ECDSA with SHA256 and custom contentType */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, @@ -20106,9 +20141,8 @@ static int pkcs7signed_run_vectors( /* set SignerIdentifier to use SubjectKeyIdentifier if desired, default is IssuerAndSerialNumber */ - if (testVectors[i].sidType == SID_SUBJECT_KEY_IDENTIFIER) { - ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, - SID_SUBJECT_KEY_IDENTIFIER); + if (testVectors[i].sidType == CMS_SKID) { + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 0adeb08cc..6d1cbe472 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -88,9 +88,9 @@ enum Pkcs7_Misc { MAX_SEQ_SZ + MAX_ALGO_SZ + 1 + MAX_ENCRYPTED_KEY_SZ }; -enum Pkcs7_SignerIdentifier_Types { - SID_ISSUER_AND_SERIAL_NUMBER = 0, - SID_SUBJECT_KEY_IDENTIFIER = 1 +enum Cms_Options { + CMS_SKID = 1, + CMS_ISSUER_AND_SERIAL_NUMBER = 2, }; /* CMS/PKCS#7 RecipientInfo types, RFC 5652, Section 6.2 */ @@ -242,11 +242,11 @@ WOLFSSL_API int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf, /* CMS/PKCS#7 EnvelopedData */ WOLFSSL_API int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, - word32 certSz); + word32 certSz, int options); WOLFSSL_API int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, int keyWrapOID, int keyAgreeOID, byte* ukm, - word32 ukmSz); + word32 ukmSz, int options); WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz); WOLFSSL_API int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, @@ -254,18 +254,19 @@ WOLFSSL_API int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* keyID, word32 keyIdSz, void* timePtr, byte* otherOID, word32 otherOIDSz, byte* other, - word32 otherSz); + word32 otherSz, int options); WOLFSSL_API int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen); WOLFSSL_API int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, byte* salt, word32 saltSz, int kdfOID, int prfOID, int iterations, - int encryptOID); + int encryptOID, int options); WOLFSSL_API int wc_PKCS7_SetOriEncryptCtx(PKCS7* pkcs7, void* ctx); WOLFSSL_API int wc_PKCS7_SetOriDecryptCtx(PKCS7* pkcs7, void* ctx); WOLFSSL_API int wc_PKCS7_SetOriDecryptCb(PKCS7* pkcs7, CallbackOriDecrypt cb); -WOLFSSL_API int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt cb); +WOLFSSL_API int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt cb, + int options); WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz); From a4da14f4b0a5f1b8fd967cb7d017b4cddf0ab98d Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 19 Sep 2018 10:37:11 -0600 Subject: [PATCH 19/56] allow CMS CompressedData to be disabled with NO_PKCS7_COMPRESSED_DATA --- wolfcrypt/src/pkcs7.c | 8 ++++---- wolfcrypt/test/test.c | 6 +++--- wolfssl/wolfcrypt/pkcs7.h | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 808e2c0b2..401985e9e 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -86,7 +86,7 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) /* FirmwarePkgData (1.2.840.113549.1.9.16.1.16), RFC 4108 */ const byte firmwarePkgData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x10 }; -#ifdef HAVE_LIBZ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) /* id-ct-compressedData (1.2.840.113549.1.9.16.1.9), RFC 3274 */ const byte compressedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x09 }; @@ -141,7 +141,7 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) typeName = encryptedData; break; #endif -#ifdef HAVE_LIBZ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) case COMPRESSED_DATA: typeSz = sizeof(compressedData); typeName = compressedData; @@ -7321,7 +7321,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, #endif /* NO_PKCS7_ENCRYPTED_DATA */ -#ifdef HAVE_LIBZ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) /* build PKCS#7 compressedData content type, return encrypted size */ int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz) @@ -7572,7 +7572,7 @@ int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, return decompressedSz; } -#endif /* HAVE_LIBZ */ +#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ #else /* HAVE_PKCS7 */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 2fcee72d3..c232b0db0 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -326,7 +326,7 @@ int scrypt_test(void); #ifndef NO_PKCS7_ENCRYPTED_DATA int pkcs7encrypted_test(void); #endif - #ifdef HAVE_LIBZ + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) int pkcs7compressed_test(void); #endif #endif @@ -967,7 +967,7 @@ initDefaultName(); else printf( "PKCS7encrypted test passed!\n"); #endif - #ifdef HAVE_LIBZ + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) if ( (ret = pkcs7compressed_test()) != 0) return err_sys("PKCS7compressed test failed!\n", ret); else @@ -19750,7 +19750,7 @@ int pkcs7encrypted_test(void) #endif /* NO_PKCS7_ENCRYPTED_DATA */ -#ifdef HAVE_LIBZ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) typedef struct { const byte* content; diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 6d1cbe472..8685565da 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -67,7 +67,7 @@ enum PKCS7_TYPES { SIGNED_AND_ENVELOPED_DATA = 654, /* 1.2.840.113549.1.7.4 */ DIGESTED_DATA = 655, /* 1.2.840.113549.1.7.5 */ ENCRYPTED_DATA = 656, /* 1.2.840.113549.1.7.6 */ -#ifdef HAVE_LIBZ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) COMPRESSED_DATA = 678, /* 1.2.840.113549.1.9.16.1.9, RFC 3274 */ #endif FIRMWARE_PKG_DATA = 685 /* 1.2.840.113549.1.9.16.1.16, RFC 4108 */ @@ -284,13 +284,13 @@ WOLFSSL_API int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, #endif /* NO_PKCS7_ENCRYPTED_DATA */ /* CMS/PKCS#7 CompressedData */ -#ifdef HAVE_LIBZ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) WOLFSSL_API int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz); WOLFSSL_API int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz); -#endif /* HAVE_LIBZ */ +#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ #ifdef __cplusplus } /* extern "C" */ From bc94cdc11b54ba2fc543ff063c79caa0cad67459 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 21 Sep 2018 15:35:41 -0600 Subject: [PATCH 20/56] add CMS AuthEnvelopedData content type support --- .gitignore | 12 + Makefile.am | 12 + wolfcrypt/src/asn.c | 62 +++ wolfcrypt/src/pkcs7.c | 797 +++++++++++++++++++++++++++++++++++--- wolfcrypt/test/test.c | 522 ++++++++++++++++++++++++- wolfssl/wolfcrypt/asn.h | 6 + wolfssl/wolfcrypt/pkcs7.h | 16 +- 7 files changed, 1362 insertions(+), 65 deletions(-) diff --git a/.gitignore b/.gitignore index 570a4406c..58f4aa6ff 100644 --- a/.gitignore +++ b/.gitignore @@ -101,6 +101,18 @@ ecc-key.pem certreq.der certreq.pem pkcs7cert.der +pkcs7authEnvelopedDataAES128GCM.der +pkcs7authEnvelopedDataAES128GCM_ECDH_SHA1KDF.der +pkcs7authEnvelopedDataAES128GCM_KEKRI.der +pkcs7authEnvelopedDataAES128GCM_ORI.der +pkcs7authEnvelopedDataAES128GCM_PWRI.der +pkcs7authEnvelopedDataAES192GCM.der +pkcs7authEnvelopedDataAES256GCM.der +pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der +pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der +pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der +pkcs7authEnvelopedDataAES256GCM_IANDS.der +pkcs7authEnvelopedDataAES256GCM_SKID.der pkcs7compressedData_data_zlib.der pkcs7compressedData_firmwarePkgData_zlib.der pkcs7encryptedDataAES128CBC.der diff --git a/Makefile.am b/Makefile.am index 08a60d8b8..85d8f76e0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -39,6 +39,18 @@ CLEANFILES+= cert.der \ othercert.der \ othercert.pem \ pkcs7cert.der \ + pkcs7authEnvelopedDataAES128GCM.der \ + pkcs7authEnvelopedDataAES128GCM_ECDH_SHA1KDF.der \ + pkcs7authEnvelopedDataAES128GCM_KEKRI.der \ + pkcs7authEnvelopedDataAES128GCM_ORI.der \ + pkcs7authEnvelopedDataAES128GCM_PWRI.der \ + pkcs7authEnvelopedDataAES192GCM.der \ + pkcs7authEnvelopedDataAES256GCM.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der \ + pkcs7authEnvelopedDataAES256GCM_IANDS.der \ + pkcs7authEnvelopedDataAES256GCM_SKID.der \ pkcs7compressedData_data_zlib.der \ pkcs7compressedData_firmwarePkgData_zlib.der \ pkcs7encryptedDataAES128CBC.der \ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 1ab2059d3..3caa915d2 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -1226,6 +1226,28 @@ static word32 SetBitString16Bit(word16 val, byte* output) static const byte blkAes256CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 42}; #endif #endif /* HAVE_AES_CBC */ +#ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + static const byte blkAes128GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 6}; + #endif + #ifdef WOLFSSL_AES_192 + static const byte blkAes192GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 26}; + #endif + #ifdef WOLFSSL_AES_256 + static const byte blkAes256GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 46}; + #endif +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + static const byte blkAes128CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 7}; + #endif + #ifdef WOLFSSL_AES_192 + static const byte blkAes192CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 27}; + #endif + #ifdef WOLFSSL_AES_256 + static const byte blkAes256CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 47}; + #endif +#endif /* HAVE_AESCCM */ #ifndef NO_DES3 static const byte blkDesCbcOid[] = {43, 14, 3, 2, 7}; @@ -1547,6 +1569,46 @@ const byte* OidFromId(word32 id, word32 type, word32* oidSz) break; #endif #endif /* HAVE_AES_CBC */ + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + oid = blkAes128GcmOid; + *oidSz = sizeof(blkAes128GcmOid); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + oid = blkAes192GcmOid; + *oidSz = sizeof(blkAes192GcmOid); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + oid = blkAes256GcmOid; + *oidSz = sizeof(blkAes256GcmOid); + break; + #endif + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + oid = blkAes128CcmOid; + *oidSz = sizeof(blkAes128CcmOid); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + oid = blkAes192CcmOid; + *oidSz = sizeof(blkAes192CcmOid); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + oid = blkAes256CcmOid; + *oidSz = sizeof(blkAes256CcmOid); + break; + #endif + #endif /* HAVE_AESCCM */ #ifndef NO_DES3 case DESb: oid = blkDesCbcOid; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 401985e9e..6c39920df 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -75,6 +75,8 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) 0x0D, 0x01, 0x07, 0x02}; const byte envelopedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x03 }; + const byte authEnvelopedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x10, 0x01, 0x17}; const byte signedAndEnveloped[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x04 }; const byte digestedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, @@ -125,6 +127,11 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) typeName = envelopedData; break; + case AUTH_ENVELOPED_DATA: + typeSz = sizeof(authEnvelopedData); + typeName = authEnvelopedData; + break; + case SIGNED_AND_ENVELOPED_DATA: typeSz = sizeof(signedAndEnveloped); typeName = signedAndEnveloped; @@ -204,12 +211,18 @@ static int wc_PKCS7_GetOIDBlockSize(int oid) #ifndef NO_AES #ifdef WOLFSSL_AES_128 case AES128CBCb: + case AES128GCMb: + case AES128CCMb: #endif #ifdef WOLFSSL_AES_192 case AES192CBCb: + case AES192GCMb: + case AES192CCMb: #endif #ifdef WOLFSSL_AES_256 case AES256CBCb: + case AES256GCMb: + case AES256CCMb: #endif blockSz = AES_BLOCK_SIZE; break; @@ -238,18 +251,24 @@ static int wc_PKCS7_GetOIDKeySize(int oid) #ifndef NO_AES #ifdef WOLFSSL_AES_128 case AES128CBCb: + case AES128GCMb: + case AES128CCMb: case AES128_WRAP: blockKeySz = 16; break; #endif #ifdef WOLFSSL_AES_192 case AES192CBCb: + case AES192GCMb: + case AES192CCMb: case AES192_WRAP: blockKeySz = 24; break; #endif #ifdef WOLFSSL_AES_256 case AES256CBCb: + case AES256GCMb: + case AES256CCMb: case AES256_WRAP: blockKeySz = 32; break; @@ -3805,8 +3824,14 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; XMEMSET(encryptedKey, 0, encryptedKeySz); + /* default to IssuerAndSerialNumber if not set */ + if (pkcs7->sidType != 0) { + sidType = pkcs7->sidType; + } else { + sidType = CMS_ISSUER_AND_SERIAL_NUMBER; + } + /* allow options to override SubjectIdentifier type if set */ - sidType = pkcs7->sidType; if (options & CMS_SKID) { sidType = CMS_SKID; } else if (options & CMS_ISSUER_AND_SERIAL_NUMBER) { @@ -3837,7 +3862,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return MEMORY_E; + return blockKeySz; } /* generate random content encryption key, if needed */ @@ -3850,7 +3875,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return MEMORY_E; + return ret; } InitDecodedCert(decoded, (byte*)cert, certSz, pkcs7->heap); @@ -3918,6 +3943,8 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, return PKCS7_RECIP_E; } + pkcs7->publicKeyOID = decoded->keyOID; + /* KeyEncryptionAlgorithmIdentifier, only support RSA now */ if (pkcs7->publicKeyOID != RSAk) { FreeDecodedCert(decoded); @@ -4130,8 +4157,9 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, /* encrypt content using encryptOID algo */ static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, - byte* iv, int ivSz, byte* in, int inSz, - byte* out) + byte* iv, int ivSz, byte* aad, word32 aadSz, + byte* authTag, word32 authTagSz, byte* in, + int inSz, byte* out) { int ret; #ifndef NO_AES @@ -4174,7 +4202,51 @@ static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, ret = wc_AesCbcEncrypt(&aes, out, in, inSz); break; -#endif + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + if (authTag == NULL) + return BAD_FUNC_ARG; + + ret = wc_AesGcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesGcmEncrypt(&aes, out, in, inSz, iv, ivSz, + authTag, authTagSz, aad, aadSz); + break; + #endif + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + if (authTag == NULL) + return BAD_FUNC_ARG; + + ret = wc_AesCcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesCcmEncrypt(&aes, out, in, inSz, iv, ivSz, + authTag, authTagSz, aad, aadSz); + break; + #endif + #endif /* HAVE_AESCCM */ +#endif /* NO_AES */ #ifndef NO_DES3 case DESb: if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE) @@ -4201,14 +4273,21 @@ static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, return ALGO_ID_E; }; +#if defined(NO_AES) || (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM)) + (void)authTag; + (void)authTagSz; + (void)aad; + (void)aadSz; +#endif return ret; } /* decrypt content using encryptOID algo */ static int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz, - byte* iv, int ivSz, byte* in, int inSz, - byte* out) + byte* iv, int ivSz, byte* aad, word32 aadSz, + byte* authTag, word32 authTagSz, byte* in, + int inSz, byte* out) { int ret; #ifndef NO_AES @@ -4251,7 +4330,51 @@ static int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz, ret = wc_AesCbcDecrypt(&aes, out, in, inSz); break; -#endif + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + if (authTag == NULL) + return BAD_FUNC_ARG; + + ret = wc_AesGcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesGcmDecrypt(&aes, out, in, inSz, iv, ivSz, + authTag, authTagSz, aad, aadSz); + break; + #endif + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + if (authTag == NULL) + return BAD_FUNC_ARG; + + ret = wc_AesCcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesCcmDecrypt(&aes, out, in, inSz, iv, ivSz, + authTag, authTagSz, aad, aadSz); + break; + #endif + #endif /* HAVE_AESCCM */ +#endif /* NO_AES */ #ifndef NO_DES3 case DESb: if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE) @@ -4277,17 +4400,26 @@ static int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz, return ALGO_ID_E; }; +#if defined(NO_AES) || (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM)) + (void)authTag; + (void)authTagSz; + (void)aad; + (void)aadSz; +#endif + return ret; } -/* generate random IV, place in iv, return 0 on success negative on error */ -static int wc_PKCS7_GenerateIV(PKCS7* pkcs7, WC_RNG* rng, byte* iv, word32 ivSz) +/* Generate random block, place in out, return 0 on success negative on error. + * Used for generation of IV, nonce, etc */ +static int wc_PKCS7_GenerateBlock(PKCS7* pkcs7, WC_RNG* rng, byte* out, + word32 outSz) { int ret; WC_RNG* rnd = NULL; - if (iv == NULL || ivSz == 0) + if (out == NULL || outSz == 0) return BAD_FUNC_ARG; /* input RNG is optional, init local one if input rng is NULL */ @@ -4306,7 +4438,7 @@ static int wc_PKCS7_GenerateIV(PKCS7* pkcs7, WC_RNG* rng, byte* iv, word32 ivSz) rnd = rng; } - ret = wc_RNG_GenerateBlock(rnd, iv, ivSz); + ret = wc_RNG_GenerateBlock(rnd, out, outSz); if (rng == NULL) { wc_FreeRng(rnd); @@ -4589,14 +4721,15 @@ static int wc_PKCS7_PwriKek_KeyWrap(PKCS7* pkcs7, const byte* kek, word32 kekSz, if (ret == 0) { /* encrypt, normal */ ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, (byte*)iv, - ivSz, out, outLen, out); + ivSz, NULL, 0, NULL, 0, out, outLen, out); } if (ret == 0) { /* encrypt again, using last ciphertext block as IV */ lastBlock = out + (((outLen / blockSz) - 1) * blockSz); ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, lastBlock, - blockSz, out, outLen, out); + blockSz, NULL, 0, NULL, 0, out, + outLen, out); } if (ret == 0) { @@ -4654,20 +4787,22 @@ static int wc_PKCS7_PwriKek_KeyUnWrap(PKCS7* pkcs7, const byte* kek, /* decrypt last block */ ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, tmpIv, blockSz, - lastBlock, blockSz, outTmp + inSz - blockSz); + NULL, 0, NULL, 0, lastBlock, blockSz, + outTmp + inSz - blockSz); if (ret == 0) { /* using last decrypted block as IV, decrypt [0 ... n-1] blocks */ lastBlock = outTmp + inSz - blockSz; ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, lastBlock, - blockSz, (byte*)in, inSz - blockSz, - outTmp); + blockSz, NULL, 0, NULL, 0, (byte*)in, + inSz - blockSz, outTmp); } if (ret == 0) { /* decrypt using original kek and iv */ ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, (byte*)iv, - ivSz, outTmp, inSz, outTmp); + ivSz, NULL, 0, NULL, 0, outTmp, inSz, + outTmp); } if (ret != 0) { @@ -4714,7 +4849,7 @@ static int wc_PKCS7_PwriKek_KeyUnWrap(PKCS7* pkcs7, const byte* kek, * Return 0 on success, negative upon error */ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, byte* salt, word32 saltSz, int kdfOID, - int hashOID, int iterations, int encryptOID, + int hashOID, int iterations, int kekEncryptOID, int options) { Pkcs7EncodedRecip* recip = NULL; @@ -4752,7 +4887,8 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, byte* encryptedKey = NULL; byte* kek = NULL; - int blockKeySz = 0, ret = 0; + int cekKeySz = 0, kekKeySz = 0, kekBlockSz = 0, ret = 0; + int encryptOID; word32 idx, totalSz = 0, encryptedKeySz; if (pkcs7 == NULL || passwd == NULL || pLen == 0 || @@ -4760,18 +4896,38 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, return BAD_FUNC_ARG; } + /* allow user to use different KEK encryption algorithm than used for + * main content encryption algorithm, if passed in */ + if (kekEncryptOID != 0) { + encryptOID = kekEncryptOID; + } else { + encryptOID = pkcs7->encryptOID; + } + /* get content-encryption key size, based on algorithm */ - blockKeySz = wc_PKCS7_GetOIDKeySize(encryptOID); - if (blockKeySz < 0) - return blockKeySz; + cekKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (cekKeySz < 0) + return cekKeySz; + + /* get KEK encryption key size, based on algorithm */ + if (encryptOID != pkcs7->encryptOID) { + kekKeySz = wc_PKCS7_GetOIDKeySize(encryptOID); + } else { + kekKeySz = cekKeySz; + } + + /* get KEK encryption block size */ + kekBlockSz = wc_PKCS7_GetOIDBlockSize(encryptOID); + if (kekBlockSz < 0) + return kekBlockSz; /* generate random CEK */ - ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, cekKeySz); if (ret < 0) return ret; /* generate random IV */ - ret = wc_PKCS7_GenerateIV(pkcs7, NULL, tmpIv, blockKeySz); + ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, kekBlockSz); if (ret != 0) return ret; @@ -4781,7 +4937,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, if (recip == NULL) return MEMORY_E; - kek = (byte*)XMALLOC(blockKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + kek = (byte*)XMALLOC(kekKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (kek == NULL) { XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return MEMORY_E; @@ -4797,13 +4953,13 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); - XMEMSET(kek, 0, blockKeySz); + XMEMSET(kek, 0, kekKeySz); XMEMSET(encryptedKey, 0, encryptedKeySz); /* generate KEK: expand password into KEK */ ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, passwd, pLen, salt, saltSz, kdfOID, hashOID, iterations, kek, - blockKeySz); + kekKeySz); if (ret < 0) { XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -4812,9 +4968,9 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, } /* generate encrypted key: encrypt CEK with KEK */ - ret = wc_PKCS7_PwriKek_KeyWrap(pkcs7, kek, blockKeySz, pkcs7->cek, + ret = wc_PKCS7_PwriKek_KeyWrap(pkcs7, kek, kekKeySz, pkcs7->cek, pkcs7->cekSz, encryptedKey, &encryptedKeySz, - tmpIv, blockKeySz, pkcs7->encryptOID); + tmpIv, kekBlockSz, encryptOID); if (ret < 0) { XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -4828,13 +4984,13 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, totalSz += (encKeyOctetStrSz + encryptedKeySz); /* put together IV OCTET STRING */ - ivOctetStringSz = SetOctetString(blockKeySz, ivOctetString); - totalSz += (ivOctetStringSz + blockKeySz); + ivOctetStringSz = SetOctetString(kekBlockSz, ivOctetString); + totalSz += (ivOctetStringSz + kekBlockSz); /* set PWRIAlgorithms AlgorithmIdentifier, adding (ivOctetStringSz + blockKeySz) for IV OCTET STRING */ - pwriEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, pwriEncAlgoId, - oidBlkType, ivOctetStringSz + blockKeySz); + pwriEncAlgoIdSz = SetAlgoID(encryptOID, pwriEncAlgoId, + oidBlkType, ivOctetStringSz + kekBlockSz); totalSz += pwriEncAlgoIdSz; /* set KeyEncryptionAlgorithms OID */ @@ -4850,7 +5006,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, /* KeyEncryptionAlgorithm SEQ */ keyEncAlgoIdSeqSz = SetSequence(keyEncAlgoIdSz + pwriEncAlgoIdSz + - ivOctetStringSz + blockKeySz, + ivOctetStringSz + kekBlockSz, keyEncAlgoIdSeq); totalSz += keyEncAlgoIdSeqSz; @@ -4925,14 +5081,14 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, idx += pwriEncAlgoIdSz; XMEMCPY(recip->recip + idx, ivOctetString, ivOctetStringSz); idx += ivOctetStringSz; - XMEMCPY(recip->recip + idx, tmpIv, blockKeySz); - idx += blockKeySz; + XMEMCPY(recip->recip + idx, tmpIv, kekBlockSz); + idx += kekBlockSz; XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); idx += encKeyOctetStrSz; XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); idx += encryptedKeySz; - ForceZero(kek, blockKeySz); + ForceZero(kek, kekBlockSz); ForceZero(encryptedKey, encryptedKeySz); XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -5282,7 +5438,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) return ret; /* generate IV for block cipher */ - ret = wc_PKCS7_GenerateIV(pkcs7, &rng, tmpIv, blockSz); + ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, tmpIv, blockSz); wc_FreeRng(&rng); if (ret != 0) return ret; @@ -5336,8 +5492,8 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) /* encrypt content */ ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek, - pkcs7->cekSz, tmpIv, blockSz, plain, encryptedOutSz, - encryptedContent); + pkcs7->cekSz, tmpIv, blockSz, NULL, 0, NULL, 0, plain, + encryptedOutSz, encryptedContent); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -6613,7 +6769,8 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, * * return size of RecipientInfo SET on success, negative upon error */ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* pkiMsg, - word32 pkiMsgSz, word32* idx) + word32 pkiMsgSz, word32* idx, + int type) { int version, length; word32 contentType; @@ -6621,6 +6778,9 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* pkiMsg, if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || idx == NULL) return BAD_FUNC_ARG; + if ((type != ENVELOPED_DATA) && (type != AUTH_ENVELOPED_DATA)) + return BAD_FUNC_ARG; + /* read past ContentInfo, verify type is envelopedData */ if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; @@ -6652,9 +6812,14 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* pkiMsg, if (wc_GetContentType(pkiMsg, idx, &contentType, pkiMsgSz) < 0) return ASN_PARSE_E; - if (contentType != ENVELOPED_DATA) { + if (type == ENVELOPED_DATA && contentType != ENVELOPED_DATA) { WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData"); return PKCS7_OID_E; + + } else if (type == AUTH_ENVELOPED_DATA && + contentType != AUTH_ENVELOPED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type AuthEnvelopedData"); + return PKCS7_OID_E; } if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) @@ -6670,14 +6835,22 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* pkiMsg, if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) return ASN_PARSE_E; - /* TODO :: make this more accurate */ - if ((pkcs7->publicKeyOID == RSAk && version != 0) - #ifdef HAVE_ECC - || (pkcs7->publicKeyOID == ECDSAk && version != 2) - #endif - ) { - WOLFSSL_MSG("PKCS#7 envelopedData needs to be of version 0"); - return ASN_VERSION_E; + if (type == ENVELOPED_DATA) { + /* TODO :: make this more accurate */ + if ((pkcs7->publicKeyOID == RSAk && version != 0) + #ifdef HAVE_ECC + || (pkcs7->publicKeyOID == ECDSAk && version != 2) + #endif + ) { + WOLFSSL_MSG("PKCS#7 envelopedData version incorrect"); + return ASN_VERSION_E; + } + } else { + /* AuthEnvelopedData version MUST be 0 */ + if (version != 0) { + WOLFSSL_MSG("PKCS#7 AuthEnvelopedData needs to be of version 0"); + return ASN_VERSION_E; + } } /* remove RecipientInfo set, get length of set */ @@ -6735,7 +6908,8 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, output == NULL || outputSz == 0) return BAD_FUNC_ARG; - length = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, &idx); + length = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, &idx, + ENVELOPED_DATA); if (length < 0) return length; @@ -6877,8 +7051,9 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, /* decrypt encryptedContent */ ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, - tmpIv, expBlockSz, encryptedContent, - encryptedContentSz, encryptedContent); + tmpIv, expBlockSz, NULL, 0, NULL, 0, + encryptedContent, encryptedContentSz, + encryptedContent); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #ifdef WOLFSSL_SMALL_STACK @@ -6904,6 +7079,508 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, } +/* build PKCS#7 authEnvelopedData content type, return enveloped size */ +int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, + word32 outputSz) +{ + int ret, idx = 0; + int totalSz, encryptedOutSz; + + 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]; + + WC_RNG rng; + int blockSz, blockKeySz; + byte* encryptedContent; + + Pkcs7EncodedRecip* tmpRecip = NULL; + int recipSz, recipSetSz; + byte recipSet[MAX_SET_SZ]; + + int encContentOctetSz, encContentSeqSz, contentTypeSz; + int contentEncAlgoSz, nonceOctetStringSz, macOctetStringSz; + byte encContentSeq[MAX_SEQ_SZ]; + byte contentType[MAX_ALGO_SZ]; + byte contentEncAlgo[MAX_ALGO_SZ]; + byte nonceOctetString[MAX_OCTET_STR_SZ]; + byte encContentOctet[MAX_OCTET_STR_SZ]; + byte macOctetString[MAX_OCTET_STR_SZ]; + + byte authTag[AES_BLOCK_SIZE]; + byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */ + byte macInt[MAX_VERSION_SZ]; + word32 nonceSz, macIntSz; + + if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0) + return BAD_FUNC_ARG; + + if (output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + + if (pkcs7->encryptOID != AES128GCMb && + pkcs7->encryptOID != AES192GCMb && + pkcs7->encryptOID != AES256GCMb && + pkcs7->encryptOID != AES128CCMb && + pkcs7->encryptOID != AES192CCMb && + pkcs7->encryptOID != AES256CCMb) { + WOLFSSL_MSG("CMS AuthEnvelopedData must use AES-GCM or AES-CCM"); + return BAD_FUNC_ARG; + } + + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) + return blockKeySz; + + blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); + if (blockKeySz < 0 || blockSz < 0) + return blockSz; + + /* outer content type */ + ret = wc_SetContentType(AUTH_ENVELOPED_DATA, outerContentType, + sizeof(outerContentType)); + if (ret < 0) + return ret; + + outerContentTypeSz = ret; + + /* version, defined as 0 in RFC 5083 */ + verSz = SetMyVersion(0, ver, 0); + + /* generate random content encryption key */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret != 0) { + return ret; + } + + /* build RecipientInfo, only if user manually set singleCert and size */ + if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) { + switch (pkcs7->publicKeyOID) { + #ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert, + pkcs7->singleCertSz, 0); + break; + #endif + #ifdef HAVE_ECC + case ECDSAk: + ret = wc_PKCS7_AddRecipient_KARI(pkcs7, pkcs7->singleCert, + pkcs7->singleCertSz, + pkcs7->keyWrapOID, + pkcs7->keyAgreeOID, pkcs7->ukm, + pkcs7->ukmSz, 0); + break; + #endif + + default: + WOLFSSL_MSG("Unsupported RecipientInfo public key type"); + return BAD_FUNC_ARG; + }; + + if (ret < 0) { + WOLFSSL_MSG("Failed to create RecipientInfo"); + return ret; + } + } + + recipSz = wc_PKCS7_GetRecipientListSize(pkcs7); + if (recipSz < 0) { + return ret; + + } else if (recipSz == 0) { + WOLFSSL_MSG("You must add at least one CMS recipient"); + return PKCS7_RECIP_E; + } + recipSetSz = SetSet(recipSz, recipSet); + + /* generate random nonce and IV for encryption */ + if (pkcs7->encryptOID == AES128GCMb || + pkcs7->encryptOID == AES192GCMb || + pkcs7->encryptOID == AES256GCMb) { + /* GCM nonce is GCM_NONCE_MID_SZ (12) */ + nonceSz = GCM_NONCE_MID_SZ; + } else { + /* CCM nonce is CCM_NONCE_MIN_SZ (7) */ + nonceSz = CCM_NONCE_MIN_SZ; + } + + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) + return ret; + + ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, nonce, nonceSz); + if (ret != 0) { + wc_FreeRng(&rng); + return ret; + } + + /* allocate encrypted content buffer */ + encryptedOutSz = pkcs7->contentSz; + + encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedContent == NULL) + 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); + + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* EncryptedContentInfo */ + ret = wc_SetContentType(pkcs7->contentOID, contentType, + sizeof(contentType)); + if (ret < 0) + return ret; + + contentTypeSz = ret; + + /* put together nonce OCTET STRING */ + nonceOctetStringSz = SetOctetString(nonceSz, nonceOctetString); + + /* put together aes-ICVlen INTEGER */ + macIntSz = SetMyVersion(sizeof(authTag), macInt, 0); + + /* build up our ContentEncryptionAlgorithmIdentifier sequence, + * adding (nonceOctetStringSz + blockSz + macIntSz) for nonce OCTET STRING + * and tag size */ + contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, + oidBlkType, nonceOctetStringSz + nonceSz + + macIntSz); + + if (contentEncAlgoSz == 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + + encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz, + encContentOctet); + + encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + + nonceOctetStringSz + nonceSz + macIntSz + + encContentOctetSz + encryptedOutSz, + encContentSeq); + + macOctetStringSz = SetOctetString(sizeof(authTag), macOctetString); + + /* keep track of sizes for outer wrapper layering */ + totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + + contentEncAlgoSz + nonceOctetStringSz + nonceSz + macIntSz + + encContentOctetSz + encryptedOutSz + macOctetStringSz + + sizeof(authTag); + + /* EnvelopedData */ + envDataSeqSz = SetSequence(totalSz, envDataSeq); + totalSz += envDataSeqSz; + + /* outer content */ + outerContentSz = SetExplicit(0, totalSz, outerContent); + totalSz += outerContentTypeSz; + totalSz += outerContentSz; + + /* ContentInfo */ + contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); + totalSz += contentInfoSeqSz; + + if (totalSz > (int)outputSz) { + WOLFSSL_MSG("Pkcs7_encrypt output buffer too small"); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + 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; + /* copy in recipients from list */ + tmpRecip = pkcs7->recipList; + while (tmpRecip != NULL) { + XMEMCPY(output + idx, tmpRecip->recip, tmpRecip->recipSz); + idx += tmpRecip->recipSz; + tmpRecip = tmpRecip->next; + } + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + XMEMCPY(output + idx, encContentSeq, encContentSeqSz); + idx += encContentSeqSz; + XMEMCPY(output + idx, contentType, contentTypeSz); + idx += contentTypeSz; + XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); + idx += contentEncAlgoSz; + XMEMCPY(output + idx, nonceOctetString, nonceOctetStringSz); + idx += nonceOctetStringSz; + XMEMCPY(output + idx, nonce, nonceSz); + idx += nonceSz; + XMEMCPY(output + idx, macInt, macIntSz); + idx += macIntSz; + XMEMCPY(output + idx, encContentOctet, encContentOctetSz); + idx += encContentOctetSz; + XMEMCPY(output + idx, encryptedContent, encryptedOutSz); + idx += encryptedOutSz; + XMEMCPY(output + idx, macOctetString, macOctetStringSz); + idx += macOctetStringSz; + XMEMCPY(output + idx, authTag, sizeof(authTag)); + idx += sizeof(authTag); + + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + return idx; +} + + +/* unwrap and decrypt PKCS#7 AuthEnvelopedData object, return decoded size */ +WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, + word32 pkiMsgSz, byte* output, + word32 outputSz) +{ + int recipFound = 0; + int ret, length; + word32 idx = 0; + word32 contentType, encOID; + word32 decryptedKeySz; + + int expBlockSz, blockKeySz; + byte authTag[AES_BLOCK_SIZE]; + byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */ + int nonceSz, authTagSz, macSz; + +#ifdef WOLFSSL_SMALL_STACK + byte* decryptedKey; +#else + byte decryptedKey[MAX_ENCRYPTED_KEY_SZ]; +#endif + int encryptedContentSz; + byte* encryptedContent = NULL; + int explicitOctet; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + if (pkiMsg == NULL || pkiMsgSz == 0 || + output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + + length = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, &idx, + AUTH_ENVELOPED_DATA); + if (length < 0) + return length; + +#ifdef WOLFSSL_SMALL_STACK + decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (decryptedKey == NULL) + return MEMORY_E; +#endif + decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + + ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, pkiMsg, pkiMsgSz, &idx, + decryptedKey, &decryptedKeySz, + &recipFound); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ret; + } + + if (recipFound == 0) { + WOLFSSL_MSG("No recipient found in envelopedData that matches input"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return PKCS7_RECIP_E; + } + + /* remove EncryptedContentInfo */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + + if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + + if (GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + + blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); + if (blockKeySz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return blockKeySz; + } + + expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); + if (expBlockSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return expBlockSz; + } + + /* get nonce, stored in OPTIONAL parameter of AlgoID */ + if (pkiMsg[idx++] != ASN_OCTET_STRING) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + + if (nonceSz > (int)sizeof(nonce)) { + WOLFSSL_MSG("AuthEnvelopedData nonce too large for buffer"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + + XMEMCPY(nonce, &pkiMsg[idx], nonceSz); + idx += nonceSz; + + /* get mac size, also stored in OPTIONAL parameter of AlgoID */ + if (GetMyVersion(pkiMsg, &idx, &macSz, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + + explicitOctet = pkiMsg[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); + + /* read encryptedContent, cont[0] */ + if (pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) && + pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + idx++; + + if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + + if (explicitOctet) { + if (pkiMsg[idx++] != ASN_OCTET_STRING) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + } + + encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedContent == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return MEMORY_E; + } + + XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); + idx += encryptedContentSz; + + /* get authTag OCTET STRING */ + if (pkiMsg[idx++] != ASN_OCTET_STRING) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, &idx, &authTagSz, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + + if (authTagSz > (int)sizeof(authTag)) { + WOLFSSL_MSG("AuthEnvelopedData authTag too large for buffer"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ASN_PARSE_E; + } + + XMEMCPY(authTag, &pkiMsg[idx], authTagSz); + idx += authTagSz; + + /* decrypt encryptedContent */ + ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, + nonce, nonceSz, NULL, 0, authTag, + authTagSz, encryptedContent, + encryptedContentSz, encryptedContent); + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + return ret; + } + + /* copy plaintext to output */ + XMEMCPY(output, encryptedContent, encryptedContentSz); + + /* free memory, zero out keys */ + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + + return encryptedContentSz; +} + + #ifndef NO_PKCS7_ENCRYPTED_DATA /* build PKCS#7 encryptedData content type, return encrypted size */ @@ -7016,7 +7693,7 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) } /* encrypt content */ - ret = wc_PKCS7_GenerateIV(pkcs7, NULL, tmpIv, blockSz); + ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, blockSz); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -7024,8 +7701,8 @@ int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) } ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->encryptionKey, - pkcs7->encryptionKeySz, tmpIv, blockSz, plain, encryptedOutSz, - encryptedContent); + pkcs7->encryptionKeySz, tmpIv, blockSz, NULL, 0, NULL, 0, + plain, encryptedOutSz, encryptedContent); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -7278,8 +7955,8 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, /* decrypt encryptedContent */ ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey, pkcs7->encryptionKeySz, tmpIv, expBlockSz, - encryptedContent, encryptedContentSz, - encryptedContent); + NULL, 0, NULL, 0, encryptedContent, + encryptedContentSz, encryptedContent); if (ret != 0) { XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index c232b0db0..d7f19cb4d 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -322,6 +322,7 @@ int scrypt_test(void); #endif #ifdef HAVE_PKCS7 int pkcs7enveloped_test(void); + int pkcs7authenveloped_test(void); int pkcs7signed_test(void); #ifndef NO_PKCS7_ENCRYPTED_DATA int pkcs7encrypted_test(void); @@ -956,6 +957,11 @@ initDefaultName(); else printf( "PKCS7enveloped test passed!\n"); + if ( (ret = pkcs7authenveloped_test()) != 0) + return err_sys("PKCS7authenveloped test failed!\n", ret); + else + printf( "PKCS7authenveloped test passed!\n"); + if ( (ret = pkcs7signed_test()) != 0) return err_sys("PKCS7signed test failed!\n", ret); else @@ -19512,6 +19518,519 @@ int pkcs7enveloped_test(void) } +typedef struct { + const byte* content; + word32 contentSz; + int contentOID; + int encryptOID; + int keyWrapOID; + int keyAgreeOID; + byte* cert; + size_t certSz; + byte* privateKey; + word32 privateKeySz; + PKCS7Attrib* signedAttribs; + word32 signedAttribsSz; + + /* KARI / KTRI specific */ + byte* optionalUkm; + word32 optionalUkmSz; + int ktriOptions; /* KTRI options flags */ + int kariOptions; /* KARI options flags */ + + /* KEKRI specific */ + byte* secretKey; /* key, only for kekri RecipientInfo types */ + word32 secretKeySz; /* size of secretKey, bytes */ + byte* secretKeyId; /* key identifier */ + word32 secretKeyIdSz; /* size of key identifier, bytes */ + void* timePtr; /* time_t pointer */ + byte* otherAttrOID; /* OPTIONAL, other attribute OID */ + word32 otherAttrOIDSz; /* size of otherAttrOID, bytes */ + byte* otherAttr; /* OPTIONAL, other attribute, ASN.1 encoded */ + word32 otherAttrSz; /* size of otherAttr, bytes */ + int kekriOptions; /* KEKRI options flags */ + + /* PWRI specific */ + char* password; /* password */ + word32 passwordSz; /* password size, bytes */ + byte* salt; /* KDF salt */ + word32 saltSz; /* KDF salt size, bytes */ + int kdfOID; /* KDF OID */ + int hashOID; /* KDF hash algorithm OID */ + int kdfIterations; /* KDF iterations */ + int kekEncryptOID; /* KEK encryption algorithm OID */ + int pwriOptions; /* PWRI options flags */ + + /* ORI specific */ + int isOri; + int oriOptions; /* ORI options flags */ + + const char* outFileName; +} pkcs7AuthEnvelopedVector; + + +static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, + byte* rsaPrivKey, word32 rsaPrivKeySz, + byte* eccCert, word32 eccCertSz, + byte* eccPrivKey, word32 eccPrivKeySz) +{ + int ret, testSz, i; + int envelopedSz, decodedSz; + + byte enveloped[2048]; + byte decoded[2048]; + PKCS7* pkcs7; +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + FILE* pkcs7File; +#endif + + const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 + }; + +#if !defined(NO_AES) && defined(WOLFSSL_AES_256) && defined(HAVE_ECC) && \ + defined(WOLFSSL_SHA512) + byte optionalUkm[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + }; +#endif /* NO_AES */ + +#if !defined(NO_AES) && !defined(NO_SHA) && defined(WOLFSSL_AES_128) + /* encryption key for kekri recipient types */ + byte secretKey[] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 + }; + + /* encryption key identifier */ + byte secretKeyId[] = { + 0x02,0x02,0x03,0x04 + }; +#endif + +#if !defined(NO_PWDBASED) + char password[] = "password"; + + byte salt[] = { + 0x12, 0x34, 0x56, 0x78, 0x78, 0x56, 0x34, 0x12 + }; +#endif + + const pkcs7AuthEnvelopedVector testVectors[] = + { + /* key transport key encryption technique */ +#ifndef NO_RSA + #if !defined(NO_AES) && defined(HAVE_AESGCM) + #ifdef WOLFSSL_AES_128 + {data, (word32)sizeof(data), DATA, AES128GCMb, 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, + "pkcs7authEnvelopedDataAES128GCM.der"}, + #endif + #ifdef WOLFSSL_AES_192 + {data, (word32)sizeof(data), DATA, AES192GCMb, 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, + "pkcs7authEnvelopedDataAES192GCM.der"}, + #endif + #ifdef WOLFSSL_AES_256 + {data, (word32)sizeof(data), 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.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, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, + 0, 0, "pkcs7authEnvelopedDataAES256GCM_SKID.der"}, + + /* explicitly using IssuerAndSerialNumber for SubjectKeyIdentifier */ + {data, (word32)sizeof(data), DATA, AES256GCMb, 0, 0, rsaCert, rsaCertSz, + rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, + CMS_ISSUER_AND_SERIAL_NUMBER, 0, NULL, 0, NULL, 0, NULL, NULL, 0, + NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, + "pkcs7authEnvelopedDataAES256GCM_IANDS.der"}, + #endif + #endif /* NO_AES */ +#endif + + /* key agreement key encryption technique*/ +#ifdef HAVE_ECC + #if !defined(NO_AES) && defined(HAVE_AESGCM) + #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) + {data, (word32)sizeof(data), DATA, AES128GCMb, AES128_WRAP, + dhSinglePass_stdDH_sha1kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, 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, + "pkcs7authEnvelopedDataAES128GCM_ECDH_SHA1KDF.der"}, + #endif + + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_256) + {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, 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_ECDH_SHA256KDF.der"}, + #endif /* NO_SHA256 && WOLFSSL_AES_256 */ + + #if defined(WOLFSSL_SHA512) && defined(WOLFSSL_AES_256) + {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, 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_ECDH_SHA512KDF.der"}, + + /* with optional user keying material (ukm) */ + {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, optionalUkm, sizeof(optionalUkm), 0, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, + 0, 0, "pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der"}, + #endif /* WOLFSSL_SHA512 && WOLFSSL_AES_256 */ + #endif /* NO_AES */ +#endif + + /* kekri (KEKRecipientInfo) recipient types */ +#if !defined(NO_AES) && defined(HAVE_AESGCM) + #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) + {data, (word32)sizeof(data), DATA, AES128GCMb, AES128_WRAP, 0, + NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, secretKey, sizeof(secretKey), + secretKeyId, sizeof(secretKeyId), NULL, NULL, 0, NULL, 0, + 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, + "pkcs7authEnvelopedDataAES128GCM_KEKRI.der"}, + #endif +#endif + + /* pwri (PasswordRecipientInfo) recipient types */ +#if !defined(NO_PWDBASED) && !defined(NO_AES) && defined(HAVE_AESGCM) + #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) + {data, (word32)sizeof(data), DATA, AES128GCMb, 0, 0, + NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, + NULL, 0, NULL, NULL, 0, NULL, 0, 0, password, + (word32)XSTRLEN(password), salt, sizeof(salt), PBKDF2_OID, WC_SHA, 5, + AES128CBCb, 0, 0, 0, "pkcs7authEnvelopedDataAES128GCM_PWRI.der"}, + #endif +#endif + +#if !defined(NO_AES) && defined(HAVE_AESGCM) + #ifdef WOLFSSL_AES_128 + /* ori (OtherRecipientInfo) recipient types */ + {data, (word32)sizeof(data), DATA, AES128GCMb, 0, 0, NULL, 0, NULL, 0, + 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, 1, 0, + "pkcs7authEnvelopedDataAES128GCM_ORI.der"}, + #endif +#endif + }; + + testSz = sizeof(testVectors) / sizeof(pkcs7AuthEnvelopedVector); + + for (i = 0; i < testSz; i++) { + pkcs7 = wc_PKCS7_New(HEAP_HINT, + #ifdef WOLFSSL_ASYNC_CRYPT + INVALID_DEVID /* async PKCS7 is not supported */ + #else + devId + #endif + ); + if (pkcs7 == NULL) + return -9214; + + if (testVectors[i].secretKey != NULL) { + /* KEKRI recipient type */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -9215; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + + ret = wc_PKCS7_AddRecipient_KEKRI(pkcs7, testVectors[i].keyWrapOID, + testVectors[i].secretKey, testVectors[i].secretKeySz, + testVectors[i].secretKeyId, testVectors[i].secretKeyIdSz, + testVectors[i].timePtr, testVectors[i].otherAttrOID, + testVectors[i].otherAttrOIDSz, testVectors[i].otherAttr, + testVectors[i].otherAttrSz, testVectors[i].kekriOptions); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -9216; + } + + /* set key, for decryption */ + ret = wc_PKCS7_SetKey(pkcs7, testVectors[i].secretKey, + testVectors[i].secretKeySz); + + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -9217; + } + + } else if (testVectors[i].password != NULL) { + /* PWRI recipient type */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -9218; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + + ret = wc_PKCS7_AddRecipient_PWRI(pkcs7, + (byte*)testVectors[i].password, + testVectors[i].passwordSz, testVectors[i].salt, + testVectors[i].saltSz, testVectors[i].kdfOID, + testVectors[i].hashOID, testVectors[i].kdfIterations, + testVectors[i].kekEncryptOID, testVectors[i].pwriOptions); + + if (ret < 0) { + printf("CHRIS: ret = %d\n", ret); + wc_PKCS7_Free(pkcs7); + return -9219; + } + + /* set password, for decryption */ + ret = wc_PKCS7_SetPassword(pkcs7, (byte*)testVectors[i].password, + testVectors[i].passwordSz); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -9220; + } + + } else if (testVectors[i].isOri == 1) { + /* ORI recipient type */ + + ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + return -9221; + } + + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + + ret = wc_PKCS7_AddRecipient_ORI(pkcs7, myOriEncryptCb, + testVectors[i].oriOptions); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -9222; + } + + /* set decrypt callback for decryption */ + ret = wc_PKCS7_SetOriDecryptCb(pkcs7, myOriDecryptCb); + + if (ret < 0) { + wc_PKCS7_Free(pkcs7); + return -9223; + } + + } else { + /* KTRI or KARI recipient types */ + + ret = wc_PKCS7_InitWithCert(pkcs7, testVectors[i].cert, + (word32)testVectors[i].certSz); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -9224; + } + + pkcs7->keyWrapOID = testVectors[i].keyWrapOID; + pkcs7->keyAgreeOID = testVectors[i].keyAgreeOID; + pkcs7->privateKey = testVectors[i].privateKey; + pkcs7->privateKeySz = testVectors[i].privateKeySz; + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + + /* set SubjectIdentifier type for KTRI types */ + if (testVectors[i].ktriOptions & CMS_SKID) { + + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -9225; + } + } else if (testVectors[i].ktriOptions & + CMS_ISSUER_AND_SERIAL_NUMBER) { + + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, + CMS_ISSUER_AND_SERIAL_NUMBER); + if (ret != 0) { + wc_PKCS7_Free(pkcs7); + return -9225; + } + } + } + + /* encode envelopedData */ + envelopedSz = wc_PKCS7_EncodeAuthEnvelopedData(pkcs7, enveloped, + sizeof(enveloped)); + if (envelopedSz <= 0) { + wc_PKCS7_Free(pkcs7); + return -9226; + } + + /* decode envelopedData */ + decodedSz = wc_PKCS7_DecodeAuthEnvelopedData(pkcs7, enveloped, + envelopedSz, decoded, + sizeof(decoded)); + if (decodedSz <= 0) { + wc_PKCS7_Free(pkcs7); + return -9226; + } + + /* test decode result */ + if (XMEMCMP(decoded, data, sizeof(data)) != 0){ + wc_PKCS7_Free(pkcs7); + return -9227; + } + +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* output pkcs7 envelopedData for external testing */ + pkcs7File = fopen(testVectors[i].outFileName, "wb"); + if (!pkcs7File) { + wc_PKCS7_Free(pkcs7); + return -9228; + } + + ret = (int)fwrite(enveloped, 1, envelopedSz, pkcs7File); + fclose(pkcs7File); + if (ret != envelopedSz) { + wc_PKCS7_Free(pkcs7); + return -9229; + } +#endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + + wc_PKCS7_Free(pkcs7); + pkcs7 = NULL; + } + +#if !defined(HAVE_ECC) || defined(NO_AES) + (void)eccCert; + (void)eccCertSz; + (void)eccPrivKey; + (void)eccPrivKeySz; + (void)secretKey; + (void)secretKeyId; +#endif +#ifdef NO_RSA + (void)rsaCert; + (void)rsaCertSz; + (void)rsaPrivKey; + (void)rsaPrivKeySz; +#endif + return 0; +} + + +int pkcs7authenveloped_test(void) +{ + int ret = 0; + + byte* rsaCert = NULL; + byte* rsaPrivKey = NULL; + word32 rsaCertSz = 0; + word32 rsaPrivKeySz = 0; + + byte* eccCert = NULL; + byte* eccPrivKey = NULL; + word32 eccCertSz = 0; + word32 eccPrivKeySz = 0; + +#ifndef NO_RSA + /* read client RSA cert and key in DER format */ + rsaCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (rsaCert == NULL) + return -9300; + + rsaPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (rsaPrivKey == NULL) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -9301; + } + + rsaCertSz = FOURK_BUF; + rsaPrivKeySz = FOURK_BUF; +#endif /* NO_RSA */ + +#ifdef HAVE_ECC + /* read client ECC cert and key in DER format */ + eccCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (eccCert == NULL) { + #ifndef NO_RSA + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return -9302; + } + + eccPrivKey =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (eccPrivKey == NULL) { + #ifndef NO_RSA + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + #endif + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -9303; + } + + eccCertSz = FOURK_BUF; + eccPrivKeySz = FOURK_BUF; +#endif /* HAVE_ECC */ + + ret = pkcs7_load_certs_keys(rsaCert, &rsaCertSz, rsaPrivKey, + &rsaPrivKeySz, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, eccCert, &eccCertSz, + eccPrivKey, &eccPrivKeySz); + if (ret < 0) { + #ifndef NO_RSA + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + #endif + #ifdef HAVE_ECC + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + ret = pkcs7authenveloped_run_vectors(rsaCert, (word32)rsaCertSz, + rsaPrivKey, (word32)rsaPrivKeySz, + eccCert, (word32)eccCertSz, + eccPrivKey, (word32)eccPrivKeySz); + +#ifndef NO_RSA + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#endif +#ifdef HAVE_ECC + XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + #ifndef NO_PKCS7_ENCRYPTED_DATA typedef struct { @@ -20119,9 +20638,9 @@ static int pkcs7signed_run_vectors( pkcs7->rng = &rng; pkcs7->content = (byte*)testVectors[i].content; pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; pkcs7->hashOID = testVectors[i].hashOID; pkcs7->encryptOID = testVectors[i].encryptOID; - pkcs7->contentOID = testVectors[i].contentOID; pkcs7->privateKey = testVectors[i].privateKey; pkcs7->privateKeySz = testVectors[i].privateKeySz; pkcs7->signedAttribs = testVectors[i].signedAttribs; @@ -20252,7 +20771,6 @@ static int pkcs7signed_run_vectors( } } - if (pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 20c986dcf..2c7064a1a 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -353,12 +353,18 @@ enum Hash_Sum { enum Block_Sum { #ifdef WOLFSSL_AES_128 AES128CBCb = 414, + AES128GCMb = 418, + AES128CCMb = 419, #endif #ifdef WOLFSSL_AES_192 AES192CBCb = 434, + AES192GCMb = 438, + AES192CCMb = 439, #endif #ifdef WOLFSSL_AES_256 AES256CBCb = 454, + AES256GCMb = 458, + AES256CCMb = 459, #endif #ifndef NO_DES3 DESb = 69, diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 8685565da..49a413d7b 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -70,7 +70,8 @@ enum PKCS7_TYPES { #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) COMPRESSED_DATA = 678, /* 1.2.840.113549.1.9.16.1.9, RFC 3274 */ #endif - FIRMWARE_PKG_DATA = 685 /* 1.2.840.113549.1.9.16.1.16, RFC 4108 */ + FIRMWARE_PKG_DATA = 685, /* 1.2.840.113549.1.9.16.1.16, RFC 4108 */ + AUTH_ENVELOPED_DATA = 692 /* 1.2.840.113549.1.9.16.1.23, RFC 5083 */ }; enum Pkcs7_Misc { @@ -197,6 +198,7 @@ typedef struct PKCS7 { word32 cekSz; /* size of cek, bytes */ byte* pass; /* password, for PWRI decryption */ word32 passSz; /* size of pass, bytes */ + int kekEncryptOID; /* KEK encryption algorithm OID */ CallbackOriEncrypt oriEncryptCb; /* ORI encrypt callback */ CallbackOriDecrypt oriDecryptCb; /* ORI decrypt callback */ @@ -240,7 +242,7 @@ WOLFSSL_API int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf, word32 hashSz, byte* pkiMsgHead, word32 pkiMsgHeadSz, byte* pkiMsgFoot, word32 pkiMsgFootSz); -/* CMS/PKCS#7 EnvelopedData */ +/* EnvelopedData and AuthEnvelopedData RecipientInfo functions */ WOLFSSL_API int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, int options); WOLFSSL_API int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, @@ -261,19 +263,27 @@ WOLFSSL_API int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, byte* salt, word32 saltSz, int kdfOID, int prfOID, int iterations, - int encryptOID, int options); + int kekEncryptOID, int options); WOLFSSL_API int wc_PKCS7_SetOriEncryptCtx(PKCS7* pkcs7, void* ctx); WOLFSSL_API int wc_PKCS7_SetOriDecryptCtx(PKCS7* pkcs7, void* ctx); WOLFSSL_API int wc_PKCS7_SetOriDecryptCb(PKCS7* pkcs7, CallbackOriDecrypt cb); WOLFSSL_API int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt cb, int options); +/* CMS/PKCS#7 EnvelopedData */ WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz); WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* output, word32 outputSz); +/* CMS/PKCS#7 AuthEnvelopedData */ +WOLFSSL_API int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, + byte* output, word32 outputSz); +WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, + word32 pkiMsgSz, byte* output, + word32 outputSz); + /* CMS/PKCS#7 EncryptedData */ #ifndef NO_PKCS7_ENCRYPTED_DATA WOLFSSL_API int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, From 06a6f8400b6ded8386746725b4ee34bea8648909 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 21 Sep 2018 17:13:33 -0600 Subject: [PATCH 21/56] add CMS AuthEnvelopedData support for authAttrs --- .gitignore | 1 + Makefile.am | 1 + tests/api.c | 9 +- wolfcrypt/src/pkcs7.c | 180 +++++++++++++++++++++++++++++++++++--- wolfcrypt/test/test.c | 7 +- wolfssl/wolfcrypt/pkcs7.h | 7 ++ 6 files changed, 190 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 58f4aa6ff..538acaa5b 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/Makefile.am b/Makefile.am index 85d8f76e0..6213db8f5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/tests/api.c b/tests/api.c index d3f0ad366..e87552e66 100644 --- a/tests/api.c +++ b/tests/api.c @@ -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 */ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 6c39920df..5148e81b1 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -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); diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index d7f19cb4d..2c007286a 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -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; } diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 49a413d7b..9f2d19fff 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -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; From 431538405181048dbf7a85d0493bd5a555390323 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Mon, 24 Sep 2018 10:05:36 -0600 Subject: [PATCH 22/56] update test.c error returns for PKCS7 --- wolfcrypt/test/test.c | 144 +++++++++++++++++++++--------------------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 2c007286a..5b62589d7 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19225,14 +19225,14 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #endif ); if (pkcs7 == NULL) - return -9214; + return -9310; if (testVectors[i].secretKey != NULL) { /* KEKRI recipient type */ ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); if (ret != 0) { - return -9215; + return -9311; } pkcs7->content = (byte*)testVectors[i].content; @@ -19251,7 +19251,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9216; + return -9313; } /* set key, for decryption */ @@ -19260,7 +19260,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9217; + return -9314; } } else if (testVectors[i].password != NULL) { @@ -19268,7 +19268,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); if (ret != 0) { - return -9218; + return -9315; } pkcs7->content = (byte*)testVectors[i].content; @@ -19287,7 +19287,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9219; + return -9316; } /* set password, for decryption */ @@ -19296,7 +19296,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9220; + return -9317; } } else if (testVectors[i].isOri == 1) { @@ -19304,7 +19304,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); if (ret != 0) { - return -9221; + return -9318; } pkcs7->content = (byte*)testVectors[i].content; @@ -19317,7 +19317,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9222; + return -9319; } /* set decrypt callback for decryption */ @@ -19325,7 +19325,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9223; + return -9320; } } else { @@ -19335,7 +19335,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, (word32)testVectors[i].certSz); if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9224; + return -9321; } pkcs7->keyWrapOID = testVectors[i].keyWrapOID; @@ -19355,7 +19355,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9225; + return -9322; } } else if (testVectors[i].ktriOptions & CMS_ISSUER_AND_SERIAL_NUMBER) { @@ -19364,7 +19364,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, CMS_ISSUER_AND_SERIAL_NUMBER); if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9225; + return -9323; } } } @@ -19374,7 +19374,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, sizeof(enveloped)); if (envelopedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9225; + return -9324; } /* decode envelopedData */ @@ -19382,13 +19382,13 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, decoded, sizeof(decoded)); if (decodedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9226; + return -9325; } /* test decode result */ if (XMEMCMP(decoded, data, sizeof(data)) != 0){ wc_PKCS7_Free(pkcs7); - return -9227; + return -9326; } #ifdef PKCS7_OUTPUT_TEST_BUNDLES @@ -19396,14 +19396,14 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7File = fopen(testVectors[i].outFileName, "wb"); if (!pkcs7File) { wc_PKCS7_Free(pkcs7); - return -9228; + return -9327; } ret = (int)fwrite(enveloped, 1, envelopedSz, pkcs7File); fclose(pkcs7File); if (ret != envelopedSz) { wc_PKCS7_Free(pkcs7); - return -9229; + return -9328; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ @@ -19497,7 +19497,7 @@ int pkcs7enveloped_test(void) XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif - return ret; + return -9304; } ret = pkcs7enveloped_run_vectors(rsaCert, (word32)rsaCertSz, @@ -19742,14 +19742,14 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #endif ); if (pkcs7 == NULL) - return -9214; + return -9370; if (testVectors[i].secretKey != NULL) { /* KEKRI recipient type */ ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); if (ret != 0) { - return -9215; + return -9371; } pkcs7->content = (byte*)testVectors[i].content; @@ -19768,7 +19768,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9216; + return -9372; } /* set key, for decryption */ @@ -19777,7 +19777,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9217; + return -9373; } } else if (testVectors[i].password != NULL) { @@ -19785,7 +19785,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); if (ret != 0) { - return -9218; + return -9374; } pkcs7->content = (byte*)testVectors[i].content; @@ -19804,7 +19804,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9219; + return -9375; } /* set password, for decryption */ @@ -19813,7 +19813,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9220; + return -9376; } } else if (testVectors[i].isOri == 1) { @@ -19821,7 +19821,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); if (ret != 0) { - return -9221; + return -9377; } pkcs7->content = (byte*)testVectors[i].content; @@ -19834,7 +19834,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9222; + return -9378; } /* set decrypt callback for decryption */ @@ -19842,7 +19842,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9223; + return -9379; } } else { @@ -19852,7 +19852,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, (word32)testVectors[i].certSz); if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9224; + return -9380; } pkcs7->keyWrapOID = testVectors[i].keyWrapOID; @@ -19872,7 +19872,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9225; + return -9381; } } else if (testVectors[i].ktriOptions & CMS_ISSUER_AND_SERIAL_NUMBER) { @@ -19881,7 +19881,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, CMS_ISSUER_AND_SERIAL_NUMBER); if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9225; + return -9382; } } } @@ -19891,7 +19891,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, sizeof(enveloped)); if (envelopedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9226; + return -9383; } /* decode envelopedData */ @@ -19900,13 +19900,13 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, sizeof(decoded)); if (decodedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9226; + return -9384; } /* test decode result */ if (XMEMCMP(decoded, data, sizeof(data)) != 0){ wc_PKCS7_Free(pkcs7); - return -9227; + return -9385; } #ifdef PKCS7_OUTPUT_TEST_BUNDLES @@ -19914,14 +19914,14 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7File = fopen(testVectors[i].outFileName, "wb"); if (!pkcs7File) { wc_PKCS7_Free(pkcs7); - return -9228; + return -9386; } ret = (int)fwrite(enveloped, 1, envelopedSz, pkcs7File); fclose(pkcs7File); if (ret != envelopedSz) { wc_PKCS7_Free(pkcs7); - return -9229; + return -9387; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ @@ -19965,12 +19965,12 @@ int pkcs7authenveloped_test(void) /* read client RSA cert and key in DER format */ rsaCert = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (rsaCert == NULL) - return -9300; + return -9360; rsaPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (rsaPrivKey == NULL) { XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -9301; + return -9361; } rsaCertSz = FOURK_BUF; @@ -19985,7 +19985,7 @@ int pkcs7authenveloped_test(void) XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif - return -9302; + return -9362; } eccPrivKey =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); @@ -19995,7 +19995,7 @@ int pkcs7authenveloped_test(void) XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -9303; + return -9363; } eccCertSz = FOURK_BUF; @@ -20015,7 +20015,7 @@ int pkcs7authenveloped_test(void) XFREE(eccCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(eccPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); #endif - return ret; + return -9364; } ret = pkcs7authenveloped_run_vectors(rsaCert, (word32)rsaCertSz, @@ -20314,7 +20314,7 @@ int pkcs7compressed_test(void) for (i = 0; i < testSz; i++) { pkcs7 = wc_PKCS7_New(HEAP_HINT, devId); if (pkcs7 == NULL) - return -9400; + return -9450; pkcs7->content = (byte*)testVectors[i].content; pkcs7->contentSz = testVectors[i].contentSz; @@ -20325,7 +20325,7 @@ int pkcs7compressed_test(void) sizeof(compressed)); if (compressedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9408; + return -9451; } /* decode compressedData */ @@ -20334,26 +20334,26 @@ int pkcs7compressed_test(void) sizeof(decoded)); if (decodedSz <= 0){ wc_PKCS7_Free(pkcs7); - return -9409; + return -9452; } /* test decode result */ if (XMEMCMP(decoded, testVectors[i].content, testVectors[i].contentSz) != 0) { wc_PKCS7_Free(pkcs7); - return -9410; + return -9453; } /* make sure content type is the same */ if (testVectors[i].contentOID != pkcs7->contentOID) - return -9411; + return -9454; #ifdef PKCS7_OUTPUT_TEST_BUNDLES /* output pkcs7 compressedData for external testing */ pkcs7File = fopen(testVectors[i].outFileName, "wb"); if (!pkcs7File) { wc_PKCS7_Free(pkcs7); - return -9412; + return -9455; } ret = (int)fwrite(compressed, compressedSz, 1, pkcs7File); @@ -20593,14 +20593,14 @@ static int pkcs7signed_run_vectors( outSz = FOURK_BUF; out = (byte*)XMALLOC(outSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (out == NULL) - return -9413; + return -9510; XMEMSET(out, 0, outSz); ret = wc_PKCS7_PadData((byte*)data, sizeof(data), out, outSz, 16); if (ret < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -9414; + return -9511; } #ifndef HAVE_FIPS @@ -20610,13 +20610,13 @@ static int pkcs7signed_run_vectors( #endif if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -9415; + return -9512; } for (i = 0; i < testSz; i++) { pkcs7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); if (pkcs7 == NULL) - return -9416; + return -9513; pkcs7->heap = HEAP_HINT; pkcs7->devId = INVALID_DEVID; @@ -20626,7 +20626,7 @@ static int pkcs7signed_run_vectors( if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9417; + return -9514; } /* load CA certificate, if present */ @@ -20636,7 +20636,7 @@ static int pkcs7signed_run_vectors( if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9418; + return -9515; } } @@ -20659,7 +20659,7 @@ static int pkcs7signed_run_vectors( if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9419; + return -9516; } } @@ -20670,7 +20670,7 @@ static int pkcs7signed_run_vectors( if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9420; + return -9517; } } @@ -20683,7 +20683,7 @@ static int pkcs7signed_run_vectors( if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9421; + return -9518; } } @@ -20706,7 +20706,7 @@ static int pkcs7signed_run_vectors( if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9422; + return -9519; } wc_ShaUpdate(&sha, pkcs7->publicKey, pkcs7->publicKeySz); wc_ShaFinal(&sha, digest); @@ -20716,7 +20716,7 @@ static int pkcs7signed_run_vectors( if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9423; + return -9520; } wc_Sha256Update(&sha, pkcs7->publicKey, pkcs7->publicKeySz); wc_Sha256Final(&sha, digest); @@ -20732,7 +20732,7 @@ static int pkcs7signed_run_vectors( if (encodedSz < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9424; + return -9521; } #ifdef PKCS7_OUTPUT_TEST_BUNDLES @@ -20741,14 +20741,14 @@ static int pkcs7signed_run_vectors( if (!file) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9425; + return -9522; } ret = (int)fwrite(out, 1, encodedSz, file); fclose(file); if (ret != (int)encodedSz) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9426; + return -9526; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ @@ -20756,30 +20756,30 @@ static int pkcs7signed_run_vectors( pkcs7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); if (pkcs7 == NULL) - return -9427; + return -9527; wc_PKCS7_InitWithCert(pkcs7, NULL, 0); ret = wc_PKCS7_VerifySignedData(pkcs7, out, outSz); if (ret < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9428; + return -9528; } /* verify contentType extracted successfully for custom content types */ if (testVectors[i].contentTypeSz > 0) { if (pkcs7->contentTypeSz != testVectors[i].contentTypeSz) { - return -9429; + return -9529; } else if (XMEMCMP(pkcs7->contentType, testVectors[i].contentType, pkcs7->contentTypeSz) != 0) { - return -9430; + return -9530; } } if (pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9431; + return -9531; } { @@ -20798,13 +20798,13 @@ static int pkcs7signed_run_vectors( NULL, (word32*)&bufSz) != LENGTH_ONLY_E) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9432; + return -9532; } if (bufSz > (int)sizeof(buf)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9433; + return -9533; } bufSz = wc_PKCS7_GetAttributeValue(pkcs7, oidPt, oidSz, @@ -20813,7 +20813,7 @@ static int pkcs7signed_run_vectors( (testVectors[i].signedAttribs == NULL && bufSz > 0)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9434; + return -9534; } } @@ -20822,7 +20822,7 @@ static int pkcs7signed_run_vectors( if (!file) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9435; + return -9535; } ret = (int)fwrite(pkcs7->singleCert, 1, pkcs7->singleCertSz, file); fclose(file); @@ -20978,7 +20978,7 @@ int pkcs7signed_test(void) XFREE(rsaClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(eccClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(eccClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return ret; + return -9508; } ret = pkcs7signed_run_vectors(rsaClientCertBuf, (word32)rsaClientCertBufSz, From 40ef246b1f6e4c3e80c538f8398b306044e633f5 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Mon, 24 Sep 2018 16:42:12 -0600 Subject: [PATCH 23/56] add CMS AuthEnvelopedData support for unauthAttrs --- .gitignore | 4 + Makefile.am | 4 + wolfcrypt/src/pkcs7.c | 117 +++++++++++++----- wolfcrypt/test/test.c | 247 ++++++++++++++++++++++++++------------ wolfssl/wolfcrypt/pkcs7.h | 10 ++ 5 files changed, 276 insertions(+), 106 deletions(-) diff --git a/.gitignore b/.gitignore index 538acaa5b..3f53b13af 100644 --- a/.gitignore +++ b/.gitignore @@ -109,6 +109,10 @@ pkcs7authEnvelopedDataAES128GCM_PWRI.der pkcs7authEnvelopedDataAES192GCM.der pkcs7authEnvelopedDataAES256GCM.der pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der +pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_authAttribs.der +pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_bothAttribs.der +pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_fw_bothAttribs.der +pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_unauthAttribs.der pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der pkcs7authEnvelopedDataAES256GCM_firmwarePkgData.der diff --git a/Makefile.am b/Makefile.am index 6213db8f5..1f3923e68 100644 --- a/Makefile.am +++ b/Makefile.am @@ -47,6 +47,10 @@ CLEANFILES+= cert.der \ pkcs7authEnvelopedDataAES192GCM.der \ pkcs7authEnvelopedDataAES256GCM.der \ pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_authAttribs.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_bothAttribs.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_fw_bothAttribs.der \ + pkcs7authEnvelopedDataAES256GCM_ECDH_SHA256KDF_unauthAttribs.der \ pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF.der \ pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der \ pkcs7authEnvelopedDataAES256GCM_firmwarePkgData.der \ diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 5148e81b1..92b2041fc 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -7119,15 +7119,25 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, byte macInt[MAX_VERSION_SZ]; word32 nonceSz, macIntSz; + /* authAttribs */ byte* flatAuthAttribs = NULL; - word32 flatAuthAttribsSz = 0; + byte authAttribSet[MAX_SET_SZ]; + EncodedAttrib authAttribs[MAX_AUTH_ATTRIBS_SZ]; + word32 authAttribsSz = 0, authAttribsCount = 0; + word32 authAttribsSetSz = 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; + word32 authAttribsAadSetSz = 0; + + /* unauthAttribs */ + byte* flatUnauthAttribs = NULL; + byte unauthAttribSet[MAX_SET_SZ]; + EncodedAttrib unauthAttribs[MAX_UNAUTH_ATTRIBS_SZ]; + word32 unauthAttribsSz = 0, unauthAttribsCount = 0; + word32 unauthAttribsSetSz = 0; + PKCS7Attrib contentTypeAttrib; byte contentTypeValue[MAX_OID_SZ]; @@ -7233,12 +7243,13 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, return ret; ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, nonce, nonceSz); + wc_FreeRng(&rng); if (ret != 0) { - wc_FreeRng(&rng); return ret; } - /* build up authenticated attributes (authAttrs) */ + + /* authAttribs: add contentType attrib if needed */ if (pkcs7->contentOID != DATA) { /* if type is not id-data, contentType attribute MUST be added */ @@ -7252,8 +7263,8 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, contentTypeAttrib.value = contentTypeValue; contentTypeAttrib.valueSz = ret; + /* otherwise, try to set from custom content type */ } 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"); @@ -7263,29 +7274,30 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, contentTypeAttrib.valueSz = pkcs7->contentTypeSz; } - authAttribsCount += 1; authAttribsSz += EncodeAttributes(authAttribs, 1, &contentTypeAttrib, 1); + authAttribsCount += 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); - - } + /* authAttribs: add in user authenticated attributes */ + if (pkcs7->authAttribs != NULL && pkcs7->authAttribsSz > 0) { + authAttribsSz += EncodeAttributes(authAttribs + authAttribsCount, + MAX_AUTH_ATTRIBS_SZ - authAttribsCount, + pkcs7->authAttribs, + pkcs7->authAttribsSz); + authAttribsCount += pkcs7->authAttribsSz; + } + /* authAttribs: flatten authAttribs */ + if (authAttribsSz > 0 && authAttribsCount > 0) { 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); @@ -7295,7 +7307,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, authAttribsAadSetSz = SetSet(authAttribsSz, authAttribAadSet); /* allocate temp buffer to hold alternate attrib encoding for aad */ - aadBuffer = (byte*)XMALLOC(flatAuthAttribsSz + authAttribsAadSetSz, + aadBuffer = (byte*)XMALLOC(authAttribsSz + authAttribsAadSetSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); if (aadBuffer == NULL) { XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -7306,8 +7318,31 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, aadBufferSz = 0; XMEMCPY(aadBuffer + aadBufferSz, authAttribAadSet, authAttribsAadSetSz); aadBufferSz += authAttribsAadSetSz; - XMEMCPY(aadBuffer + aadBufferSz, flatAuthAttribs, flatAuthAttribsSz); - aadBufferSz += flatAuthAttribsSz; + XMEMCPY(aadBuffer + aadBufferSz, flatAuthAttribs, authAttribsSz); + aadBufferSz += authAttribsSz; + } + + /* build up unauthenticated attributes (unauthAttrs) */ + if (pkcs7->unauthAttribsSz > 0) { + unauthAttribsSz = EncodeAttributes(unauthAttribs + unauthAttribsCount, + MAX_UNAUTH_ATTRIBS_SZ - unauthAttribsCount, + pkcs7->unauthAttribs, + pkcs7->unauthAttribsSz); + unauthAttribsCount = pkcs7->unauthAttribsSz; + + flatUnauthAttribs = (byte*)XMALLOC(unauthAttribsSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (flatUnauthAttribs == NULL) { + if (aadBuffer) + XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + FlattenAttributes(flatUnauthAttribs, unauthAttribs, unauthAttribsCount); + unauthAttribsSetSz = SetImplicit(ASN_SET, 2, unauthAttribsSz, + unauthAttribSet); } /* allocate encrypted content buffer */ @@ -7315,6 +7350,10 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (encryptedContent == NULL) { + if (aadBuffer) + XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (flatAuthAttribs) XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return MEMORY_E; @@ -7325,10 +7364,14 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, pkcs7->cekSz, nonce, nonceSz, aadBuffer, aadBufferSz, authTag, sizeof(authTag), pkcs7->content, encryptedOutSz, encryptedContent); - if (aadBuffer) + if (aadBuffer) { XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + aadBuffer = NULL; + } if (ret != 0) { + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (flatAuthAttribs) XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -7339,6 +7382,8 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, ret = wc_SetContentType(pkcs7->contentOID, contentType, sizeof(contentType)); if (ret < 0) { + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (flatAuthAttribs) XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -7361,6 +7406,8 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, macIntSz); if (contentEncAlgoSz == 0) { + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (flatAuthAttribs) XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -7380,8 +7427,9 @@ 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 + flatAuthAttribsSz + - authAttribsSetSz + macOctetStringSz + sizeof(authTag); + encContentOctetSz + encryptedOutSz + authAttribsSz + + authAttribsSetSz + macOctetStringSz + sizeof(authTag) + + unauthAttribsSz + unauthAttribsSetSz; /* EnvelopedData */ envDataSeqSz = SetSequence(totalSz, envDataSeq); @@ -7398,6 +7446,8 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, if (totalSz > (int)outputSz) { WOLFSSL_MSG("Pkcs7_encrypt output buffer too small"); + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (flatAuthAttribs) XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -7442,11 +7492,11 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, idx += encryptedOutSz; /* authenticated attributes */ - if (flatAuthAttribsSz > 0) { + if (authAttribsSz > 0) { XMEMCPY(output + idx, authAttribSet, authAttribsSetSz); idx += authAttribsSetSz; - XMEMCPY(output + idx, flatAuthAttribs, flatAuthAttribsSz); - idx += flatAuthAttribsSz; + XMEMCPY(output + idx, flatAuthAttribs, authAttribsSz); + idx += authAttribsSz; XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); } @@ -7455,6 +7505,15 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, XMEMCPY(output + idx, authTag, sizeof(authTag)); idx += sizeof(authTag); + /* unauthenticated attributes */ + if (unauthAttribsSz > 0) { + XMEMCPY(output + idx, unauthAttribSet, unauthAttribsSetSz); + idx += unauthAttribsSetSz; + XMEMCPY(output + idx, flatUnauthAttribs, unauthAttribsSz); + idx += unauthAttribsSz; + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return idx; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 5b62589d7..5e5a653ae 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19529,8 +19529,10 @@ typedef struct { size_t certSz; byte* privateKey; word32 privateKeySz; - PKCS7Attrib* signedAttribs; - word32 signedAttribsSz; + PKCS7Attrib* authAttribs; + word32 authAttribsSz; + PKCS7Attrib* unauthAttribs; + word32 unauthAttribsSz; /* KARI / KTRI specific */ byte* optionalUkm; @@ -19579,6 +19581,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, byte enveloped[2048]; byte decoded[2048]; + WC_RNG rng; PKCS7* pkcs7; #ifdef PKCS7_OUTPUT_TEST_BUNDLES FILE* pkcs7File; @@ -19589,6 +19592,17 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, 0x72,0x6c,0x64 }; + static byte senderNonceOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x05 }; + static byte senderNonce[PKCS7_NONCE_SZ + 2]; + + PKCS7Attrib attribs[] = + { + { senderNonceOid, sizeof(senderNonceOid), senderNonce, + sizeof(senderNonce) } + }; + #if !defined(NO_AES) && defined(WOLFSSL_AES_256) && defined(HAVE_ECC) && \ defined(WOLFSSL_SHA512) byte optionalUkm[] = { @@ -19624,37 +19638,38 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #if !defined(NO_AES) && defined(HAVE_AESGCM) #ifdef WOLFSSL_AES_128 {data, (word32)sizeof(data), DATA, AES128GCMb, 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, - "pkcs7authEnvelopedDataAES128GCM.der"}, + rsaPrivKey, rsaPrivKeySz, NULL, 0, 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, "pkcs7authEnvelopedDataAES128GCM.der"}, #endif #ifdef WOLFSSL_AES_192 {data, (word32)sizeof(data), DATA, AES192GCMb, 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, - "pkcs7authEnvelopedDataAES192GCM.der"}, + rsaPrivKey, rsaPrivKeySz, NULL, 0, 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, "pkcs7authEnvelopedDataAES192GCM.der"}, #endif #ifdef WOLFSSL_AES_256 {data, (word32)sizeof(data), 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.der"}, + rsaPrivKey, rsaPrivKeySz, NULL, 0, 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.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"}, + rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz, NULL, 0, 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, - NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, - 0, 0, "pkcs7authEnvelopedDataAES256GCM_SKID.der"}, + rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, CMS_SKID, 0, + NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, + 0, 0, 0, 0, 0, "pkcs7authEnvelopedDataAES256GCM_SKID.der"}, /* explicitly using IssuerAndSerialNumber for SubjectKeyIdentifier */ {data, (word32)sizeof(data), DATA, AES256GCMb, 0, 0, rsaCert, rsaCertSz, - rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, + rsaPrivKey, rsaPrivKeySz, NULL, 0, NULL, 0, NULL, 0, CMS_ISSUER_AND_SERIAL_NUMBER, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, "pkcs7authEnvelopedDataAES256GCM_IANDS.der"}, @@ -19668,32 +19683,70 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) {data, (word32)sizeof(data), DATA, AES128GCMb, AES128_WRAP, dhSinglePass_stdDH_sha1kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, 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, + eccPrivKeySz, NULL, 0, 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, "pkcs7authEnvelopedDataAES128GCM_ECDH_SHA1KDF.der"}, #endif #if !defined(NO_SHA256) && defined(WOLFSSL_AES_256) {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, 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, + eccPrivKeySz, NULL, 0, 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_ECDH_SHA256KDF.der"}, + + /* with authenticated attributes */ + {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, attribs, (sizeof(attribs) / sizeof(PKCS7Attrib)), + 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_ECDH_SHA256KDF_authAttribs.der"}, + + /* with unauthenticated attributes */ + {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, NULL, 0, attribs, + (sizeof(attribs) / sizeof(PKCS7Attrib)), 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_ECDH_SHA256KDF_unauthAttribs.der"}, + + /* with authenticated AND unauthenticated attributes */ + {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, attribs, (sizeof(attribs) / sizeof(PKCS7Attrib)), + attribs, (sizeof(attribs) / sizeof(PKCS7Attrib)), 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_ECDH_SHA256KDF_bothAttribs.der"}, + + /* with authenticated AND unauthenticated attributes AND + * contentType of FirmwarePkgData */ + {data, (word32)sizeof(data), FIRMWARE_PKG_DATA, AES256GCMb, AES256_WRAP, + dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, + eccPrivKeySz, attribs, (sizeof(attribs) / sizeof(PKCS7Attrib)), + attribs, (sizeof(attribs) / sizeof(PKCS7Attrib)), 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_ECDH_SHA256KDF_fw_bothAttribs.der"}, #endif /* NO_SHA256 && WOLFSSL_AES_256 */ #if defined(WOLFSSL_SHA512) && defined(WOLFSSL_AES_256) {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, 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, + eccPrivKeySz, NULL, 0, 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_ECDH_SHA512KDF.der"}, /* with optional user keying material (ukm) */ {data, (word32)sizeof(data), DATA, AES256GCMb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, - eccPrivKeySz, NULL, 0, optionalUkm, sizeof(optionalUkm), 0, 0, NULL, 0, - NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, - 0, 0, "pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der"}, + eccPrivKeySz, NULL, 0, NULL, 0, optionalUkm, sizeof(optionalUkm), 0, + 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, + 0, 0, 0, 0, 0, 0, + "pkcs7authEnvelopedDataAES256GCM_ECDH_SHA512KDF_ukm.der"}, #endif /* WOLFSSL_SHA512 && WOLFSSL_AES_256 */ #endif /* NO_AES */ #endif @@ -19702,9 +19755,9 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #if !defined(NO_AES) && defined(HAVE_AESGCM) #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) {data, (word32)sizeof(data), DATA, AES128GCMb, AES128_WRAP, 0, - NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, secretKey, sizeof(secretKey), - secretKeyId, sizeof(secretKeyId), NULL, NULL, 0, NULL, 0, - 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, + NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, + secretKey, sizeof(secretKey), secretKeyId, sizeof(secretKeyId), + NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 0, 0, 0, "pkcs7authEnvelopedDataAES128GCM_KEKRI.der"}, #endif #endif @@ -19713,7 +19766,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #if !defined(NO_PWDBASED) && !defined(NO_AES) && defined(HAVE_AESGCM) #if !defined(NO_SHA) && defined(WOLFSSL_AES_128) {data, (word32)sizeof(data), DATA, AES128GCMb, 0, 0, - NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, + NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, password, (word32)XSTRLEN(password), salt, sizeof(salt), PBKDF2_OID, WC_SHA, 5, AES128CBCb, 0, 0, 0, "pkcs7authEnvelopedDataAES128GCM_PWRI.der"}, @@ -19724,8 +19777,8 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #ifdef WOLFSSL_AES_128 /* ori (OtherRecipientInfo) recipient types */ {data, (word32)sizeof(data), DATA, AES128GCMb, 0, 0, NULL, 0, NULL, 0, - 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, 1, 0, + NULL, 0, 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, 1, 0, "pkcs7authEnvelopedDataAES128GCM_ORI.der"}, #endif #endif @@ -19733,6 +19786,30 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, testSz = sizeof(testVectors) / sizeof(pkcs7AuthEnvelopedVector); + + /* generate senderNonce */ + { +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) { + return -9370; + } + + senderNonce[0] = 0x04; + senderNonce[1] = PKCS7_NONCE_SZ; + + ret = wc_RNG_GenerateBlock(&rng, &senderNonce[2], PKCS7_NONCE_SZ); + if (ret != 0) { + wc_FreeRng(&rng); + return -9371; + } + + wc_FreeRng(&rng); + } + for (i = 0; i < testSz; i++) { pkcs7 = wc_PKCS7_New(HEAP_HINT, #ifdef WOLFSSL_ASYNC_CRYPT @@ -19742,22 +19819,26 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #endif ); if (pkcs7 == NULL) - return -9370; + return -9372; if (testVectors[i].secretKey != NULL) { /* KEKRI recipient type */ ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); if (ret != 0) { - return -9371; + return -9373; } - pkcs7->content = (byte*)testVectors[i].content; - pkcs7->contentSz = testVectors[i].contentSz; - pkcs7->contentOID = testVectors[i].contentOID; - pkcs7->encryptOID = testVectors[i].encryptOID; - pkcs7->ukm = testVectors[i].optionalUkm; - pkcs7->ukmSz = testVectors[i].optionalUkmSz; + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + pkcs7->authAttribs = testVectors[i].authAttribs; + pkcs7->authAttribsSz = testVectors[i].authAttribsSz; + pkcs7->unauthAttribs = testVectors[i].unauthAttribs; + pkcs7->unauthAttribsSz = testVectors[i].unauthAttribsSz; ret = wc_PKCS7_AddRecipient_KEKRI(pkcs7, testVectors[i].keyWrapOID, testVectors[i].secretKey, testVectors[i].secretKeySz, @@ -19768,7 +19849,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9372; + return -9374; } /* set key, for decryption */ @@ -19777,7 +19858,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9373; + return -9375; } } else if (testVectors[i].password != NULL) { @@ -19785,15 +19866,19 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); if (ret != 0) { - return -9374; + return -9376; } - pkcs7->content = (byte*)testVectors[i].content; - pkcs7->contentSz = testVectors[i].contentSz; - pkcs7->contentOID = testVectors[i].contentOID; - pkcs7->encryptOID = testVectors[i].encryptOID; - pkcs7->ukm = testVectors[i].optionalUkm; - pkcs7->ukmSz = testVectors[i].optionalUkmSz; + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + pkcs7->authAttribs = testVectors[i].authAttribs; + pkcs7->authAttribsSz = testVectors[i].authAttribsSz; + pkcs7->unauthAttribs = testVectors[i].unauthAttribs; + pkcs7->unauthAttribsSz = testVectors[i].unauthAttribsSz; ret = wc_PKCS7_AddRecipient_PWRI(pkcs7, (byte*)testVectors[i].password, @@ -19804,7 +19889,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9375; + return -9377; } /* set password, for decryption */ @@ -19813,7 +19898,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9376; + return -9378; } } else if (testVectors[i].isOri == 1) { @@ -19821,20 +19906,24 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); if (ret != 0) { - return -9377; + return -9379; } - pkcs7->content = (byte*)testVectors[i].content; - pkcs7->contentSz = testVectors[i].contentSz; - pkcs7->contentOID = testVectors[i].contentOID; - pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->authAttribs = testVectors[i].authAttribs; + pkcs7->authAttribsSz = testVectors[i].authAttribsSz; + pkcs7->unauthAttribs = testVectors[i].unauthAttribs; + pkcs7->unauthAttribsSz = testVectors[i].unauthAttribsSz; ret = wc_PKCS7_AddRecipient_ORI(pkcs7, myOriEncryptCb, testVectors[i].oriOptions); if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9378; + return -9380; } /* set decrypt callback for decryption */ @@ -19842,7 +19931,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (ret < 0) { wc_PKCS7_Free(pkcs7); - return -9379; + return -9381; } } else { @@ -19852,19 +19941,23 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, (word32)testVectors[i].certSz); if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9380; + return -9382; } - pkcs7->keyWrapOID = testVectors[i].keyWrapOID; - pkcs7->keyAgreeOID = testVectors[i].keyAgreeOID; - pkcs7->privateKey = testVectors[i].privateKey; - pkcs7->privateKeySz = testVectors[i].privateKeySz; - pkcs7->content = (byte*)testVectors[i].content; - pkcs7->contentSz = testVectors[i].contentSz; - pkcs7->contentOID = testVectors[i].contentOID; - pkcs7->encryptOID = testVectors[i].encryptOID; - pkcs7->ukm = testVectors[i].optionalUkm; - pkcs7->ukmSz = testVectors[i].optionalUkmSz; + pkcs7->keyWrapOID = testVectors[i].keyWrapOID; + pkcs7->keyAgreeOID = testVectors[i].keyAgreeOID; + pkcs7->privateKey = testVectors[i].privateKey; + pkcs7->privateKeySz = testVectors[i].privateKeySz; + pkcs7->content = (byte*)testVectors[i].content; + pkcs7->contentSz = testVectors[i].contentSz; + pkcs7->contentOID = testVectors[i].contentOID; + pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->ukm = testVectors[i].optionalUkm; + pkcs7->ukmSz = testVectors[i].optionalUkmSz; + pkcs7->authAttribs = testVectors[i].authAttribs; + pkcs7->authAttribsSz = testVectors[i].authAttribsSz; + pkcs7->unauthAttribs = testVectors[i].unauthAttribs; + pkcs7->unauthAttribsSz = testVectors[i].unauthAttribsSz; /* set SubjectIdentifier type for KTRI types */ if (testVectors[i].ktriOptions & CMS_SKID) { @@ -19872,7 +19965,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9381; + return -9383; } } else if (testVectors[i].ktriOptions & CMS_ISSUER_AND_SERIAL_NUMBER) { @@ -19881,7 +19974,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, CMS_ISSUER_AND_SERIAL_NUMBER); if (ret != 0) { wc_PKCS7_Free(pkcs7); - return -9382; + return -9384; } } } @@ -19891,7 +19984,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, sizeof(enveloped)); if (envelopedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9383; + return -9385; } /* decode envelopedData */ @@ -19900,13 +19993,13 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, sizeof(decoded)); if (decodedSz <= 0) { wc_PKCS7_Free(pkcs7); - return -9384; + return -9386; } /* test decode result */ if (XMEMCMP(decoded, data, sizeof(data)) != 0){ wc_PKCS7_Free(pkcs7); - return -9385; + return -9387; } #ifdef PKCS7_OUTPUT_TEST_BUNDLES @@ -19914,14 +20007,14 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7File = fopen(testVectors[i].outFileName, "wb"); if (!pkcs7File) { wc_PKCS7_Free(pkcs7); - return -9386; + return -9388; } ret = (int)fwrite(enveloped, 1, envelopedSz, pkcs7File); fclose(pkcs7File); if (ret != envelopedSz) { wc_PKCS7_Free(pkcs7); - return -9387; + return -9389; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 9f2d19fff..fdadba9d9 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -62,6 +62,14 @@ #define MAX_SIGNED_ATTRIBS_SZ 7 #endif +#ifndef MAX_AUTH_ATTRIBS_SZ + #define MAX_AUTH_ATTRIBS_SZ 7 +#endif + +#ifndef MAX_UNAUTH_ATTRIBS_SZ + #define MAX_UNAUTH_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 */ @@ -211,6 +219,8 @@ typedef struct PKCS7 { PKCS7Attrib* authAttribs; /* authenticated attribs */ word32 authAttribsSz; + PKCS7Attrib* unauthAttribs; /* unauthenticated attribs */ + word32 unauthAttribsSz; /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ } PKCS7; From 83a150c4dfbee30b60b630181be77cfab614be22 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Fri, 5 Oct 2018 13:28:20 -0600 Subject: [PATCH 24/56] stream of PKCS7 decode encrypted --- tests/api.c | 1 + wolfcrypt/src/error.c | 3 + wolfcrypt/src/pkcs7.c | 556 ++++++++++++++++++++++++++------ wolfcrypt/test/test.c | 19 ++ wolfssl/wolfcrypt/asn.h | 1 + wolfssl/wolfcrypt/error-crypt.h | 3 +- wolfssl/wolfcrypt/pkcs7.h | 15 + 7 files changed, 504 insertions(+), 94 deletions(-) diff --git a/tests/api.c b/tests/api.c index e87552e66..b22fff53d 100644 --- a/tests/api.c +++ b/tests/api.c @@ -15022,6 +15022,7 @@ static void test_wc_PKCS7_EncodeData (void) XMEMSET(output, 0, sizeof(output)); + pkcs7.isDynamic = 0; AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, INVALID_DEVID), 0); AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, (byte*)cert, certSz), 0); diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 47217475a..5ebf0e209 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -281,6 +281,9 @@ const char* wc_GetErrorString(int error) case PKCS7_RECIP_E: return "PKCS#7 error: no matching recipient found"; + case WC_PKCS7_WANT_READ_E: + return "PKCS#7 operations wants more input, call again"; + case FIPS_NOT_ALLOWED_E: return "FIPS mode not allowed error"; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 92b2041fc..c02b3aba5 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -58,6 +58,145 @@ typedef enum { WC_PKCS7_DECODE } pkcs7Direction; + +#ifndef NO_PKCS7_STREAM + +#define MAX_PKCS7_STREAM_BUFFER 256 +typedef struct PKCS7State { + byte* tmpCert; + word32 varOne; + word32 varTwo; + word32 varThree; + word32 vers; + word32 idx; /* index read into current input buffer */ + word32 maxLen; /* sanity cap on maximum amount of data to allow + * needed for GetSequence and other calls */ + word32 length; /* amount of data stored */ + word32 expected; /* next amount of data expected, if needed */ + word32 totalRd; /* total amount of bytes read */ + byte hasAtrib:1; + byte buffer[4096]; + byte tmpIv[MAX_CONTENT_IV_SIZE]; /* store IV if needed */ +} PKCS7State; + + +enum PKCS7_MaxLen { + PKCS7_DEFAULT_PEEK = 0, + PKCS7_SEQ_PEEK +}; + +/* creates a PKCS7State structure and returns 0 on success */ +static int wc_PKCS7_CreateStream(PKCS7* pkcs7) +{ + WOLFSSL_MSG("creating PKCS7 stream structure"); + pkcs7->stream = (PKCS7State*)XMALLOC(sizeof(PKCS7State), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream == NULL) { + return MEMORY_E; + } + XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State)); + return 0; +} + + +static void wc_PKCS7_ResetStream(PKCS7* pkcs7) +{ + /* free any buffers that may be allocated */ + + /* reset values */ + XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State)); +} + + +static void wc_PKCS7_FreeStream(PKCS7* pkcs7) +{ + if (pkcs7 != NULL && pkcs7->stream != NULL) { + wc_PKCS7_ResetStream(pkcs7); + XFREE(pkcs7->stream, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } +} + + +/* pt gets set to the buffer that is holding data in the case that stream struct + * is used. + * + * returns 0 on success + */ +static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, + word32 expected, byte** pt, word32* idx) +{ + word32 rdSz; + + if (inSz >= expected && pkcs7->stream->length == 0) { + /* storing input buffer is not needed */ + return 0; + } + + /* is there enough stored in buffer already? */ + if (pkcs7->stream->length >= expected) { + *idx = 0; + *pt = pkcs7->stream->buffer; + return 0; + } + + /* check if all data has been read from input */ + rdSz = pkcs7->stream->idx; + if (rdSz >= inSz) { + /* no more input to read */ + pkcs7->stream->idx = 0; + return WC_PKCS7_WANT_READ_E; + } + + if (inSz - rdSz > 0 && pkcs7->stream->length < expected) { + int len = min(inSz - rdSz, expected - pkcs7->stream->length); + XMEMCPY(pkcs7->stream->buffer + pkcs7->stream->length, in + rdSz, len); + pkcs7->stream->length += len; + pkcs7->stream->idx += len; + pkcs7->stream->totalRd += len; + } + + if (pkcs7->stream->length < expected) { + pkcs7->stream->idx = 0; + return WC_PKCS7_WANT_READ_E; + } + + /* read from stored buffer */ + *idx = 0; + *pt = pkcs7->stream->buffer; + return 0; +} + + +/* Does two things + * 1) Tries to get the length from current buffer and set it as max length + * 2) Retrieves the set max length + * + * if no flag value is set then the stored max length is returned. + * returns length found on success and defSz if no stored data is found + */ +static word32 wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, word32 defSz) +{ + /* check there is a buffer to read from */ + if (pkcs7 && pkcs7->stream->length > 0) { + int length = 0, ret; + word32 idx = 0; + if (flag & PKCS7_SEQ_PEEK) { + if ((ret = GetSequence(pkcs7->stream->buffer, &idx, + &length, (word32)-1)) < 0) { + return ret; + } + pkcs7->stream->maxLen = length + idx; + } + return pkcs7->stream->maxLen; + } + + if (pkcs7->stream->maxLen == 0) { + pkcs7->stream->maxLen = defSz; + } + return defSz; +} +#endif /* NO_PKCS7_STREAM */ + #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \ MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE) @@ -595,6 +734,10 @@ void wc_PKCS7_Free(PKCS7* pkcs7) if (pkcs7 == NULL) return; +#ifndef NO_PKCS7_STREAM + wc_PKCS7_FreeStream(pkcs7); +#endif + wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); wc_PKCS7_FreeCertSet(pkcs7); @@ -6774,7 +6917,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, word32* idx, int type) { - int version, length; + int version, length, ret; word32 contentType; if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || idx == NULL) @@ -6859,6 +7002,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* pkiMsg, if (GetSet(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; + (void)ret; return length; } @@ -8076,20 +8220,24 @@ static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg, /* unwrap and decrypt PKCS#7/CMS encrypted-data object, returned decoded size */ -int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, +int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, byte* output, word32 outputSz) { - int ret, version, length, haveAttribs; - word32 idx = 0; + int ret = 0, version, length, haveAttribs; + word32 idx = 0, tmpIdx = 0; word32 contentType, encOID; - int expBlockSz; - byte tmpIv[MAX_CONTENT_IV_SIZE]; + int expBlockSz = 0; + byte tmpIvBuf[MAX_CONTENT_IV_SIZE]; + byte *tmpIv = tmpIvBuf; int encryptedContentSz; byte padLen; byte* encryptedContent = NULL; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + if (pkcs7 == NULL || pkcs7->encryptionKey == NULL || pkcs7->encryptionKeySz == 0) return BAD_FUNC_ARG; @@ -8098,119 +8246,343 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, output == NULL || outputSz == 0) return BAD_FUNC_ARG; - /* read past ContentInfo, verify type is encrypted-data */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (contentType != ENCRYPTED_DATA) { - WOLFSSL_MSG("PKCS#7 input not of type EncryptedData"); - return PKCS7_OID_E; +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } } +#endif - if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) - return ASN_PARSE_E; + switch (pkcs7->state) { + case WC_PKCS7_START: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_ALGO_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); +#endif - /* remove EncryptedData and version */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; + /* read past ContentInfo, verify type is encrypted-data */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; - /* get version, check later */ - haveAttribs = 0; - if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) - return ASN_PARSE_E; + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, + pkiMsgSz) < 0) + ret = ASN_PARSE_E; - /* remove EncryptedContentInfo */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; + if (ret == 0 && contentType != ENCRYPTED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type EncryptedData"); + ret = PKCS7_OID_E; + } - if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) - return ASN_PARSE_E; + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream->length > 0) { + if (pkcs7->stream->length < idx) { + ret = BUFFER_E; + break; + } + XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx, + pkcs7->stream->length - idx); + pkcs7->stream->length -= idx; + } + else { + pkcs7->stream->totalRd += idx - tmpIdx; + tmpIdx = idx; + } +#endif + pkcs7->state = WC_PKCS7_STAGE2; + /* end of stage 1 */ - if (GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) - return ASN_PARSE_E; + case WC_PKCS7_STAGE2: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + MAX_LENGTH_SZ + MAX_SEQ_SZ + ASN_TAG_SZ, &pkiMsg, + &idx)) != 0) { + return ret; + } - expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); - if (expBlockSz < 0) - return expBlockSz; + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); +#endif + if (ret == 0 && pkiMsg[idx++] != (ASN_CONSTRUCTED | + ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; - /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ - if (pkiMsg[idx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; + /* remove EncryptedData and version */ + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; - if (length != expBlockSz) { - WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); - return ASN_PARSE_E; - } + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream->length > 0) { + if (pkcs7->stream->length < idx) { + ret = BUFFER_E; + break; + } + XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx, + pkcs7->stream->length - idx); + pkcs7->stream->length -= idx; + } + else { + pkcs7->stream->totalRd += idx - tmpIdx; + tmpIdx = idx; + } +#endif + pkcs7->state = WC_PKCS7_STAGE3; + /* end of stage 2 */ - XMEMCPY(tmpIv, &pkiMsg[idx], length); - idx += length; + case WC_PKCS7_STAGE3: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_ALGO_SZ * 2, + &pkiMsg, &idx)) != 0) { + return ret; + } - /* read encryptedContent, cont[0] */ - if (pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) - return ASN_PARSE_E; + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); +#endif + /* get version, check later */ + haveAttribs = 0; + if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) + ret = ASN_PARSE_E; - if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) - return ASN_PARSE_E; + /* remove EncryptedContentInfo */ + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; - encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, - DYNAMIC_TYPE_PKCS7); - if (encryptedContent == NULL) - return MEMORY_E; + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, + pkiMsgSz) < 0) + ret = ASN_PARSE_E; - XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); - idx += encryptedContentSz; + if (ret == 0 && (ret = GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, + pkiMsgSz)) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && (expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID)) < 0) + ret = expBlockSz; - /* decrypt encryptedContent */ - ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey, + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + /* store expBlockSz for later */ + pkcs7->stream->varOne = expBlockSz; + pkcs7->stream->varTwo = encOID; + + if (pkcs7->stream->length > 0) { + if (pkcs7->stream->length < idx) { + ret = BUFFER_E; + break; + } + XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx, + pkcs7->stream->length - idx); + pkcs7->stream->length -= idx; + } + else { + pkcs7->stream->totalRd += idx - tmpIdx; + tmpIdx = idx; + } + + /* store version for later */ + pkcs7->stream->vers = version; +#endif + pkcs7->state = WC_PKCS7_STAGE4; + /* end of stage 3 */ + + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ + case WC_PKCS7_STAGE4: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + + /* restore saved variables */ + expBlockSz = pkcs7->stream->varOne; +#endif + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && length != expBlockSz) { + WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); + ret = ASN_PARSE_E; + } + + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + /* next chunk of data expected should have the IV */ + pkcs7->stream->expected = length; + + if (pkcs7->stream->length > 0) { + if (pkcs7->stream->length < idx) { + ret = BUFFER_E; + break; + } + XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx, + pkcs7->stream->length - idx); + pkcs7->stream->length -= idx; + } + else { + pkcs7->stream->totalRd += idx - tmpIdx; + tmpIdx = idx; + } +#endif + pkcs7->state = WC_PKCS7_STAGE5; + /* end of stage 4 */ + + case WC_PKCS7_STAGE5: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected + ASN_TAG_SZ + + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + + /* restore saved variables */ + expBlockSz = pkcs7->stream->varOne; + + /* use IV buffer from stream structure */ + tmpIv = pkcs7->stream->tmpIv; +#endif + XMEMCPY(tmpIv, &pkiMsg[idx], length); + idx += length; + /* read encryptedContent, cont[0] */ + if (ret == 0 && pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) + ret = ASN_PARSE_E; + +#ifndef NO_PKCS7_STREAM + /* next chunk of data should contain encrypted content */ + pkcs7->stream->varThree = encryptedContentSz; + if (pkcs7->stream->length > 0) { + if (pkcs7->stream->length < idx) { + ret = BUFFER_E; + break; + } + XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx, + pkcs7->stream->length - idx); + pkcs7->stream->length -= idx; + } + else { + pkcs7->stream->totalRd += idx - tmpIdx; + tmpIdx = idx; + } + + if (pkcs7->stream->totalRd + encryptedContentSz < pkiMsgSz) { + pkcs7->stream->hasAtrib = 1; + } + + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + +#endif + pkcs7->state = WC_PKCS7_STAGE6; + /* end of stage 5 */ + + case WC_PKCS7_STAGE6: +#ifndef NO_PKCS7_STREAM + //@TODO + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + + /* restore saved variables */ + expBlockSz = pkcs7->stream->varOne; + encOID = pkcs7->stream->varTwo; + encryptedContentSz = pkcs7->stream->varThree; + version = pkcs7->stream->vers; + tmpIv = pkcs7->stream->tmpIv; +#endif + if (ret == 0 && (encryptedContent = (byte*)XMALLOC( + encryptedContentSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7)) == NULL) + ret = MEMORY_E; + + if (ret == 0) { + XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); + idx += encryptedContentSz; + } + + /* decrypt encryptedContent */ + ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey, pkcs7->encryptionKeySz, tmpIv, expBlockSz, NULL, 0, NULL, 0, encryptedContent, encryptedContentSz, encryptedContent); - if (ret != 0) { - XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ret; - } + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } - padLen = encryptedContent[encryptedContentSz-1]; + if (ret == 0) { + padLen = encryptedContent[encryptedContentSz-1]; - /* copy plaintext to output */ - XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); + /* copy plaintext to output */ + XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); - /* get implicit[1] unprotected attributes, optional */ - pkcs7->decodedAttrib = NULL; - if (idx < pkiMsgSz) { + /* get implicit[1] unprotected attributes, optional */ + pkcs7->decodedAttrib = NULL; +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream->hasAtrib) { +#else + if (idx < pkiMsgSz) { +#endif + haveAttribs = 1; - haveAttribs = 1; - - ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg, + ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg, pkiMsgSz, &idx); - if (ret != 0) { - ForceZero(encryptedContent, encryptedContentSz); - XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ASN_PARSE_E; - } + if (ret != 0) { + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + ret = ASN_PARSE_E; + } + } + } + + if (ret == 0) { + /* go back and check the version now that attribs have been processed */ + if ((haveAttribs == 0 && version != 0) || + (haveAttribs == 1 && version != 2) ) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version"); + return ASN_VERSION_E; + } + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + ret = encryptedContentSz - padLen; + } + + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + wc_PKCS7_ResetStream(pkcs7); +#endif + pkcs7->state = WC_PKCS7_START; + break; + + default: + WOLFSSL_MSG("Error in unknown PKCS#7 state"); + return BAD_STATE_E; } - /* go back and check the version now that attribs have been processed */ - if ((haveAttribs == 0 && version != 0) || - (haveAttribs == 1 && version != 2) ) { - XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version"); - return ASN_VERSION_E; + if (ret != 0) { + /* restart in error case */ + wc_PKCS7_ResetStream(pkcs7); + pkcs7->state = WC_PKCS7_START; } - - ForceZero(encryptedContent, encryptedContentSz); - XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - - return encryptedContentSz - padLen; + return ret; } #endif /* NO_PKCS7_ENCRYPTED_DATA */ @@ -8378,10 +8750,8 @@ int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) return ASN_PARSE_E; - if (contentType != COMPRESSED_DATA) { - printf("ContentInfo not of type CompressedData"); + if (contentType != COMPRESSED_DATA) return ASN_PARSE_E; - } /* get ContentInfo content EXPLICIT SEQUENCE */ if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 5e5a653ae..1d2a1b1da 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -20300,6 +20300,25 @@ int pkcs7encrypted_test(void) } /* decode encryptedData */ +#ifndef NO_PKCS7_STREAM + { /* test reading byte by byte */ + int z; + for (z = 0; z < encryptedSz; z++) { + decodedSz = wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted + z, 1, + decoded, sizeof(decoded)); + if (decodedSz <= 0 && decodedSz != WC_PKCS7_WANT_READ_E) { + printf("unexpected error %d\n", decodedSz); + return -9402; + } + } + /* test decode result */ + if (XMEMCMP(decoded, data, sizeof(data)) != 0) { + printf("stream read failed\n"); + wc_PKCS7_Free(pkcs7); + return -9403; + } + } +#endif decodedSz = wc_PKCS7_DecodeEncryptedData(pkcs7, encrypted, encryptedSz, decoded, sizeof(decoded)); if (decodedSz <= 0){ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 2c7064a1a..19ee854e6 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -303,6 +303,7 @@ enum Misc_ASN { HEADER_ENCRYPTED_KEY_SIZE = 0, #endif TRAILING_ZERO = 1, /* Used for size of zero pad */ + ASN_TAG_SZ = 1, /* single byte ASN.1 tag */ MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */ #if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index d651dc0ba..2581a30b5 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -221,8 +221,9 @@ enum { ZLIB_DECOMPRESS_ERROR = -268, /* zlib decompression error */ PKCS7_NO_SIGNER_E = -269, /* No signer in PKCS#7 signed data msg */ + WC_PKCS7_WANT_READ_E= -270, /* PKCS7 operations wants more input */ - WC_LAST_E = -269, /* Update this to indicate last error */ + WC_LAST_E = -270, /* Update this to indicate last error */ MIN_CODE_E = -300 /* errors -101 - -299 */ /* add new companion error id strings for any new error codes diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index fdadba9d9..8999c4455 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -86,6 +86,15 @@ enum PKCS7_TYPES { AUTH_ENVELOPED_DATA = 692 /* 1.2.840.113549.1.9.16.1.23, RFC 5083 */ }; +enum PKCS7_STATE { + WC_PKCS7_START = 0, + WC_PKCS7_STAGE2, + WC_PKCS7_STAGE3, + WC_PKCS7_STAGE4, + WC_PKCS7_STAGE5, + WC_PKCS7_STAGE6 +}; + enum Pkcs7_Misc { PKCS7_NONCE_SZ = 16, MAX_ENCRYPTED_KEY_SZ = 512, /* max enc. key size, RSA <= 4096 */ @@ -131,6 +140,7 @@ typedef struct PKCS7DecodedAttrib { word32 valueSz; } PKCS7DecodedAttrib; +typedef struct PKCS7State PKCS7State; typedef struct Pkcs7Cert Pkcs7Cert; typedef struct Pkcs7EncodedRecip Pkcs7EncodedRecip; typedef struct PKCS7 PKCS7; @@ -222,6 +232,11 @@ typedef struct PKCS7 { PKCS7Attrib* unauthAttribs; /* unauthenticated attribs */ word32 unauthAttribsSz; +#ifndef NO_PKCS7_STREAM + PKCS7State* stream; +#endif + enum PKCS7_STATE state; + /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ } PKCS7; From 02df920269c6dd7ef471e7677699fa163324e0e3 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 8 Oct 2018 17:00:06 -0600 Subject: [PATCH 25/56] use fall through and update api tests to use wc_PKCS7_New --- tests/api.c | 263 ++++++++++++++++++++++-------------------- wolfcrypt/src/pkcs7.c | 5 + 2 files changed, 142 insertions(+), 126 deletions(-) diff --git a/tests/api.c b/tests/api.c index b22fff53d..20b9dd7c6 100644 --- a/tests/api.c +++ b/tests/api.c @@ -14879,7 +14879,7 @@ static void test_wc_PKCS7_Init (void) static void test_wc_PKCS7_InitWithCert (void) { #if defined(HAVE_PKCS7) - PKCS7 pkcs7; + PKCS7* pkcs7; #ifndef NO_RSA #if defined(USE_CERT_BUFFERS_2048) @@ -14923,24 +14923,26 @@ static void test_wc_PKCS7_InitWithCert (void) #error PKCS7 requires ECC or RSA #endif printf(testingFmt, "wc_PKCS7_InitWithCert()"); - /* If initialization is not successful, it's free'd in init func. */ - pkcs7.isDynamic = 0; - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, (byte*)cert, (word32)certSz), 0); - wc_PKCS7_Free(&pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + /* If initialization is not successful, it's free'd in init func. */ + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)cert, (word32)certSz), 0); + + wc_PKCS7_Free(pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); /* Valid initialization usage. */ - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, NULL, 0), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); /* Pass in bad args. No need free for null checks, free at end.*/ AssertIntEQ(wc_PKCS7_InitWithCert(NULL, (byte*)cert, (word32)certSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, NULL, (word32)certSz), + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, (word32)certSz), BAD_FUNC_ARG); printf(resultFmt, passed); - wc_PKCS7_Free(&pkcs7); + wc_PKCS7_Free(pkcs7); #endif } /* END test_wc_PKCS7_InitWithCert */ @@ -14951,7 +14953,7 @@ static void test_wc_PKCS7_InitWithCert (void) static void test_wc_PKCS7_EncodeData (void) { #if defined(HAVE_PKCS7) - PKCS7 pkcs7; + PKCS7* pkcs7; byte output[FOURK_BUF]; byte data[] = "My encoded DER cert."; @@ -15022,29 +15024,29 @@ static void test_wc_PKCS7_EncodeData (void) XMEMSET(output, 0, sizeof(output)); - pkcs7.isDynamic = 0; - AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, INVALID_DEVID), 0); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, (byte*)cert, certSz), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, (byte*)cert, certSz), 0); printf(testingFmt, "wc_PKCS7_EncodeData()"); - pkcs7.content = data; - pkcs7.contentSz = sizeof(data); - pkcs7.privateKey = key; - pkcs7.privateKeySz = keySz; - AssertIntGT(wc_PKCS7_EncodeData(&pkcs7, output, (word32)sizeof(output)), 0); + pkcs7->content = data; + pkcs7->contentSz = sizeof(data); + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + AssertIntGT(wc_PKCS7_EncodeData(pkcs7, output, (word32)sizeof(output)), 0); /* Test bad args. */ AssertIntEQ(wc_PKCS7_EncodeData(NULL, output, (word32)sizeof(output)), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeData(&pkcs7, NULL, (word32)sizeof(output)), + AssertIntEQ(wc_PKCS7_EncodeData(pkcs7, NULL, (word32)sizeof(output)), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeData(&pkcs7, output, 5), BUFFER_E); + AssertIntEQ(wc_PKCS7_EncodeData(pkcs7, output, 5), BUFFER_E); printf(resultFmt, passed); - wc_PKCS7_Free(&pkcs7); + wc_PKCS7_Free(pkcs7); #endif } /* END test_wc_PKCS7_EncodeData */ @@ -15055,7 +15057,7 @@ static void test_wc_PKCS7_EncodeData (void) static void test_wc_PKCS7_EncodeSignedData(void) { #if defined(HAVE_PKCS7) - PKCS7 pkcs7; + PKCS7* pkcs7; WC_RNG rng; byte output[FOURK_BUF]; byte badOut[0]; @@ -15130,37 +15132,39 @@ static void test_wc_PKCS7_EncodeSignedData(void) XMEMSET(output, 0, outputSz); AssertIntEQ(wc_InitRng(&rng), 0); - AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, INVALID_DEVID), 0); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, cert, certSz), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); printf(testingFmt, "wc_PKCS7_EncodeSignedData()"); - pkcs7.content = data; - pkcs7.contentSz = (word32)sizeof(data); - pkcs7.privateKey = key; - pkcs7.privateKeySz = (word32)sizeof(key); - pkcs7.encryptOID = RSAk; - pkcs7.hashOID = SHAh; - pkcs7.rng = &rng; + pkcs7->content = data; + pkcs7->contentSz = (word32)sizeof(data); + pkcs7->privateKey = key; + pkcs7->privateKeySz = (word32)sizeof(key); + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHAh; + pkcs7->rng = &rng; - AssertIntGT(wc_PKCS7_EncodeSignedData(&pkcs7, output, outputSz), 0); + AssertIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0); - wc_PKCS7_Free(&pkcs7); - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, NULL, 0), 0); - AssertIntEQ(wc_PKCS7_VerifySignedData(&pkcs7, output, outputSz), 0); + wc_PKCS7_Free(pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, outputSz), 0); /* Pass in bad args. */ AssertIntEQ(wc_PKCS7_EncodeSignedData(NULL, output, outputSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeSignedData(&pkcs7, NULL, outputSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeSignedData(&pkcs7, badOut, + AssertIntEQ(wc_PKCS7_EncodeSignedData(pkcs7, NULL, outputSz), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeSignedData(pkcs7, badOut, badOutSz), BAD_FUNC_ARG); - pkcs7.hashOID = 0; /* bad hashOID */ - AssertIntEQ(wc_PKCS7_EncodeSignedData(&pkcs7, output, outputSz), BAD_FUNC_ARG); + pkcs7->hashOID = 0; /* bad hashOID */ + AssertIntEQ(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), BAD_FUNC_ARG); printf(resultFmt, passed); - wc_PKCS7_Free(&pkcs7); + wc_PKCS7_Free(pkcs7); wc_FreeRng(&rng); #endif @@ -15173,7 +15177,7 @@ static void test_wc_PKCS7_EncodeSignedData_ex(void) { #if defined(HAVE_PKCS7) int ret, i; - PKCS7 pkcs7; + PKCS7* pkcs7; WC_RNG rng; byte outputHead[FOURK_BUF/2]; byte outputFoot[FOURK_BUF/2]; @@ -15257,19 +15261,20 @@ static void test_wc_PKCS7_EncodeSignedData_ex(void) XMEMSET(outputFoot, 0, outputFootSz); AssertIntEQ(wc_InitRng(&rng), 0); - AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, INVALID_DEVID), 0); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, cert, certSz), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); printf(testingFmt, "wc_PKCS7_EncodeSignedData()"); - pkcs7.content = NULL; /* not used for ex */ - pkcs7.contentSz = (word32)sizeof(data); - pkcs7.privateKey = key; - pkcs7.privateKeySz = (word32)sizeof(key); - pkcs7.encryptOID = RSAk; - pkcs7.hashOID = SHAh; - pkcs7.rng = &rng; + pkcs7->content = NULL; /* not used for ex */ + pkcs7->contentSz = (word32)sizeof(data); + pkcs7->privateKey = key; + pkcs7->privateKeySz = (word32)sizeof(key); + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHAh; + pkcs7->rng = &rng; /* calculate hash for content */ ret = wc_HashInit(&hash, hashType); @@ -15283,20 +15288,21 @@ static void test_wc_PKCS7_EncodeSignedData_ex(void) AssertIntEQ(ret, 0); /* Perform PKCS7 sign using hash directly */ - AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(&pkcs7, hashBuf, hashSz, + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, hashSz, outputHead, &outputHeadSz, outputFoot, &outputFootSz), 0); AssertIntGT(outputHeadSz, 0); AssertIntGT(outputFootSz, 0); - wc_PKCS7_Free(&pkcs7); - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, NULL, 0), 0); + wc_PKCS7_Free(pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); /* required parameter even on verify when using _ex */ - pkcs7.contentSz = (word32)sizeof(data); - AssertIntEQ(wc_PKCS7_VerifySignedData_ex(&pkcs7, hashBuf, hashSz, + pkcs7->contentSz = (word32)sizeof(data); + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, outputHead, outputHeadSz, outputFoot, outputFootSz), 0); - wc_PKCS7_Free(&pkcs7); + wc_PKCS7_Free(pkcs7); /* assembly complete PKCS7 sign and use normal verify */ { @@ -15310,48 +15316,49 @@ static void test_wc_PKCS7_EncodeSignedData_ex(void) XMEMCPY(&output[outputSz], outputFoot, outputFootSz); outputSz += outputFootSz; - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, NULL, 0), 0); - AssertIntEQ(wc_PKCS7_VerifySignedData(&pkcs7, output, outputSz), 0); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, outputSz), 0); XFREE(output, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); } /* Pass in bad args. */ AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(NULL, hashBuf, hashSz, outputHead, &outputHeadSz, outputFoot, &outputFootSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(&pkcs7, NULL, hashSz, outputHead, + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, NULL, hashSz, outputHead, &outputHeadSz, outputFoot, &outputFootSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(&pkcs7, hashBuf, 0, outputHead, + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, 0, outputHead, &outputHeadSz, outputFoot, &outputFootSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(&pkcs7, hashBuf, hashSz, NULL, + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, hashSz, NULL, &outputHeadSz, outputFoot, &outputFootSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(&pkcs7, hashBuf, hashSz, + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, hashSz, outputHead, NULL, outputFoot, &outputFootSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(&pkcs7, hashBuf, hashSz, + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, hashSz, outputHead, &outputHeadSz, NULL, &outputFootSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(&pkcs7, hashBuf, hashSz, + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, hashSz, outputHead, &outputHeadSz, outputFoot, NULL), BAD_FUNC_ARG); - pkcs7.hashOID = 0; /* bad hashOID */ - AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(&pkcs7, hashBuf, hashSz, + pkcs7->hashOID = 0; /* bad hashOID */ + AssertIntEQ(wc_PKCS7_EncodeSignedData_ex(pkcs7, hashBuf, hashSz, outputHead, &outputHeadSz, outputFoot, &outputFootSz), BAD_FUNC_ARG); AssertIntEQ(wc_PKCS7_VerifySignedData_ex(NULL, hashBuf, hashSz, outputHead, outputHeadSz, outputFoot, outputFootSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_VerifySignedData_ex(&pkcs7, NULL, hashSz, outputHead, + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, NULL, hashSz, outputHead, outputHeadSz, outputFoot, outputFootSz), ASN_PARSE_E); - AssertIntEQ(wc_PKCS7_VerifySignedData_ex(&pkcs7, hashBuf, 0, outputHead, + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, 0, outputHead, outputHeadSz, outputFoot, outputFootSz), ASN_PARSE_E); - AssertIntEQ(wc_PKCS7_VerifySignedData_ex(&pkcs7, hashBuf, hashSz, NULL, + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, NULL, outputHeadSz, outputFoot, outputFootSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_VerifySignedData_ex(&pkcs7, hashBuf, hashSz, + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, outputHead, 0, outputFoot, outputFootSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_VerifySignedData_ex(&pkcs7, hashBuf, hashSz, + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, outputHead, outputHeadSz, NULL, outputFootSz), ASN_PARSE_E); - AssertIntEQ(wc_PKCS7_VerifySignedData_ex(&pkcs7, hashBuf, hashSz, + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, outputHead, outputHeadSz, outputFoot, 0), ASN_PARSE_E); printf(resultFmt, passed); - wc_PKCS7_Free(&pkcs7); + wc_PKCS7_Free(pkcs7); wc_FreeRng(&rng); #endif @@ -15364,7 +15371,7 @@ static void test_wc_PKCS7_EncodeSignedData_ex(void) static void test_wc_PKCS7_VerifySignedData(void) { #if defined(HAVE_PKCS7) - PKCS7 pkcs7; + PKCS7* pkcs7; WC_RNG rng; byte output[FOURK_BUF]; byte badOut[0]; @@ -15439,34 +15446,36 @@ static void test_wc_PKCS7_VerifySignedData(void) XMEMSET(output, 0, outputSz); AssertIntEQ(wc_InitRng(&rng), 0); - AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, INVALID_DEVID), 0); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, cert, certSz), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, cert, certSz), 0); printf(testingFmt, "wc_PKCS7_VerifySignedData()"); - pkcs7.content = data; - pkcs7.contentSz = (word32)sizeof(data); - pkcs7.privateKey = key; - pkcs7.privateKeySz = (word32)sizeof(key); - pkcs7.encryptOID = RSAk; - pkcs7.hashOID = SHAh; - pkcs7.rng = &rng; + pkcs7->content = data; + pkcs7->contentSz = (word32)sizeof(data); + pkcs7->privateKey = key; + pkcs7->privateKeySz = (word32)sizeof(key); + pkcs7->encryptOID = RSAk; + pkcs7->hashOID = SHAh; + pkcs7->rng = &rng; - AssertIntGT(wc_PKCS7_EncodeSignedData(&pkcs7, output, outputSz), 0); - wc_PKCS7_Free(&pkcs7); - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, NULL, 0), 0); - AssertIntEQ(wc_PKCS7_VerifySignedData(&pkcs7, output, outputSz), 0); + AssertIntGT(wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz), 0); + wc_PKCS7_Free(pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, output, outputSz), 0); /* Test bad args. */ AssertIntEQ(wc_PKCS7_VerifySignedData(NULL, output, outputSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_VerifySignedData(&pkcs7, NULL, outputSz), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_VerifySignedData(&pkcs7, badOut, + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, NULL, outputSz), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, badOut, badOutSz), BAD_FUNC_ARG); printf(resultFmt, passed); - wc_PKCS7_Free(&pkcs7); + wc_PKCS7_Free(pkcs7); wc_FreeRng(&rng); #endif } /* END test_wc_PKCS7_VerifySignedData() */ @@ -15478,7 +15487,7 @@ static void test_wc_PKCS7_VerifySignedData(void) static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void) { #if defined(HAVE_PKCS7) - PKCS7 pkcs7; + PKCS7* pkcs7; word32 tempWrd32 = 0; byte* tmpBytePtr = NULL; const char input[] = "Test data to encode."; @@ -15642,42 +15651,44 @@ static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void) printf(testingFmt, "wc_PKCS7_EncodeEnvelopedData()"); - AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, devId), 0); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, devId), 0); testSz = (int)sizeof(testVectors)/(int)sizeof(pkcs7EnvelopedVector); for (i = 0; i < testSz; i++) { - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, (testVectors + i)->cert, + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, (testVectors + i)->cert, (word32)(testVectors + i)->certSz), 0); - pkcs7.content = (byte*)(testVectors + i)->content; - pkcs7.contentSz = (testVectors + i)->contentSz; - pkcs7.contentOID = (testVectors + i)->contentOID; - pkcs7.encryptOID = (testVectors + i)->encryptOID; - pkcs7.keyWrapOID = (testVectors + i)->keyWrapOID; - pkcs7.keyAgreeOID = (testVectors + i)->keyAgreeOID; - pkcs7.privateKey = (testVectors + i)->privateKey; - pkcs7.privateKeySz = (testVectors + i)->privateKeySz; + pkcs7->content = (byte*)(testVectors + i)->content; + pkcs7->contentSz = (testVectors + i)->contentSz; + pkcs7->contentOID = (testVectors + i)->contentOID; + pkcs7->encryptOID = (testVectors + i)->encryptOID; + pkcs7->keyWrapOID = (testVectors + i)->keyWrapOID; + pkcs7->keyAgreeOID = (testVectors + i)->keyAgreeOID; + pkcs7->privateKey = (testVectors + i)->privateKey; + pkcs7->privateKeySz = (testVectors + i)->privateKeySz; - AssertIntGE(wc_PKCS7_EncodeEnvelopedData(&pkcs7, output, + AssertIntGE(wc_PKCS7_EncodeEnvelopedData(pkcs7, output, (word32)sizeof(output)), 0); - decodedSz = wc_PKCS7_DecodeEnvelopedData(&pkcs7, output, + decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, output, (word32)sizeof(output), decoded, (word32)sizeof(decoded)); AssertIntGE(decodedSz, 0); /* Verify the size of each buffer. */ AssertIntEQ((word32)sizeof(input)/sizeof(char), decodedSz); /* Don't free the last time through the loop. */ if (i < testSz - 1 ){ - wc_PKCS7_Free(&pkcs7); + wc_PKCS7_Free(pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); } } /* END test loop. */ /* Test bad args. */ AssertIntEQ(wc_PKCS7_EncodeEnvelopedData(NULL, output, (word32)sizeof(output)), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeEnvelopedData(&pkcs7, NULL, + AssertIntEQ(wc_PKCS7_EncodeEnvelopedData(pkcs7, NULL, (word32)sizeof(output)), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_EncodeEnvelopedData(&pkcs7, output, 0), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_EncodeEnvelopedData(pkcs7, output, 0), BAD_FUNC_ARG); printf(resultFmt, passed); /* Decode. */ @@ -15685,39 +15696,39 @@ static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void) AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(NULL, output, (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(&pkcs7, output, + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, (word32)sizeof(output), NULL, (word32)sizeof(decoded)), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(&pkcs7, output, + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, (word32)sizeof(output), decoded, 0), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(&pkcs7, NULL, + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, NULL, (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); - AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(&pkcs7, output, 0, decoded, + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, 0, decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); /* Should get a return of BAD_FUNC_ARG with structure data. Order matters.*/ - tempWrd32 = pkcs7.singleCertSz; - pkcs7.singleCertSz = 0; - AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(&pkcs7, output, + tempWrd32 = pkcs7->singleCertSz; + pkcs7->singleCertSz = 0; + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); - pkcs7.singleCertSz = tempWrd32; - tempWrd32 = pkcs7.privateKeySz; - pkcs7.privateKeySz = 0; - AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(&pkcs7, output, + pkcs7->singleCertSz = tempWrd32; + tempWrd32 = pkcs7->privateKeySz; + pkcs7->privateKeySz = 0; + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); - pkcs7.privateKeySz = tempWrd32; - tmpBytePtr = pkcs7.singleCert; - pkcs7.singleCert = NULL; - AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(&pkcs7, output, + pkcs7->privateKeySz = tempWrd32; + tmpBytePtr = pkcs7->singleCert; + pkcs7->singleCert = NULL; + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); - pkcs7.singleCert = tmpBytePtr; - tmpBytePtr = pkcs7.privateKey; - pkcs7.privateKey = NULL; - AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(&pkcs7, output, + pkcs7->singleCert = tmpBytePtr; + tmpBytePtr = pkcs7->privateKey; + pkcs7->privateKey = NULL; + AssertIntEQ(wc_PKCS7_DecodeEnvelopedData(pkcs7, output, (word32)sizeof(output), decoded, (word32)sizeof(decoded)), BAD_FUNC_ARG); - pkcs7.privateKey = tmpBytePtr; + pkcs7->privateKey = tmpBytePtr; printf(resultFmt, passed); - wc_PKCS7_Free(&pkcs7); + wc_PKCS7_Free(pkcs7); #ifndef NO_RSA if (rsaCert) { XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index c02b3aba5..fa6a34d1f 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -8295,6 +8295,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, } #endif pkcs7->state = WC_PKCS7_STAGE2; + FALL_THROUGH /* end of stage 1 */ case WC_PKCS7_STAGE2: @@ -8335,6 +8336,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, } #endif pkcs7->state = WC_PKCS7_STAGE3; + FALL_THROUGH /* end of stage 2 */ case WC_PKCS7_STAGE3: @@ -8390,6 +8392,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, pkcs7->stream->vers = version; #endif pkcs7->state = WC_PKCS7_STAGE4; + FALL_THROUGH /* end of stage 3 */ /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ @@ -8436,6 +8439,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, } #endif pkcs7->state = WC_PKCS7_STAGE5; + FALL_THROUGH /* end of stage 4 */ case WC_PKCS7_STAGE5: @@ -8490,6 +8494,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, #endif pkcs7->state = WC_PKCS7_STAGE6; + FALL_THROUGH /* end of stage 5 */ case WC_PKCS7_STAGE6: From 2cc89936e3679f46461eb340f23a65579872786e Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 9 Oct 2018 09:56:57 -0600 Subject: [PATCH 26/56] add semicolon after FALL_THROUGH --- wolfcrypt/src/pkcs7.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index fa6a34d1f..ea8b76828 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -8295,7 +8295,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, } #endif pkcs7->state = WC_PKCS7_STAGE2; - FALL_THROUGH + FALL_THROUGH; /* end of stage 1 */ case WC_PKCS7_STAGE2: @@ -8336,7 +8336,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, } #endif pkcs7->state = WC_PKCS7_STAGE3; - FALL_THROUGH + FALL_THROUGH; /* end of stage 2 */ case WC_PKCS7_STAGE3: @@ -8392,7 +8392,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, pkcs7->stream->vers = version; #endif pkcs7->state = WC_PKCS7_STAGE4; - FALL_THROUGH + FALL_THROUGH; /* end of stage 3 */ /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ @@ -8439,7 +8439,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, } #endif pkcs7->state = WC_PKCS7_STAGE5; - FALL_THROUGH + FALL_THROUGH; /* end of stage 4 */ case WC_PKCS7_STAGE5: @@ -8494,7 +8494,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, #endif pkcs7->state = WC_PKCS7_STAGE6; - FALL_THROUGH + FALL_THROUGH; /* end of stage 5 */ case WC_PKCS7_STAGE6: From cc05c4631809ab4b5b6f518f9f87badd39f2c9c9 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Tue, 9 Oct 2018 10:23:47 -0600 Subject: [PATCH 27/56] add single-shot API for generating CMS Signed FirmwarePkgData --- wolfcrypt/src/pkcs7.c | 15 +++++++++++++++ wolfssl/wolfcrypt/pkcs7.h | 17 +++++++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index ea8b76828..b1ea4c831 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -1873,6 +1873,21 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) } +/* build PKCS#7 signedData content type with inner type set to FirmwarePkgData, + return size of generated bundle on success, negative upon error */ +int wc_PKCS7_EncodeSignedFirmwarePkgData(PKCS7* pkcs7, byte* output, + word32 outputSz) +{ + if (pkcs7 == NULL || output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + + /* force content type to FirmwarePkgData */ + pkcs7->contentOID = FIRMWARE_PKG_DATA; + + return wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); +} + + #ifndef NO_RSA /* returns size of signature put into out, negative on error */ diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 8999c4455..f7cfde6be 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -263,16 +263,21 @@ WOLFSSL_API int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, /* CMS/PKCS#7 SignedData */ WOLFSSL_API int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, - byte* output, word32 outputSz); + byte* output, word32 outputSz); WOLFSSL_API int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf, - word32 hashSz, byte* outputHead, word32* outputHeadSz, byte* outputFoot, - word32* outputFootSz); + word32 hashSz, byte* outputHead, + word32* outputHeadSz, + byte* outputFoot, + word32* outputFootSz); +WOLFSSL_API int wc_PKCS7_EncodeSignedFirmwarePkgData(PKCS7* pkcs7, + byte* output, word32 outputSz); WOLFSSL_API void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag); WOLFSSL_API int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, - byte* pkiMsg, word32 pkiMsgSz); + byte* pkiMsg, word32 pkiMsgSz); WOLFSSL_API int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf, - word32 hashSz, byte* pkiMsgHead, word32 pkiMsgHeadSz, byte* pkiMsgFoot, - word32 pkiMsgFootSz); + word32 hashSz, byte* pkiMsgHead, + word32 pkiMsgHeadSz, byte* pkiMsgFoot, + word32 pkiMsgFootSz); /* EnvelopedData and AuthEnvelopedData RecipientInfo functions */ WOLFSSL_API int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, From ed7cd54a912a46d08f4a28a9ec4148511510b779 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Tue, 9 Oct 2018 15:56:14 -0600 Subject: [PATCH 28/56] add single-shot API for generating CMS Signed Encrypted FirmwarePkgData --- wolfcrypt/src/pkcs7.c | 191 +++++++++++++++++++++++++++++++++----- wolfssl/wolfcrypt/pkcs7.h | 25 ++++- 2 files changed, 193 insertions(+), 23 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index b1ea4c831..8769d32d4 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -1873,20 +1873,182 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) } -/* build PKCS#7 signedData content type with inner type set to FirmwarePkgData, - return size of generated bundle on success, negative upon error */ -int wc_PKCS7_EncodeSignedFirmwarePkgData(PKCS7* pkcs7, byte* output, - word32 outputSz) +/* Single-shot API to generate a CMS SignedData bundle that encapsulates a + * content of type FirmwarePkgData. Any recipient certificates should be + * loaded into the PKCS7 structure prior to calling this function, using + * wc_PKCS7_InitWithCert() and/or wc_PKCS7_AddCertificate(). + * + * pkcs7 - pointer to initialized PKCS7 struct + * privateKey - private RSA/ECC key, used for signing SignedData + * privateKeySz - size of privateKey, octets + * signOID - public key algorithm OID, used for sign operation + * hashOID - hash algorithm OID, used for signature generation + * content - content to be encapsulated, of type FirmwarePkgData + * contentSz - size of content, octets + * signedAttribs - optional signed attributes + * signedAttribsSz - number of PKCS7Attrib members in signedAttribs + * heap - user heap pointer, otherwise NULL if not needed + * devId - dev ID if used, otherwise 0 if not needed + * output - output buffer for final bundle + * outputSz - size of output buffer, octets + * + * Returns length of generated bundle on success, negative upon error. */ +int wc_PKCS7_EncodeSignedFPD(PKCS7* pkcs7, byte* privateKey, + word32 privateKeySz, int signOID, int hashOID, + byte* content, word32 contentSz, + PKCS7Attrib* signedAttribs, word32 signedAttribsSz, + byte* output, word32 outputSz) { - if (pkcs7 == NULL || output == NULL || outputSz == 0) + int ret = 0; + WC_RNG rng; + + if (pkcs7 == NULL || privateKey == NULL || privateKeySz == 0 || + content == NULL || contentSz == 0 || output == NULL || outputSz == 0) return BAD_FUNC_ARG; - /* force content type to FirmwarePkgData */ - pkcs7->contentOID = FIRMWARE_PKG_DATA; + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; - return wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + pkcs7->rng = &rng; + pkcs7->content = content; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + pkcs7->hashOID = hashOID; + pkcs7->encryptOID = signOID; + pkcs7->privateKey = privateKey; + pkcs7->privateKeySz = privateKeySz; + pkcs7->signedAttribs = signedAttribs; + pkcs7->signedAttribsSz = signedAttribsSz; + + ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + if (ret <= 0) { + WOLFSSL_MSG("Error encoding CMS SignedData content type"); + wc_FreeRng(&rng); + return ret; + } + + wc_FreeRng(&rng); + + return ret; } +#ifndef NO_PKCS7_ENCRYPTED_DATA + +/* Single-shot API to generate a CMS SignedData bundle that encapsulates a + * CMS EncryptedData bundle. Content of inner EncryptedData is set to that + * of FirmwarePkgData. Any recipient certificates should be loaded into the + * PKCS7 structure prior to calling this function, using wc_PKCS7_InitWithCert() + * and/or wc_PKCS7_AddCertificate(). + * + * pkcs7 - pointer to initialized PKCS7 struct + * encryptKey - encryption key used for encrypting EncryptedData + * encryptKeySz - size of encryptKey, octets + * privateKey - private RSA/ECC key, used for signing SignedData + * privateKeySz - size of privateKey, octets + * encryptOID - encryption algorithm OID, to be used as encryption + * algorithm for EncryptedData + * signOID - public key algorithm OID, to be used for sign + * operation in SignedData generation + * hashOID - hash algorithm OID, to be used for signature in + * SignedData generation + * content - content to be encapsulated + * contentSz - size of content, octets + * unprotectedAttribs - optional unprotected attributes, for EncryptedData + * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs + * signedAttribs - optional signed attributes, for SignedData + * signedAttribsSz - number of PKCS7Attrib members in signedAttribs + * heap - user heap pointer, otherwise NULL if not needed + * devId - dev ID if used, otherwise 0 if not needed + * output - output buffer for final bundle + * outputSz - size of output buffer, octets + * + * Returns length of generated bundle on success, negative upon error. */ +int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, byte* encryptKey, + word32 encryptKeySz, byte* privateKey, + word32 privateKeySz, int encryptOID, + int signOID, int hashOID, + byte* content, word32 contentSz, + PKCS7Attrib* unprotectedAttribs, + word32 unprotectedAttribsSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, + byte* output, word32 outputSz) +{ + int ret = 0, encryptedSz = 0; + byte* encrypted = NULL; + WC_RNG rng; + + if (pkcs7 == NULL || encryptKey == NULL || encryptKeySz == 0 || + privateKey == NULL || privateKeySz == 0 || content == NULL || + contentSz == 0 || output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* 1: build up EncryptedData using FirmwarePkgData type, use output + * buffer as tmp for storage and to get size */ + + /* set struct elements, inner content type is FirmwarePkgData */ + pkcs7->content = content; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + pkcs7->encryptOID = encryptOID; + pkcs7->encryptionKey = encryptKey; + pkcs7->encryptionKeySz = encryptKeySz; + pkcs7->unprotectedAttribs = unprotectedAttribs; + pkcs7->unprotectedAttribsSz = unprotectedAttribsSz; + + encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, output, outputSz); + if (encryptedSz < 0) { + WOLFSSL_MSG("Error encoding CMS EncryptedData content type"); + return encryptedSz; + } + + /* save encryptedData, reset output buffer and struct */ + encrypted = (byte*)XMALLOC(encryptedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (encrypted == NULL) { + wc_PKCS7_Free(pkcs7); + return MEMORY_E; + } + XMEMSET(encrypted, 0, encryptedSz); + + XMEMCPY(encrypted, output, encryptedSz); + ForceZero(output, outputSz); + + ret = wc_InitRng(&rng); + if (ret != 0) { + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* 2: build up SignedData, encapsulating EncryptedData */ + pkcs7->rng = &rng; + pkcs7->content = encrypted; + pkcs7->contentSz = encryptedSz; + pkcs7->contentOID = ENCRYPTED_DATA; + pkcs7->hashOID = hashOID; + pkcs7->encryptOID = signOID; + pkcs7->privateKey = privateKey; + pkcs7->privateKeySz = privateKeySz; + pkcs7->signedAttribs = signedAttribs; + pkcs7->signedAttribsSz = signedAttribsSz; + + ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + if (ret <= 0) { + WOLFSSL_MSG("Error encoding CMS SignedData content type"); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + return ret; + } + + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + + return ret; +} + +#endif /* NO_PKCS7_ENCRYPTED_DATA */ + #ifndef NO_RSA @@ -2907,19 +3069,6 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, return ASN_VERSION_E; } - /* Get the sequence of digestAlgorithm */ - if (GetAlgoId(pkiMsg2, &idx, &hashOID, oidHashType, pkiMsg2Sz) < 0) { - return ASN_PARSE_E; - } - pkcs7->hashOID = (int)hashOID; - - /* Get the sequence of IssuerAndSerialNumber */ - if (GetSequence(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; - - /* Skip it */ - idx += length; - /* Get the sequence of digestAlgorithm */ if (GetAlgoId(pkiMsg2, &idx, &hashOID, oidHashType, pkiMsg2Sz) < 0) { return ASN_PARSE_E; diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index f7cfde6be..80aa78d3b 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -269,8 +269,6 @@ WOLFSSL_API int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf, word32* outputHeadSz, byte* outputFoot, word32* outputFootSz); -WOLFSSL_API int wc_PKCS7_EncodeSignedFirmwarePkgData(PKCS7* pkcs7, - byte* output, word32 outputSz); WOLFSSL_API void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag); WOLFSSL_API int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz); @@ -279,6 +277,29 @@ WOLFSSL_API int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf, word32 pkiMsgHeadSz, byte* pkiMsgFoot, word32 pkiMsgFootSz); +/* CMS single-shot API for Signed FirmwarePkgData */ +WOLFSSL_API int wc_PKCS7_EncodeSignedFPD(PKCS7* pkcs7, byte* privateKey, + word32 privateKeySz, int signOID, + int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, byte* output, + word32 outputSz); +#ifndef NO_PKCS7_ENCRYPTED_DATA +/* CMS single-shot API for Signed Encrypted FirmwarePkgData */ +WOLFSSL_API int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, + byte* encryptKey, word32 encryptKeySz, + byte* privateKey, word32 privateKeySz, + int encryptOID, int signOID, + int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* unprotectedAttribs, + word32 unprotectedAttribsSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, + byte* output, word32 outputSz); +#endif /* NO_PKCS7_ENCRYPTED_DATA */ + /* EnvelopedData and AuthEnvelopedData RecipientInfo functions */ WOLFSSL_API int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, int options); From 175e32b4681eea4ad723b02df499b1fb66dde23d Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 10 Oct 2018 10:53:03 -0600 Subject: [PATCH 29/56] add single-shot API for generating CMS Signed Compressed FirmwarePkgData --- wolfcrypt/src/pkcs7.c | 101 ++++++++++++++++++++++++++++++++++++-- wolfssl/wolfcrypt/pkcs7.h | 10 ++++ 2 files changed, 107 insertions(+), 4 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 8769d32d4..ce64e24b3 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -1887,8 +1887,6 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) * contentSz - size of content, octets * signedAttribs - optional signed attributes * signedAttribsSz - number of PKCS7Attrib members in signedAttribs - * heap - user heap pointer, otherwise NULL if not needed - * devId - dev ID if used, otherwise 0 if not needed * output - output buffer for final bundle * outputSz - size of output buffer, octets * @@ -1958,8 +1956,6 @@ int wc_PKCS7_EncodeSignedFPD(PKCS7* pkcs7, byte* privateKey, * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs * signedAttribs - optional signed attributes, for SignedData * signedAttribsSz - number of PKCS7Attrib members in signedAttribs - * heap - user heap pointer, otherwise NULL if not needed - * devId - dev ID if used, otherwise 0 if not needed * output - output buffer for final bundle * outputSz - size of output buffer, octets * @@ -2049,6 +2045,103 @@ int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, byte* encryptKey, #endif /* NO_PKCS7_ENCRYPTED_DATA */ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) +/* Single-shot API to generate a CMS SignedData bundle that encapsulates a + * CMS CompressedData bundle. Content of inner CompressedData is set to that + * of FirmwarePkgData. Any recipient certificates should be loaded into the + * PKCS7 structure prior to calling this function, using wc_PKCS7_InitWithCert() + * and/or wc_PKCS7_AddCertificate(). + * + * pkcs7 - pointer to initialized PKCS7 struct + * privateKey - private RSA/ECC key, used for signing SignedData + * privateKeySz - size of privateKey, octets + * signOID - public key algorithm OID, to be used for sign + * operation in SignedData generation + * hashOID - hash algorithm OID, to be used for signature in + * SignedData generation + * content - content to be encapsulated + * contentSz - size of content, octets + * signedAttribs - optional signed attributes, for SignedData + * signedAttribsSz - number of PKCS7Attrib members in signedAttribs + * output - output buffer for final bundle + * outputSz - size of output buffer, octets + * + * Returns length of generated bundle on success, negative upon error. */ +int wc_PKCS7_EncodeSignedCompressedFPD(PKCS7* pkcs7, byte* privateKey, + word32 privateKeySz, int signOID, + int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, byte* output, + word32 outputSz) +{ + int ret = 0, compressedSz = 0; + byte* compressed = NULL; + WC_RNG rng; + + if (pkcs7 == NULL || privateKey == NULL || privateKeySz == 0 || + content == NULL || contentSz == 0 || output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* 1: build up CompressedData using FirmwarePkgData type, use output + * buffer as tmp for storage and to get size */ + + /* set struct elements, inner content type is FirmwarePkgData */ + pkcs7->content = content; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + + compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, output, outputSz); + if (compressedSz < 0) { + WOLFSSL_MSG("Error encoding CMS CompressedData content type"); + return compressedSz; + } + + /* save compressedData, reset output buffer and struct */ + compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (compressed == NULL) { + wc_PKCS7_Free(pkcs7); + return MEMORY_E; + } + XMEMSET(compressed, 0, compressedSz); + + XMEMCPY(compressed, output, compressedSz); + ForceZero(output, outputSz); + + ret = wc_InitRng(&rng); + if (ret != 0) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* 2: build up SignedData, encapsulating EncryptedData */ + pkcs7->rng = &rng; + pkcs7->content = compressed; + pkcs7->contentSz = compressedSz; + pkcs7->contentOID = COMPRESSED_DATA; + pkcs7->hashOID = hashOID; + pkcs7->encryptOID = signOID; + pkcs7->privateKey = privateKey; + pkcs7->privateKeySz = privateKeySz; + pkcs7->signedAttribs = signedAttribs; + pkcs7->signedAttribsSz = signedAttribsSz; + + ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + if (ret <= 0) { + WOLFSSL_MSG("Error encoding CMS SignedData content type"); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + return ret; + } + + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + + return ret; +} +#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + #ifndef NO_RSA diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 80aa78d3b..9244f2314 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -299,6 +299,16 @@ WOLFSSL_API int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, word32 signedAttribsSz, byte* output, word32 outputSz); #endif /* NO_PKCS7_ENCRYPTED_DATA */ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) +/* CMS single-shot API for Signed Compressed FirmwarePkgData */ +WOLFSSL_API int wc_PKCS7_EncodeSignedCompressedFPD(PKCS7* pkcs7, + byte* privateKey, word32 privateKeySz, + int signOID, int hashOID, + byte* content, word32 contentSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, byte* output, + word32 outputSz); +#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ /* EnvelopedData and AuthEnvelopedData RecipientInfo functions */ WOLFSSL_API int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, From c9f75fe7b4401097a1fd41acb615bc7be15cb675 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 10 Oct 2018 13:46:11 -0600 Subject: [PATCH 30/56] add test cases for CMS Signed-Encrypted and Signed-Compressed FirmwarePkgData to test.c --- .gitignore | 15 ++ Makefile.am | 17 +- wolfcrypt/test/test.c | 546 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 538 insertions(+), 40 deletions(-) diff --git a/.gitignore b/.gitignore index 3f53b13af..5645c9762 100644 --- a/.gitignore +++ b/.gitignore @@ -160,6 +160,21 @@ pkcs7signedData_RSA_SHA384.der pkcs7signedData_RSA_SHA512.der pkcs7signedData_RSA_SHA.der pkcs7signedData_RSA_SHA_noattr.der +pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256.der +pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der +pkcs7signedCompressedFirmwarePkgData_RSA_SHA256.der +pkcs7signedCompressedFirmwarePkgData_RSA_SHA256_noattr.der +pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256.der +pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256_noattr.der +pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256.der +pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256_noattr.der +pkcs7signedFirmwarePkgData_ECDSA_SHA256.der +pkcs7signedFirmwarePkgData_ECDSA_SHA256_SKID.der +pkcs7signedFirmwarePkgData_ECDSA_SHA256_noattr.der +pkcs7signedFirmwarePkgData_RSA_SHA256.der +pkcs7signedFirmwarePkgData_RSA_SHA256_SKID.der +pkcs7signedFirmwarePkgData_RSA_SHA256_noattr.der +pkcs7signedFirmwarePkgData_RSA_SHA256_with_ca_cert.der diff sslSniffer/sslSnifferTest/tracefile.txt tracefile.txt diff --git a/Makefile.am b/Makefile.am index 1f3923e68..0f8ed7c78 100644 --- a/Makefile.am +++ b/Makefile.am @@ -98,7 +98,22 @@ CLEANFILES+= cert.der \ pkcs7signedData_ECDSA_SHA256_custom_contentType.der \ pkcs7signedData_ECDSA_SHA256_SKID.der \ pkcs7signedData_ECDSA_SHA384.der \ - pkcs7signedData_ECDSA_SHA512.der + pkcs7signedData_ECDSA_SHA512.der \ + pkcs7signedFirmwarePkgData_ECDSA_SHA256.der \ + pkcs7signedFirmwarePkgData_ECDSA_SHA256_SKID.der \ + pkcs7signedFirmwarePkgData_ECDSA_SHA256_noattr.der \ + pkcs7signedFirmwarePkgData_RSA_SHA256.der \ + pkcs7signedFirmwarePkgData_RSA_SHA256_SKID.der \ + pkcs7signedFirmwarePkgData_RSA_SHA256_noattr.der \ + pkcs7signedFirmwarePkgData_RSA_SHA256_with_ca_cert.der \ + pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256.der \ + pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der \ + pkcs7signedCompressedFirmwarePkgData_RSA_SHA256.der \ + pkcs7signedCompressedFirmwarePkgData_RSA_SHA256_noattr.der \ + pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256.der \ + pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256_noattr.der \ + pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256.der \ + pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256_noattr.der exampledir = $(docdir)/example dist_example_DATA= diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 1d2a1b1da..c23697f5b 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -321,15 +321,15 @@ int scrypt_test(void); int compress_test(void); #endif #ifdef HAVE_PKCS7 - int pkcs7enveloped_test(void); - int pkcs7authenveloped_test(void); - int pkcs7signed_test(void); #ifndef NO_PKCS7_ENCRYPTED_DATA int pkcs7encrypted_test(void); #endif #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) int pkcs7compressed_test(void); #endif + int pkcs7signed_test(void); + int pkcs7enveloped_test(void); + int pkcs7authenveloped_test(void); #endif #if !defined(NO_ASN_TIME) && !defined(NO_RSA) && defined(WOLFSSL_TEST_CERT) int cert_test(void); @@ -952,21 +952,6 @@ initDefaultName(); #endif #ifdef HAVE_PKCS7 - if ( (ret = pkcs7enveloped_test()) != 0) - return err_sys("PKCS7enveloped test failed!\n", ret); - else - printf( "PKCS7enveloped test passed!\n"); - - if ( (ret = pkcs7authenveloped_test()) != 0) - return err_sys("PKCS7authenveloped test failed!\n", ret); - else - printf( "PKCS7authenveloped test passed!\n"); - - if ( (ret = pkcs7signed_test()) != 0) - return err_sys("PKCS7signed test failed!\n", ret); - else - printf( "PKCS7signed test passed!\n"); - #ifndef NO_PKCS7_ENCRYPTED_DATA if ( (ret = pkcs7encrypted_test()) != 0) return err_sys("PKCS7encrypted test failed!\n", ret); @@ -979,6 +964,20 @@ initDefaultName(); else printf( "PKCS7compressed test passed!\n"); #endif + if ( (ret = pkcs7signed_test()) != 0) + return err_sys("PKCS7signed test failed!\n", ret); + else + printf( "PKCS7signed test passed!\n"); + + if ( (ret = pkcs7enveloped_test()) != 0) + return err_sys("PKCS7enveloped test failed!\n", ret); + else + printf( "PKCS7enveloped test passed!\n"); + + if ( (ret = pkcs7authenveloped_test()) != 0) + return err_sys("PKCS7authenveloped test failed!\n", ret); + else + printf( "PKCS7authenveloped test passed!\n"); #endif #ifdef HAVE_VALGRIND @@ -20488,7 +20487,7 @@ typedef struct { const byte* content; word32 contentSz; int hashOID; - int encryptOID; + int signOID; byte* privateKey; word32 privateKeySz; byte* cert; @@ -20502,6 +20501,12 @@ typedef struct { byte* contentType; word32 contentTypeSz; int sidType; + int encryptOID; /* for single-shot encrypt alg OID */ + int encCompFlag; /* for single-shot. 1 = enc, 2 = comp, 3 = both*/ + byte* encryptKey; /* for single-shot, encryptedData */ + word32 encryptKeySz; /* for single-shot, encryptedData */ + PKCS7Attrib* unprotectedAttribs; /* for single-shot, encryptedData */ + word32 unprotectedAttribsSz; /* for single-shot, encryptedData */ } pkcs7SignedVector; @@ -20570,68 +20575,76 @@ static int pkcs7signed_run_vectors( {data, (word32)sizeof(data), SHAh, RSAk, rsaClientPrivKeyBuf, rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA.der", 0, NULL, 0, 0}, + "pkcs7signedData_RSA_SHA.der", 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0}, /* RSA with SHA, no signed attributes */ {data, (word32)sizeof(data), SHAh, RSAk, rsaClientPrivKeyBuf, rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, NULL, 0, - "pkcs7signedData_RSA_SHA_noattr.der", 0, NULL, 0, 0}, + "pkcs7signedData_RSA_SHA_noattr.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0}, #endif #ifdef WOLFSSL_SHA224 /* RSA with SHA224 */ {data, (word32)sizeof(data), SHA224h, RSAk, rsaClientPrivKeyBuf, rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA224.der", 0, NULL, 0, 0}, + "pkcs7signedData_RSA_SHA224.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0}, #endif #ifndef NO_SHA256 /* RSA with SHA256 */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA256.der", 0, NULL, 0, 0}, + "pkcs7signedData_RSA_SHA256.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0}, /* RSA with SHA256 and SubjectKeyIdentifier in SignerIdentifier */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA256_SKID.der", 0, NULL, 0, CMS_SKID}, + "pkcs7signedData_RSA_SHA256_SKID.der", 0, NULL, 0, CMS_SKID, 0, 0, + NULL, 0, NULL, 0}, /* RSA with SHA256 and custom contentType */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_RSA_SHA256_custom_contentType.der", 0, - customContentType, sizeof(customContentType), 0}, + customContentType, sizeof(customContentType), 0, 0, 0, NULL, 0, + NULL, 0}, /* RSA with SHA256 and FirmwarePkgData contentType */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_RSA_SHA256_firmwarePkgData.der", - FIRMWARE_PKG_DATA, NULL, 0, 0}, + FIRMWARE_PKG_DATA, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0}, /* RSA with SHA256 using server cert and ca cert */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaServerPrivKeyBuf, rsaServerPrivKeyBufSz, rsaServerCertBuf, rsaServerCertBufSz, rsaCaCertBuf, rsaCaCertBufSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA256_with_ca_cert.der", 0, NULL, 0, 0}, + "pkcs7signedData_RSA_SHA256_with_ca_cert.der", 0, NULL, 0, 0, 0, 0, + NULL, 0, NULL, 0}, #endif #if defined(WOLFSSL_SHA384) /* RSA with SHA384 */ {data, (word32)sizeof(data), SHA384h, RSAk, rsaClientPrivKeyBuf, rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA384.der", 0, NULL, 0, 0}, + "pkcs7signedData_RSA_SHA384.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0}, #endif #if defined(WOLFSSL_SHA512) /* RSA with SHA512 */ {data, (word32)sizeof(data), SHA512h, RSAk, rsaClientPrivKeyBuf, rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_RSA_SHA512.der", 0, NULL, 0, 0}, + "pkcs7signedData_RSA_SHA512.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0}, #endif #endif /* NO_RSA */ @@ -20641,61 +20654,69 @@ static int pkcs7signed_run_vectors( {data, (word32)sizeof(data), SHAh, ECDSAk, eccClientPrivKeyBuf, eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA.der", 0, NULL, 0, 0}, + "pkcs7signedData_ECDSA_SHA.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0}, /* ECDSA with SHA, no signed attributes */ {data, (word32)sizeof(data), SHAh, ECDSAk, eccClientPrivKeyBuf, eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, NULL, 0, - "pkcs7signedData_ECDSA_SHA_noattr.der", 0, NULL, 0, 0}, + "pkcs7signedData_ECDSA_SHA_noattr.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0}, #endif #ifdef WOLFSSL_SHA224 /* ECDSA with SHA224 */ {data, (word32)sizeof(data), SHA224h, ECDSAk, eccClientPrivKeyBuf, eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA224.der", 0, NULL, 0, 0}, + "pkcs7signedData_ECDSA_SHA224.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0}, #endif #ifndef NO_SHA256 /* ECDSA with SHA256 */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA256.der", 0, NULL, 0, 0}, + "pkcs7signedData_ECDSA_SHA256.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0}, /* ECDSA with SHA256 and SubjectKeyIdentifier in SigherIdentifier */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA256_SKID.der", 0, NULL, 0, CMS_SKID}, + "pkcs7signedData_ECDSA_SHA256_SKID.der", 0, NULL, 0, CMS_SKID, 0, 0, + NULL, 0, NULL, 0}, /* ECDSA with SHA256 and custom contentType */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_ECDSA_SHA256_custom_contentType.der", 0, - customContentType, sizeof(customContentType), 0}, + customContentType, sizeof(customContentType), 0, 0, 0, NULL, 0, + NULL, 0}, /* ECDSA with SHA256 and FirmwarePkgData contentType */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedData_ECDSA_SHA256_firmwarePkgData.der", - FIRMWARE_PKG_DATA, NULL, 0, 0}, + FIRMWARE_PKG_DATA, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0}, #endif #ifdef WOLFSSL_SHA384 /* ECDSA with SHA384 */ {data, (word32)sizeof(data), SHA384h, ECDSAk, eccClientPrivKeyBuf, eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA384.der", 0, NULL, 0, 0}, + "pkcs7signedData_ECDSA_SHA384.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0}, #endif #ifdef WOLFSSL_SHA512 /* ECDSA with SHA512 */ {data, (word32)sizeof(data), SHA512h, ECDSAk, eccClientPrivKeyBuf, eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), - "pkcs7signedData_ECDSA_SHA512.der", 0, NULL, 0, 0}, + "pkcs7signedData_ECDSA_SHA512.der", 0, NULL, 0, 0, 0, 0, NULL, 0, + NULL, 0}, #endif #endif /* HAVE_ECC */ }; @@ -20757,7 +20778,7 @@ static int pkcs7signed_run_vectors( pkcs7->contentSz = testVectors[i].contentSz; pkcs7->contentOID = testVectors[i].contentOID; pkcs7->hashOID = testVectors[i].hashOID; - pkcs7->encryptOID = testVectors[i].encryptOID; + pkcs7->encryptOID = testVectors[i].signOID; pkcs7->privateKey = testVectors[i].privateKey; pkcs7->privateKeySz = testVectors[i].privateKeySz; pkcs7->signedAttribs = testVectors[i].signedAttribs; @@ -20982,6 +21003,436 @@ static int pkcs7signed_run_vectors( } +static int pkcs7signed_run_SingleShotVectors( + byte* rsaClientCertBuf, word32 rsaClientCertBufSz, + byte* rsaClientPrivKeyBuf, word32 rsaClientPrivKeyBufSz, + byte* rsaServerCertBuf, word32 rsaServerCertBufSz, + byte* rsaServerPrivKeyBuf, word32 rsaServerPrivKeyBufSz, + byte* rsaCaCertBuf, word32 rsaCaCertBufSz, + byte* rsaCaPrivKeyBuf, word32 rsaCaPrivKeyBufSz, + byte* eccClientCertBuf, word32 eccClientCertBufSz, + byte* eccClientPrivKeyBuf, word32 eccClientPrivKeyBufSz) +{ + int ret, testSz, i; + int encodedSz; + byte* out; + word32 outSz; + WC_RNG rng; + PKCS7* pkcs7; +#ifdef PKCS7_OUTPUT_TEST_BUNDLES + FILE* file; +#endif + + const byte data[] = { /* Hello World */ + 0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f, + 0x72,0x6c,0x64 + }; + +#ifdef WOLFSSL_AES_256 + byte aes256Key[] = { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 + }; +#endif + + static byte messageTypeOid[] = + { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, + 0x09, 0x02 }; + static byte messageType[] = { 0x13, 2, '1', '9' }; + + PKCS7Attrib attribs[] = + { + { messageTypeOid, sizeof(messageTypeOid), messageType, + sizeof(messageType) }, + }; + + const pkcs7SignedVector testVectors[] = + { +#ifndef NO_RSA + #ifndef NO_SHA256 + /* Signed FirmwarePkgData, RSA, SHA256, no attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedFirmwarePkgData_RSA_SHA256_noattr.der", 0, NULL, 0, 0, + 0, 0, NULL, 0, NULL, 0}, + + /* Signed FirmwarePkgData, RSA, SHA256, attrs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedFirmwarePkgData_RSA_SHA256.der", 0, NULL, 0, 0, 0, 0, + NULL, 0, NULL, 0}, + + /* Signed FirmwarePkgData, RSA, SHA256, SubjectKeyIdentifier, attrs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedFirmwarePkgData_RSA_SHA256_SKID.der", 0, NULL, + 0, CMS_SKID, 0, 0, NULL, 0, NULL, 0}, + + /* Signed FirmwraePkgData, RSA, SHA256, server cert and ca cert, attr */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaServerPrivKeyBuf, + rsaServerPrivKeyBufSz, rsaServerCertBuf, rsaServerCertBufSz, + rsaCaCertBuf, rsaCaCertBufSz, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedFirmwarePkgData_RSA_SHA256_with_ca_cert.der", 0, NULL, + 0, 0, 0, 0, NULL, 0, NULL, 0}, + + #ifdef WOLFSSL_AES_256 + /* Signed Encrypted FirmwarePkgData, RSA, SHA256, no attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256_noattr.der", 0, + NULL, 0, 0, AES256CBCb, 1, aes256Key, sizeof(aes256Key), NULL, 0}, + + /* Signed Encrypted FirmwarePkgData, RSA, SHA256, attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256.der", 0, + NULL, 0, 0, AES256CBCb, 1, aes256Key, sizeof(aes256Key), + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib))}, + #endif /* WOLFSSL_AES_256 */ + + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + /* Signed Compressed FirmwarePkgData, RSA, SHA256, no attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedCompressedFirmwarePkgData_RSA_SHA256_noattr.der", 0, + NULL, 0, 0, 0, 2, NULL, 0, NULL, 0}, + + /* Signed Compressed FirmwarePkgData, RSA, SHA256, attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedCompressedFirmwarePkgData_RSA_SHA256.der", 0, + NULL, 0, 0, 0, 2, NULL, 0, NULL, 0}, + #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + + #endif /* NO_SHA256 */ +#endif /* NO_RSA */ + +#ifdef HAVE_ECC + #ifndef NO_SHA256 + /* Signed FirmwarePkgData, ECDSA, SHA256, no attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedFirmwarePkgData_ECDSA_SHA256_noattr.der", 0, NULL, + 0, 0, 0, 0, NULL, 0, NULL, 0}, + + /* Signed FirmwarePkgData, ECDSA, SHA256, attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedFirmwarePkgData_ECDSA_SHA256.der", 0, NULL, + 0, 0, 0, 0, NULL, 0, NULL, 0}, + + /* Signed FirmwarePkgData, ECDSA, SHA256, SubjectKeyIdentifier, attr */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedFirmwarePkgData_ECDSA_SHA256_SKID.der", 0, NULL, + 0, CMS_SKID, 0, 0, NULL, 0, NULL, 0}, + + #ifdef WOLFSSL_AES_256 + /* Signed Encrypted FirmwarePkgData, ECDSA, SHA256, no attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256_noattr.der", 0, NULL, + 0, 0, AES256CBCb, 1, aes256Key, sizeof(aes256Key), NULL, 0}, + + /* Signed Encrypted FirmwarePkgData, ECDSA, SHA256, attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256.der", 0, NULL, + 0, 0, AES256CBCb, 1, aes256Key, sizeof(aes256Key), + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib))}, + #endif /* WOLFSSL_AES_256 */ + + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + /* Signed Compressed FirmwarePkgData, ECDSA, SHA256, no attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der", 0, NULL, + 0, 0, 0, 2, NULL, 0, NULL, 0}, + + /* Signed Compressed FirmwarePkgData, ECDSA, SHA256, attrib */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256.der", 0, NULL, + 0, 0, 0, 2, NULL, 0, NULL, 0}, + #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + + #endif /* NO_SHA256 */ +#endif /* HAVE_ECC */ + }; + + testSz = sizeof(testVectors) / sizeof(pkcs7SignedVector); + + outSz = FOURK_BUF; + out = (byte*)XMALLOC(outSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (out == NULL) + return -9510; + + XMEMSET(out, 0, outSz); + + ret = wc_PKCS7_PadData((byte*)data, sizeof(data), out, outSz, 16); + if (ret < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -9511; + } + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); +#else + ret = wc_InitRng(&rng); +#endif + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -9512; + } + + for (i = 0; i < testSz; i++) { + pkcs7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); + if (pkcs7 == NULL) + return -9513; + + pkcs7->heap = HEAP_HINT; + pkcs7->devId = INVALID_DEVID; + ret = wc_PKCS7_InitWithCert(pkcs7, testVectors[i].cert, + (word32)testVectors[i].certSz); + + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9514; + } + + /* load CA certificate, if present */ + if (testVectors[i].caCert != NULL) { + ret = wc_PKCS7_AddCertificate(pkcs7, testVectors[i].caCert, + (word32)testVectors[i].caCertSz); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9515; + } + } + + /* set SignerIdentifier to use SubjectKeyIdentifier if desired, + default is IssuerAndSerialNumber */ + if (testVectors[i].sidType == CMS_SKID) { + ret = wc_PKCS7_SetSignerIdentifierType(pkcs7, CMS_SKID); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9516; + } + } + + if (testVectors[i].encCompFlag == 0) { + + /* encode Signed FirmwarePkgData */ + encodedSz = wc_PKCS7_EncodeSignedFPD(pkcs7, + testVectors[i].privateKey, testVectors[i].privateKeySz, + testVectors[i].signOID, testVectors[i].hashOID, + (byte*)testVectors[i].content, testVectors[i].contentSz, + testVectors[i].signedAttribs, + testVectors[i].signedAttribsSz, out, outSz); + + if (encodedSz < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9517; + } + + } else if (testVectors[i].encCompFlag == 1) { + + /* encode Signed Encrypted FirmwarePkgData */ + encodedSz = wc_PKCS7_EncodeSignedEncryptedFPD(pkcs7, + testVectors[i].encryptKey, testVectors[i].encryptKeySz, + testVectors[i].privateKey, testVectors[i].privateKeySz, + testVectors[i].encryptOID, testVectors[i].signOID, + testVectors[i].hashOID, (byte*)testVectors[i].content, + testVectors[i].contentSz, testVectors[i].unprotectedAttribs, + testVectors[i].unprotectedAttribsSz, + testVectors[i].signedAttribs, + testVectors[i].signedAttribsSz, out, outSz); + + if (encodedSz <= 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9518; + } + + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + } else if (testVectors[i].encCompFlag == 2) { + + /* encode Signed Compressed FirmwarePkgData */ + encodedSz = wc_PKCS7_EncodeSignedCompressedFPD(pkcs7, + testVectors[i].privateKey, testVectors[i].privateKeySz, + testVectors[i].signOID, testVectors[i].hashOID, + (byte*)testVectors[i].content, testVectors[i].contentSz, + testVectors[i].signedAttribs, + testVectors[i].signedAttribsSz, out, outSz); + + if (encodedSz <= 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9519; + } + #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + + } else { + /* unsupported SignedData single-shot combination */ + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9520; + } + + #ifdef PKCS7_OUTPUT_TEST_BUNDLES + /* write PKCS#7 to output file for more testing */ + file = fopen(testVectors[i].outFileName, "wb"); + if (!file) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9522; + } + ret = (int)fwrite(out, 1, encodedSz, file); + fclose(file); + if (ret != (int)encodedSz) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9526; + } + #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + + wc_PKCS7_Free(pkcs7); + + pkcs7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); + if (pkcs7 == NULL) + return -9527; + wc_PKCS7_InitWithCert(pkcs7, NULL, 0); + + ret = wc_PKCS7_VerifySignedData(pkcs7, out, outSz); + if (ret < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9528; + } + + if (pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9531; + } + + if (testVectors[i].encCompFlag == 0) { + /* verify decoded content matches expected */ + if ((pkcs7->contentSz != testVectors[i].contentSz) || + XMEMCMP(pkcs7->content, testVectors[i].content, + pkcs7->contentSz)) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9532; + } + + } else if (testVectors[i].encCompFlag == 1) { + + /* decrypt inner encryptedData */ + pkcs7->encryptionKey = testVectors[i].encryptKey; + pkcs7->encryptionKeySz = testVectors[i].encryptKeySz; + + ret = wc_PKCS7_DecodeEncryptedData(pkcs7, pkcs7->content, + pkcs7->contentSz, out, outSz); + if (ret < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9533; + } + + /* compare decrypted to expected */ + if (((word32)ret != testVectors[i].contentSz) || + XMEMCMP(out, testVectors[i].content, ret)) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9534; + } + } + #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + else if (testVectors[i].encCompFlag == 2) { + + /* decompress inner compressedData */ + ret = wc_PKCS7_DecodeCompressedData(pkcs7, pkcs7->content, + pkcs7->contentSz, out, outSz); + if (ret < 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9535; + } + + /* compare decompressed to expected */ + if (((word32)ret != testVectors[i].contentSz) || + XMEMCMP(out, testVectors[i].content, ret)) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9536; + } + } + #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + + wc_PKCS7_Free(pkcs7); + } + + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeRng(&rng); + + if (ret > 0) + return 0; + +#ifndef HAVE_ECC + (void)eccCert; + (void)eccCertSz; + (void)eccPrivKey; + (void)eccPrivKeySz; +#endif +#ifdef NO_RSA + (void)rsaClientCertBuf; + (void)rsaClientCertBufSz; + (void)rsaClientPrivKeyBuf; + (void)rsaClientPrivKeyBufSz; + (void)rsaServerCertBuf; + (void)rsaServerCertBufSz; + (void)rsaServerPrivKeyBuf; + (void)rsaServerPrivKeyBufSz; + (void)rsaCaCertBuf; + (void)rsaCaCertBufSz; + (void)rsaCaPrivKeyBuf; + (void)rsaCaPrivKeyBufSz; +#endif + + (void)rsaServerCertBuf; + (void)rsaServerCertBufSz; + (void)rsaServerPrivKeyBuf; + (void)rsaServerPrivKeyBufSz; + (void)rsaCaCertBuf; + (void)rsaCaCertBufSz; + (void)rsaCaPrivKeyBuf; + (void)rsaCaPrivKeyBufSz; + return ret; +} + + int pkcs7signed_test(void) { int ret = 0; @@ -21101,6 +21552,23 @@ int pkcs7signed_test(void) rsaCaPrivKeyBuf, (word32)rsaCaPrivKeyBufSz, eccClientCertBuf, (word32)eccClientCertBufSz, eccClientPrivKeyBuf, (word32)eccClientPrivKeyBufSz); + if (ret < 0) { + XFREE(rsaClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(eccClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -9509; + } + + ret = pkcs7signed_run_SingleShotVectors( + rsaClientCertBuf, (word32)rsaClientCertBufSz, + rsaClientPrivKeyBuf, (word32)rsaClientPrivKeyBufSz, + rsaServerCertBuf, (word32)rsaServerCertBufSz, + rsaServerPrivKeyBuf, (word32)rsaServerPrivKeyBufSz, + rsaCaCertBuf, (word32)rsaCaCertBufSz, + rsaCaPrivKeyBuf, (word32)rsaCaPrivKeyBufSz, + eccClientCertBuf, (word32)eccClientCertBufSz, + eccClientPrivKeyBuf, (word32)eccClientPrivKeyBufSz); XFREE(rsaClientCertBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(rsaClientPrivKeyBuf, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); From d69a3c10927b242ce92410fd7b6cc2607ff387f3 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 10 Oct 2018 15:10:47 -0600 Subject: [PATCH 31/56] add single-shot API for generating CMS Signed Encrypted Compressed FirmwarePkgData --- .gitignore | 4 + Makefile.am | 6 +- wolfcrypt/src/pkcs7.c | 152 +++++++++++++++++++++++++++++++++- wolfcrypt/test/test.c | 167 ++++++++++++++++++++++++++++++++------ wolfssl/wolfcrypt/pkcs7.h | 15 ++++ 5 files changed, 313 insertions(+), 31 deletions(-) diff --git a/.gitignore b/.gitignore index 5645c9762..b5d7e99d0 100644 --- a/.gitignore +++ b/.gitignore @@ -175,6 +175,10 @@ pkcs7signedFirmwarePkgData_RSA_SHA256.der pkcs7signedFirmwarePkgData_RSA_SHA256_SKID.der pkcs7signedFirmwarePkgData_RSA_SHA256_noattr.der pkcs7signedFirmwarePkgData_RSA_SHA256_with_ca_cert.der +pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256.der +pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der +pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256.der +pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256_noattr.der diff sslSniffer/sslSnifferTest/tracefile.txt tracefile.txt diff --git a/Makefile.am b/Makefile.am index 0f8ed7c78..8f97513cb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -113,7 +113,11 @@ CLEANFILES+= cert.der \ pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256.der \ pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256_noattr.der \ pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256.der \ - pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256_noattr.der + pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256_noattr.der \ + pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256.der \ + pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der \ + pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256.der \ + pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256_noattr.der exampledir = $(docdir)/example dist_example_DATA= diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index ce64e24b3..c38a2972d 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -2003,16 +2003,16 @@ int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, byte* encryptKey, /* save encryptedData, reset output buffer and struct */ encrypted = (byte*)XMALLOC(encryptedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (encrypted == NULL) { - wc_PKCS7_Free(pkcs7); + ForceZero(output, outputSz); return MEMORY_E; } - XMEMSET(encrypted, 0, encryptedSz); XMEMCPY(encrypted, output, encryptedSz); ForceZero(output, outputSz); ret = wc_InitRng(&rng); if (ret != 0) { + ForceZero(encrypted, encryptedSz); XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } @@ -2032,11 +2032,13 @@ int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, byte* encryptKey, ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); if (ret <= 0) { WOLFSSL_MSG("Error encoding CMS SignedData content type"); + ForceZero(encrypted, encryptedSz); XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); wc_FreeRng(&rng); return ret; } + ForceZero(encrypted, encryptedSz); XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); wc_FreeRng(&rng); @@ -2101,16 +2103,16 @@ int wc_PKCS7_EncodeSignedCompressedFPD(PKCS7* pkcs7, byte* privateKey, /* save compressedData, reset output buffer and struct */ compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (compressed == NULL) { - wc_PKCS7_Free(pkcs7); + ForceZero(output, outputSz); return MEMORY_E; } - XMEMSET(compressed, 0, compressedSz); XMEMCPY(compressed, output, compressedSz); ForceZero(output, outputSz); ret = wc_InitRng(&rng); if (ret != 0) { + ForceZero(compressed, compressedSz); XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return ret; } @@ -2130,16 +2132,158 @@ int wc_PKCS7_EncodeSignedCompressedFPD(PKCS7* pkcs7, byte* privateKey, ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); if (ret <= 0) { WOLFSSL_MSG("Error encoding CMS SignedData content type"); + ForceZero(compressed, compressedSz); XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); wc_FreeRng(&rng); return ret; } + ForceZero(compressed, compressedSz); XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); wc_FreeRng(&rng); return ret; } + +#ifndef NO_PKCS7_ENCRYPTED_DATA + +/* Single-shot API to generate a CMS SignedData bundle that encapsulates a + * CMS EncryptedData bundle, which then encapsulates a CMS CompressedData + * bundle. Content of inner CompressedData is set to that of FirmwarePkgData. + * Any recipient certificates should be loaded into the PKCS7 structure prior + * to calling this function, using wc_PKCS7_InitWithCert() and/or + * wc_PKCS7_AddCertificate(). + * + * pkcs7 - pointer to initialized PKCS7 struct + * encryptKey - encryption key used for encrypting EncryptedData + * encryptKeySz - size of encryptKey, octets + * privateKey - private RSA/ECC key, used for signing SignedData + * privateKeySz - size of privateKey, octets + * encryptOID - encryption algorithm OID, to be used as encryption + * algorithm for EncryptedData + * signOID - public key algorithm OID, to be used for sign + * operation in SignedData generation + * hashOID - hash algorithm OID, to be used for signature in + * SignedData generation + * content - content to be encapsulated + * contentSz - size of content, octets + * unprotectedAttribs - optional unprotected attributes, for EncryptedData + * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs + * signedAttribs - optional signed attributes, for SignedData + * signedAttribsSz - number of PKCS7Attrib members in signedAttribs + * output - output buffer for final bundle + * outputSz - size of output buffer, octets + * + * Returns length of generated bundle on success, negative upon error. */ +int wc_PKCS7_EncodeSignedEncryptedCompressedFPD(PKCS7* pkcs7, byte* encryptKey, + word32 encryptKeySz, byte* privateKey, + word32 privateKeySz, int encryptOID, + int signOID, int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* unprotectedAttribs, + word32 unprotectedAttribsSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, + byte* output, word32 outputSz) +{ + int ret = 0, compressedSz = 0, encryptedSz = 0; + byte* compressed = NULL; + byte* encrypted = NULL; + WC_RNG rng; + + if (pkcs7 == NULL || encryptKey == NULL || encryptKeySz == 0 || + privateKey == NULL || privateKeySz == 0 || content == NULL || + contentSz == 0 || output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* 1: build up CompressedData using FirmwarePkgData type, use output + * buffer as tmp for storage and to get size */ + pkcs7->content = content; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + + compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, output, outputSz); + if (compressedSz < 0) { + WOLFSSL_MSG("Error encoding CMS CompressedData content type"); + return compressedSz; + } + + /* save compressedData, reset output buffer and struct */ + compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (compressed == NULL) + return MEMORY_E; + + XMEMCPY(compressed, output, compressedSz); + ForceZero(output, outputSz); + + /* 2: build up EncryptedData using CompressedData, use output + * buffer as tmp for storage and to get size */ + pkcs7->content = compressed; + pkcs7->contentSz = compressedSz; + pkcs7->contentOID = COMPRESSED_DATA; + pkcs7->encryptOID = encryptOID; + pkcs7->encryptionKey = encryptKey; + pkcs7->encryptionKeySz = encryptKeySz; + pkcs7->unprotectedAttribs = unprotectedAttribs; + pkcs7->unprotectedAttribsSz = unprotectedAttribsSz; + + encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, output, outputSz); + if (encryptedSz < 0) { + WOLFSSL_MSG("Error encoding CMS EncryptedData content type"); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return encryptedSz; + } + + /* save encryptedData, reset output buffer and struct */ + encrypted = (byte*)XMALLOC(encryptedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (encrypted == NULL) { + ForceZero(compressed, compressedSz); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + XMEMCPY(encrypted, output, encryptedSz); + ForceZero(compressed, compressedSz); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + ForceZero(output, outputSz); + + ret = wc_InitRng(&rng); + if (ret != 0) { + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* 3: build up SignedData, encapsulating EncryptedData */ + pkcs7->rng = &rng; + pkcs7->content = encrypted; + pkcs7->contentSz = encryptedSz; + pkcs7->contentOID = ENCRYPTED_DATA; + pkcs7->hashOID = hashOID; + pkcs7->encryptOID = signOID; + pkcs7->privateKey = privateKey; + pkcs7->privateKeySz = privateKeySz; + pkcs7->signedAttribs = signedAttribs; + pkcs7->signedAttribsSz = signedAttribsSz; + + ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + if (ret <= 0) { + WOLFSSL_MSG("Error encoding CMS SignedData content type"); + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + return ret; + } + + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + + return ret; +} + +#endif /* !NO_PKCS7_ENCRYPTED_DATA */ #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index c23697f5b..6d96b274e 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -21081,7 +21081,7 @@ static int pkcs7signed_run_SingleShotVectors( "pkcs7signedFirmwarePkgData_RSA_SHA256_with_ca_cert.der", 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0}, - #ifdef WOLFSSL_AES_256 + #if defined(WOLFSSL_AES_256) && !defined(NO_PKCS7_ENCRYPTED_DATA) /* Signed Encrypted FirmwarePkgData, RSA, SHA256, no attribs */ {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, @@ -21096,7 +21096,7 @@ static int pkcs7signed_run_SingleShotVectors( "pkcs7signedEncryptedFirmwarePkgData_RSA_SHA256.der", 0, NULL, 0, 0, AES256CBCb, 1, aes256Key, sizeof(aes256Key), attribs, (sizeof(attribs)/sizeof(PKCS7Attrib))}, - #endif /* WOLFSSL_AES_256 */ + #endif /* WOLFSSL_AES_256 && !NO_PKCS7_ENCRYPTED_DATA */ #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) /* Signed Compressed FirmwarePkgData, RSA, SHA256, no attribs */ @@ -21112,6 +21112,26 @@ static int pkcs7signed_run_SingleShotVectors( attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedCompressedFirmwarePkgData_RSA_SHA256.der", 0, NULL, 0, 0, 0, 2, NULL, 0, NULL, 0}, + + #ifndef NO_PKCS7_ENCRYPTED_DATA + /* Signed Encrypted Compressed FirmwarePkgData, RSA, SHA256, + no attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256_noattr.der", + 0, NULL, 0, 0, AES256CBCb, 3, aes256Key, sizeof(aes256Key), NULL, 0}, + + /* Signed Encrypted Compressed FirmwarePkgData, RSA, SHA256, + attribs */ + {data, (word32)sizeof(data), SHA256h, RSAk, rsaClientPrivKeyBuf, + rsaClientPrivKeyBufSz, rsaClientCertBuf, rsaClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedEncryptedCompressedFirmwarePkgData_RSA_SHA256.der", + 0, NULL, 0, 0, AES256CBCb, 3, aes256Key, sizeof(aes256Key), + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib))}, + #endif /* !NO_PKCS7_ENCRYPTED_DATA */ + #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ #endif /* NO_SHA256 */ @@ -21122,7 +21142,7 @@ static int pkcs7signed_run_SingleShotVectors( /* Signed FirmwarePkgData, ECDSA, SHA256, no attribs */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, - attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + NULL, 0, "pkcs7signedFirmwarePkgData_ECDSA_SHA256_noattr.der", 0, NULL, 0, 0, 0, 0, NULL, 0, NULL, 0}, @@ -21140,7 +21160,7 @@ static int pkcs7signed_run_SingleShotVectors( "pkcs7signedFirmwarePkgData_ECDSA_SHA256_SKID.der", 0, NULL, 0, CMS_SKID, 0, 0, NULL, 0, NULL, 0}, - #ifdef WOLFSSL_AES_256 + #if defined(WOLFSSL_AES_256) && !defined(NO_PKCS7_ENCRYPTED_DATA) /* Signed Encrypted FirmwarePkgData, ECDSA, SHA256, no attribs */ {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, @@ -21155,7 +21175,7 @@ static int pkcs7signed_run_SingleShotVectors( "pkcs7signedEncryptedFirmwarePkgData_ECDSA_SHA256.der", 0, NULL, 0, 0, AES256CBCb, 1, aes256Key, sizeof(aes256Key), attribs, (sizeof(attribs)/sizeof(PKCS7Attrib))}, - #endif /* WOLFSSL_AES_256 */ + #endif /* WOLFSSL_AES_256 && !NO_PKCS7_ENCRYPTED_DATA */ #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) /* Signed Compressed FirmwarePkgData, ECDSA, SHA256, no attribs */ @@ -21171,6 +21191,26 @@ static int pkcs7signed_run_SingleShotVectors( attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), "pkcs7signedCompressedFirmwarePkgData_ECDSA_SHA256.der", 0, NULL, 0, 0, 0, 2, NULL, 0, NULL, 0}, + + #ifndef NO_PKCS7_ENCRYPTED_DATA + /* Signed Encrypted Compressed FirmwarePkgData, ECDSA, SHA256, + no attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + NULL, 0, + "pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256_noattr.der", + 0, NULL, 0, 0, AES256CBCb, 3, aes256Key, sizeof(aes256Key), NULL, 0}, + + /* Signed Encrypted Compressed FirmwarePkgData, ECDSA, SHA256, + attribs */ + {data, (word32)sizeof(data), SHA256h, ECDSAk, eccClientPrivKeyBuf, + eccClientPrivKeyBufSz, eccClientCertBuf, eccClientCertBufSz, NULL, 0, + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedEncryptedCompressedFirmwarePkgData_ECDSA_SHA256.der", + 0, NULL, 0, 0, AES256CBCb, 3, aes256Key, sizeof(aes256Key), + attribs, (sizeof(attribs)/sizeof(PKCS7Attrib))}, + #endif /* !NO_PKCS7_ENCRYPTED_DATA */ + #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ #endif /* NO_SHA256 */ @@ -21182,14 +21222,14 @@ static int pkcs7signed_run_SingleShotVectors( outSz = FOURK_BUF; out = (byte*)XMALLOC(outSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); if (out == NULL) - return -9510; + return -9550; XMEMSET(out, 0, outSz); ret = wc_PKCS7_PadData((byte*)data, sizeof(data), out, outSz, 16); if (ret < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -9511; + return -9551; } #ifndef HAVE_FIPS @@ -21199,13 +21239,13 @@ static int pkcs7signed_run_SingleShotVectors( #endif if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -9512; + return -9552; } for (i = 0; i < testSz; i++) { pkcs7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); if (pkcs7 == NULL) - return -9513; + return -9553; pkcs7->heap = HEAP_HINT; pkcs7->devId = INVALID_DEVID; @@ -21215,7 +21255,7 @@ static int pkcs7signed_run_SingleShotVectors( if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9514; + return -9554; } /* load CA certificate, if present */ @@ -21225,7 +21265,7 @@ static int pkcs7signed_run_SingleShotVectors( if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9515; + return -9555; } } @@ -21236,7 +21276,7 @@ static int pkcs7signed_run_SingleShotVectors( if (ret != 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9516; + return -9556; } } @@ -21253,7 +21293,7 @@ static int pkcs7signed_run_SingleShotVectors( if (encodedSz < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9517; + return -9557; } } else if (testVectors[i].encCompFlag == 1) { @@ -21272,7 +21312,7 @@ static int pkcs7signed_run_SingleShotVectors( if (encodedSz <= 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9518; + return -9558; } #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) @@ -21289,15 +21329,37 @@ static int pkcs7signed_run_SingleShotVectors( if (encodedSz <= 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9519; + return -9559; } + + #ifndef NO_PKCS7_ENCRYPTED_DATA + } else if (testVectors[i].encCompFlag == 3) { + + /* encode Signed Encrypted Compressed FirmwarePkgData */ + encodedSz = wc_PKCS7_EncodeSignedEncryptedCompressedFPD(pkcs7, + testVectors[i].encryptKey, testVectors[i].encryptKeySz, + testVectors[i].privateKey, testVectors[i].privateKeySz, + testVectors[i].encryptOID, testVectors[i].signOID, + testVectors[i].hashOID, (byte*)testVectors[i].content, + testVectors[i].contentSz, testVectors[i].unprotectedAttribs, + testVectors[i].unprotectedAttribsSz, + testVectors[i].signedAttribs, + testVectors[i].signedAttribsSz, out, outSz); + + if (encodedSz <= 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9560; + } + + #endif /* NO_PKCS7_ENCRYPTED_DATA */ #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ } else { /* unsupported SignedData single-shot combination */ XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9520; + return -9561; } #ifdef PKCS7_OUTPUT_TEST_BUNDLES @@ -21306,14 +21368,14 @@ static int pkcs7signed_run_SingleShotVectors( if (!file) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9522; + return -9562; } ret = (int)fwrite(out, 1, encodedSz, file); fclose(file); if (ret != (int)encodedSz) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9526; + return -9563; } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ @@ -21321,20 +21383,20 @@ static int pkcs7signed_run_SingleShotVectors( pkcs7 = wc_PKCS7_New(HEAP_HINT, INVALID_DEVID); if (pkcs7 == NULL) - return -9527; + return -9564; wc_PKCS7_InitWithCert(pkcs7, NULL, 0); ret = wc_PKCS7_VerifySignedData(pkcs7, out, outSz); if (ret < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9528; + return -9565; } if (pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9531; + return -9566; } if (testVectors[i].encCompFlag == 0) { @@ -21344,7 +21406,7 @@ static int pkcs7signed_run_SingleShotVectors( pkcs7->contentSz)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9532; + return -9567; } } else if (testVectors[i].encCompFlag == 1) { @@ -21358,7 +21420,7 @@ static int pkcs7signed_run_SingleShotVectors( if (ret < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9533; + return -9568; } /* compare decrypted to expected */ @@ -21366,7 +21428,7 @@ static int pkcs7signed_run_SingleShotVectors( XMEMCMP(out, testVectors[i].content, ret)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9534; + return -9569; } } #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) @@ -21378,7 +21440,7 @@ static int pkcs7signed_run_SingleShotVectors( if (ret < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9535; + return -9570; } /* compare decompressed to expected */ @@ -21386,9 +21448,62 @@ static int pkcs7signed_run_SingleShotVectors( XMEMCMP(out, testVectors[i].content, ret)) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS7_Free(pkcs7); - return -9536; + return -9571; } } + #ifndef NO_PKCS7_ENCRYPTED_DATA + else if (testVectors[i].encCompFlag == 3) { + + byte* encryptedTmp; + int encryptedTmpSz; + + encryptedTmpSz = FOURK_BUF; + encryptedTmp = (byte*)XMALLOC(encryptedTmpSz, HEAP_HINT, + DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedTmp == NULL) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9572; + } + + XMEMSET(encryptedTmp, 0, encryptedTmpSz); + + /* decrypt inner encryptedData */ + pkcs7->encryptionKey = testVectors[i].encryptKey; + pkcs7->encryptionKeySz = testVectors[i].encryptKeySz; + + encryptedTmpSz = wc_PKCS7_DecodeEncryptedData(pkcs7, pkcs7->content, + pkcs7->contentSz, encryptedTmp, + encryptedTmpSz); + + if (encryptedTmpSz < 0) { + XFREE(encryptedTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9573; + } + + /* decompress inner compressedData */ + ret = wc_PKCS7_DecodeCompressedData(pkcs7, encryptedTmp, + encryptedTmpSz, out, outSz); + if (ret < 0) { + XFREE(encryptedTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9574; + } + + XFREE(encryptedTmp, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + + /* compare decompressed to expected */ + if (((word32)ret != testVectors[i].contentSz) || + XMEMCMP(out, testVectors[i].content, ret)) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + return -9575; + } + } + #endif /* NO_PKCS7_ENCRYPTED_DATA */ #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ wc_PKCS7_Free(pkcs7); diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 9244f2314..4a5c052da 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -308,6 +308,21 @@ WOLFSSL_API int wc_PKCS7_EncodeSignedCompressedFPD(PKCS7* pkcs7, PKCS7Attrib* signedAttribs, word32 signedAttribsSz, byte* output, word32 outputSz); + +#ifndef NO_PKCS7_ENCRYPTED_DATA +/* CMS single-shot API for Signed Encrypted Compressed FirmwarePkgData */ +WOLFSSL_API int wc_PKCS7_EncodeSignedEncryptedCompressedFPD(PKCS7* pkcs7, + byte* encryptKey, word32 encryptKeySz, + byte* privateKey, word32 privateKeySz, + int encryptOID, int signOID, + int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* unprotectedAttribs, + word32 unprotectedAttribsSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, + byte* output, word32 outputSz); +#endif /* !NO_PKCS7_ENCRYPTED_DATA */ #endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ /* EnvelopedData and AuthEnvelopedData RecipientInfo functions */ From 5d8f59d83bad0b88598ab1f5ea5f121ab6008dbc Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 10 Oct 2018 16:48:10 -0600 Subject: [PATCH 32/56] initial AuthEnvelopedData stream and add debug messages --- wolfcrypt/src/pkcs7.c | 2545 ++++++++++++++++++++++++------------- wolfcrypt/test/test.c | 21 +- wolfssl/wolfcrypt/pkcs7.h | 37 +- 3 files changed, 1710 insertions(+), 893 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index c38a2972d..cd0c0734e 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -64,9 +64,16 @@ typedef enum { #define MAX_PKCS7_STREAM_BUFFER 256 typedef struct PKCS7State { byte* tmpCert; + byte* bufferPt; + byte* nonce; /* stored nonce */ + byte* aad; /* additional data for AEAD algos */ + byte* tag; /* tag data for AEAD algos */ + + /* stack variables to store for when returning */ word32 varOne; - word32 varTwo; - word32 varThree; + int varTwo; + int varThree; + word32 vers; word32 idx; /* index read into current input buffer */ word32 maxLen; /* sanity cap on maximum amount of data to allow @@ -74,9 +81,16 @@ typedef struct PKCS7State { word32 length; /* amount of data stored */ word32 expected; /* next amount of data expected, if needed */ word32 totalRd; /* total amount of bytes read */ - byte hasAtrib:1; byte buffer[4096]; + word32 nonceSz; /* size of nonce stored */ + word32 aadSz; /* size of additional AEAD data */ + word32 tagSz; /* size of tag for AEAD */ byte tmpIv[MAX_CONTENT_IV_SIZE]; /* store IV if needed */ +#ifdef WC_PKCS7_STREAM_DEBUG + word32 peakUsed; /* most bytes used for struct at any one time */ + word32 peakRead; /* most bytes used by read buffer */ +#endif + byte hasAtrib:1; } PKCS7State; @@ -95,16 +109,49 @@ static int wc_PKCS7_CreateStream(PKCS7* pkcs7) return MEMORY_E; } XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State)); +#ifdef WC_PKCS7_STREAM_DEBUG + printf("\nCreating new PKCS#7 stream %p\n", pkcs7->stream); +#endif return 0; } static void wc_PKCS7_ResetStream(PKCS7* pkcs7) { - /* free any buffers that may be allocated */ + if (pkcs7 != NULL && pkcs7->stream != NULL) { +#ifdef WC_PKCS7_STREAM_DEBUG + /* collect final data point in case more was read right before reset */ + if (pkcs7->stream->length > pkcs7->stream->peakRead) { + pkcs7->stream->peakRead = pkcs7->stream->length; + } + if (pkcs7->stream->length + pkcs7->stream->aadSz + + pkcs7->stream->nonceSz + pkcs7->stream->tagSz > + pkcs7->stream->peakUsed) { + pkcs7->stream->peakUsed = pkcs7->stream->length + + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + + pkcs7->stream->tagSz; + } - /* reset values */ - XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State)); + /* print out debugging statistics */ + if (pkcs7->stream->peakUsed > 0 || pkcs7->stream->peakRead > 0) { + printf("PKCS#7 STREAM:\n\tPeak heap used by struct = %d" + "\n\tPeak read buffer bytes = %d" + "\n\tTotal bytes read = %d" + "\n", + pkcs7->stream->peakUsed, pkcs7->stream->peakRead, + pkcs7->stream->totalRd); + } + printf("PKCS#7 stream reset : Address [%p]\n", pkcs7->stream); + #endif + + /* free any buffers that may be allocated */ + XFREE(pkcs7->stream->aad, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->tag, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->nonce, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + /* reset values */ + XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State)); + } } @@ -155,6 +202,16 @@ static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, pkcs7->stream->totalRd += len; } +#ifdef WC_PKCS7_STREAM_DEBUG + if (pkcs7->stream->length > pkcs7->stream->peakRead) { + pkcs7->stream->peakRead = pkcs7->stream->length; + } + if (pkcs7->stream->length + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + + pkcs7->stream->tagSz > pkcs7->stream->peakUsed) { + pkcs7->stream->peakUsed = pkcs7->stream->length + pkcs7->stream->aadSz + + pkcs7->stream->nonceSz + pkcs7->stream->tagSz; + } +#endif if (pkcs7->stream->length < expected) { pkcs7->stream->idx = 0; return WC_PKCS7_WANT_READ_E; @@ -180,7 +237,7 @@ static word32 wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, word32 defSz) if (pkcs7 && pkcs7->stream->length > 0) { int length = 0, ret; word32 idx = 0; - if (flag & PKCS7_SEQ_PEEK) { + if (flag == PKCS7_SEQ_PEEK) { if ((ret = GetSequence(pkcs7->stream->buffer, &idx, &length, (word32)-1)) < 0) { return ret; @@ -195,8 +252,117 @@ static word32 wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, word32 defSz) } return defSz; } + + +/* setter function for stored variables */ +static void wc_PKCS7_StreamStoreVar(PKCS7* pkcs7, word32 var1, int var2, + int var3) +{ + if (pkcs7 != NULL && pkcs7->stream != NULL) { + pkcs7->stream->varOne = var1; + pkcs7->stream->varTwo = var2; + pkcs7->stream->varThree = var3; + } +} + +/* getter function for stored variables */ +static void wc_PKCS7_StreamGetVar(PKCS7* pkcs7, word32* var1, int* var2, + int* var3) +{ + if (pkcs7 != NULL && pkcs7->stream != NULL) { + if (var1 != NULL) *var1 = pkcs7->stream->varOne; + if (var2 != NULL) *var2 = pkcs7->stream->varTwo; + if (var3 != NULL) *var3 = pkcs7->stream->varThree; + } +} + + +/* common update of index and total read after section complete + * returns 0 on success */ +static int wc_PKCS7_StreamEndCase(PKCS7* pkcs7, word32* tmpIdx, word32* idx) +{ + int ret = 0; + + if (pkcs7->stream->length > 0) { + if (pkcs7->stream->length < *idx) { + ret = BUFFER_E; + } + else { + XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + *idx, + pkcs7->stream->length - *idx); + pkcs7->stream->length -= *idx; + } + } + else { + pkcs7->stream->totalRd += *idx - *tmpIdx; + *tmpIdx = *idx; + } + + return ret; +} #endif /* NO_PKCS7_STREAM */ +#ifdef WC_PKCS7_STREAM_DEBUG +/* used to print out human readable state for debugging */ +static const char* wc_PKCS7_GetStateName(int in) +{ + switch (in) { + case WC_PKCS7_START: return "WC_PKCS7_START"; + + case WC_PKCS7_STAGE2: return "WC_PKCS7_STAGE2"; + case WC_PKCS7_STAGE3: return "WC_PKCS7_STAGE3"; + case WC_PKCS7_STAGE4: return "WC_PKCS7_STAGE4"; + case WC_PKCS7_STAGE5: return "WC_PKCS7_STAGE5"; + case WC_PKCS7_STAGE6: return "WC_PKCS7_STAGE6"; + + /* parse info set */ + case WC_PKCS7_INFOSET_START: return "WC_PKCS7_INFOSET_START"; + case WC_PKCS7_INFOSET_BER: return "WC_PKCS7_INFOSET_BER"; + case WC_PKCS7_INFOSET_STAGE1: return "WC_PKCS7_INFOSET_STAGE1"; + case WC_PKCS7_INFOSET_STAGE2: return "WC_PKCS7_INFOSET_STAGE2"; + case WC_PKCS7_INFOSET_END: return "WC_PKCS7_INFOSET_END"; + + /* decode auth enveloped */ + case WC_PKCS7_AUTHENV_2: return "WC_PKCS7_AUTHENV_2"; + case WC_PKCS7_AUTHENV_3: return "WC_PKCS7_AUTHENV_3"; + case WC_PKCS7_AUTHENV_4: return "WC_PKCS7_AUTHENV_4"; + case WC_PKCS7_AUTHENV_5: return "WC_PKCS7_AUTHENV_5"; + case WC_PKCS7_AUTHENV_6: return "WC_PKCS7_AUTHENV_6"; + case WC_PKCS7_AUTHENV_ATRB: return "WC_PKCS7_AUTHENV_ATRB"; + case WC_PKCS7_AUTHENV_ATRBEND: return "WC_PKCS7_AUTHENV_ATRBEND"; + case WC_PKCS7_AUTHENV_7: return "WC_PKCS7_AUTHENV_7"; + + /* decryption state types */ + case WC_PKCS7_DECRYPT_KTRI: return "WC_PKCS7_DECRYPT_KTRI"; + case WC_PKCS7_DECRYPT_KTRI_2: return "WC_PKCS7_DECRYPT_KTRI_2"; + case WC_PKCS7_DECRYPT_KTRI_3: return "WC_PKCS7_DECRYPT_KTRI_3"; + + + case WC_PKCS7_DECRYPT_KARI: return "WC_PKCS7_DECRYPT_KARI"; + case WC_PKCS7_DECRYPT_KEKRI: return "WC_PKCS7_DECRYPT_KEKRI"; + case WC_PKCS7_DECRYPT_PWRI: return "WC_PKCS7_DECRYPT_PWRI"; + case WC_PKCS7_DECRYPT_ORI: return "WC_PKCS7_DECRYPT_ORI"; + + case WC_PKCS7_DECRYPT_DONE: return "WC_PKCS7_DECRYPT_DONE"; + + default: + return "Unknown state"; + } +} +#endif + +/* Used to change the PKCS7 state. Having state change as a function allows + * for easier debugging */ +static void wc_PKCS7_ChangeState(PKCS7* pkcs7, int newState) +{ +#ifdef WC_PKCS7_STREAM_DEBUG + printf("\tChanging from state [%02d] %s to [%02d] %s\n", + pkcs7->state, wc_PKCS7_GetStateName(pkcs7->state), + newState, wc_PKCS7_GetStateName(newState)); +#endif + pkcs7->state = newState; +} + #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \ MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE) @@ -6123,16 +6289,19 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) #ifndef NO_RSA /* decode KeyTransRecipientInfo (ktri), return 0 on success, <0 on error */ -static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, +static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { - int length, encryptedKeySz, ret; - int keySz, version, sidType; + int length, encryptedKeySz, ret = 0; + int keySz, version, sidType = 0; word32 encOID; word32 keyIdx; byte issuerHash[KEYID_SIZE]; byte* outKey = NULL; + word32 tmpIdx = *idx; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; #ifdef WC_RSA_BLINDING WC_RNG rng; @@ -6148,180 +6317,274 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, RsaKey privKey[1]; #endif - if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) - return ASN_PARSE_E; + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_KTRI: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_VERSION_SZ, + &pkiMsg, idx)) != 0) { + return ret; + } - if (version == 0) { - sidType = CMS_ISSUER_AND_SERIAL_NUMBER; - } else if (version == 2) { - sidType = CMS_SKID; - } else { - return ASN_VERSION_E; - } + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); - if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { - - /* remove IssuerAndSerialNumber */ - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* if we found correct recipient, issuer hashes will match */ - if (XMEMCMP(issuerHash, pkcs7->issuerHash, KEYID_SIZE) == 0) { - *recipFound = 1; - } - -#ifdef WOLFSSL_SMALL_STACK - serialNum = (mp_int*)XMALLOC(sizeof(mp_int), pkcs7->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (serialNum == NULL) - return MEMORY_E; -#endif - - if (GetInt(serialNum, pkiMsg, idx, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - mp_clear(serialNum); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - } else { - - /* remove SubjectKeyIdentifier */ - if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) - return ASN_PARSE_E; - - if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - - if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* if we found correct recipient, SKID will match */ - if (XMEMCMP(pkiMsg + (*idx), pkcs7->issuerSubjKeyId, KEYID_SIZE) == 0) { - *recipFound = 1; - } - (*idx) += KEYID_SIZE; - } - - if (GetAlgoId(pkiMsg, idx, &encOID, oidKeyType, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* key encryption algorithm must be RSA for now */ - if (encOID != RSAk) - return ALGO_ID_E; - - /* read encryptedKey */ -#ifdef WOLFSSL_SMALL_STACK - encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (encryptedKey == NULL) - return MEMORY_E; -#endif - - if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (GetLength(pkiMsg, idx, &encryptedKeySz, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ASN_PARSE_E; - } - - if (*recipFound == 1) - XMEMCPY(encryptedKey, &pkiMsg[*idx], encryptedKeySz); - *idx += encryptedKeySz; - - /* load private key */ -#ifdef WOLFSSL_SMALL_STACK - privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (privKey == NULL) { - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, INVALID_DEVID); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - - if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { - keyIdx = 0; - ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &keyIdx, privKey, - pkcs7->privateKeySz); - } - else if (pkcs7->devId == INVALID_DEVID) { - ret = BAD_FUNC_ARG; - } - if (ret != 0) { - WOLFSSL_MSG("Failed to decode RSA private key"); - wc_FreeRsaKey(privKey); -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - - /* decrypt encryptedKey */ - #ifdef WC_RSA_BLINDING - ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); - if (ret == 0) { - ret = wc_RsaSetRNG(privKey, &rng); - } - #endif - if (ret == 0) { - keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, - &outKey, privKey); - #ifdef WC_RSA_BLINDING - wc_FreeRng(&rng); #endif - } else { - keySz = ret; - } - wc_FreeRsaKey(privKey); + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; - if (keySz <= 0 || outKey == NULL) { - ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ); -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return keySz; - } else { - *decryptedKeySz = keySz; - XMEMCPY(decryptedKey, outKey, keySz); - ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ); + if (version == 0) { + sidType = CMS_ISSUER_AND_SERIAL_NUMBER; + } else if (version == 2) { + sidType = CMS_SKID; + } else { + return ASN_VERSION_E; + } + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, 0, sidType, version); + + /* @TODO getting total amount left because of GetInt call later on + * this could be optimized to stream better */ + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_2); + FALL_THROUGH; + + case WC_PKCS7_DECRYPT_KTRI_2: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, + &pkiMsg, idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + wc_PKCS7_StreamGetVar(pkcs7, NULL, &sidType, &version); + + /* @TODO get expected size for next part, does not account for + * GetInt call well */ + if (pkcs7->stream->expected == MAX_SEQ_SZ) { + int sz; + word32 lidx; + + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + lidx = *idx; + ret = GetSequence(pkiMsg, &lidx, &sz, pkiMsgSz); + if (ret < 0) + return ret; + } + else { + lidx = *idx + ASN_TAG_SZ; + ret = GetLength(pkiMsg, &lidx, &sz, pkiMsgSz); + if (ret < 0) + return ret; + } + + pkcs7->stream->expected = sz + MAX_ALGO_SZ + ASN_TAG_SZ + + MAX_LENGTH_SZ; + if (pkcs7->stream->length > 0 && + pkcs7->stream->length < pkcs7->stream->expected) { + return WC_PKCS7_WANT_READ_E; + } + } + #endif + + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + + /* remove IssuerAndSerialNumber */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* if we found correct recipient, issuer hashes will match */ + if (XMEMCMP(issuerHash, pkcs7->issuerHash, KEYID_SIZE) == 0) { + *recipFound = 1; + } + + #ifdef WOLFSSL_SMALL_STACK + serialNum = (mp_int*)XMALLOC(sizeof(mp_int), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (serialNum == NULL) + return MEMORY_E; + #endif + + if (GetInt(serialNum, pkiMsg, idx, pkiMsgSz) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ASN_PARSE_E; + } + + mp_clear(serialNum); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + } else { + + /* remove SubjectKeyIdentifier */ + if (pkiMsg[(*idx)++] != + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* if we found correct recipient, SKID will match */ + if (XMEMCMP(pkiMsg + (*idx), pkcs7->issuerSubjKeyId, + KEYID_SIZE) == 0) { + *recipFound = 1; + } + (*idx) += KEYID_SIZE; + } + + if (GetAlgoId(pkiMsg, idx, &encOID, oidKeyType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* key encryption algorithm must be RSA for now */ + if (encOID != RSAk) + return ALGO_ID_E; + + /* read encryptedKey */ + if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) { + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &encryptedKeySz, pkiMsgSz) < 0) { + return ASN_PARSE_E; + } + if (encryptedKeySz > MAX_ENCRYPTED_KEY_SZ) { + return BUFFER_E; + } + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, encryptedKeySz, sidType, version); + pkcs7->stream->expected = encryptedKeySz; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_3); + + case WC_PKCS7_DECRYPT_KTRI_3: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + #endif + + #ifdef WOLFSSL_SMALL_STACK + encryptedKey = (byte*)XMALLOC(encryptedKeySz, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedKey == NULL) + return MEMORY_E; + #endif + + if (*recipFound == 1) + XMEMCPY(encryptedKey, &pkiMsg[*idx], encryptedKeySz); + *idx += encryptedKeySz; + + /* load private key */ + #ifdef WOLFSSL_SMALL_STACK + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) { + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + #endif + + ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, INVALID_DEVID); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { + keyIdx = 0; + ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &keyIdx, + privKey, pkcs7->privateKeySz); + } + else if (pkcs7->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } + if (ret != 0) { + WOLFSSL_MSG("Failed to decode RSA private key"); + wc_FreeRsaKey(privKey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + /* decrypt encryptedKey */ + #ifdef WC_RSA_BLINDING + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret == 0) { + ret = wc_RsaSetRNG(privKey, &rng); + } + #endif + if (ret == 0) { + keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, + &outKey, privKey); + #ifdef WC_RSA_BLINDING + wc_FreeRng(&rng); + #endif + } else { + keySz = ret; + } + wc_FreeRsaKey(privKey); + + if (keySz <= 0 || outKey == NULL) { + ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return keySz; + } else { + *decryptedKeySz = keySz; + XMEMCPY(decryptedKey, outKey, keySz); + ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + break; + + default: + WOLFSSL_MSG("PKCS7 Unknown KTRI decrypt state"); + ret = BAD_FUNC_ARG; } -#ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return 0; + return ret; } #endif /* !NO_RSA */ @@ -6710,7 +6973,7 @@ int wc_PKCS7_SetOriDecryptCb(PKCS7* pkcs7, CallbackOriDecrypt cb) * * Return 0 on success, negative upon error. */ -static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, +static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* in, word32 inSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { @@ -6720,51 +6983,83 @@ static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte* oriValue; byte oriOID[MAX_OID_SZ]; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + word32 stateIdx = *idx; + if (pkcs7->oriDecryptCb == NULL) { WOLFSSL_MSG("You must register an ORI Decrypt callback"); return BAD_FUNC_ARG; } - /* get OtherRecipientInfo sequence length */ - if (GetLength(pkiMsg, idx, &seqSz, pkiMsgSz) < 0) - return ASN_PARSE_E; + switch (pkcs7->state) { - tmpIdx = *idx; + case WC_PKCS7_DECRYPT_ORI: + //@TODO for now just get full buffer, needs divided up - /* remove and store oriType OBJECT IDENTIFIER */ - if (GetASNObjectId(pkiMsg, idx, &oriOIDSz, pkiMsgSz) != 0) - return ASN_PARSE_E; + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + + pkcs7->stream->length, &pkiMsg, idx)) != 0) { + return ret; + } - XMEMCPY(oriOID, pkiMsg + *idx, oriOIDSz); - *idx += oriOIDSz; + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + #endif + /* get OtherRecipientInfo sequence length */ + if (GetLength(pkiMsg, idx, &seqSz, pkiMsgSz) < 0) + return ASN_PARSE_E; - /* get oriValue, increment idx */ - oriValue = pkiMsg + *idx; - oriValueSz = seqSz - (*idx - tmpIdx); - *idx += oriValueSz; + tmpIdx = *idx; - /* pass oriOID and oriValue to user callback, expect back - decryptedKey and size */ - ret = pkcs7->oriDecryptCb(pkcs7, oriOID, (word32)oriOIDSz, oriValue, - oriValueSz, decryptedKey, decryptedKeySz, - pkcs7->oriDecryptCtx); + /* remove and store oriType OBJECT IDENTIFIER */ + if (GetASNObjectId(pkiMsg, idx, &oriOIDSz, pkiMsgSz) != 0) + return ASN_PARSE_E; + + XMEMCPY(oriOID, pkiMsg + *idx, oriOIDSz); + *idx += oriOIDSz; + + /* get oriValue, increment idx */ + oriValue = pkiMsg + *idx; + oriValueSz = seqSz - (*idx - tmpIdx); + *idx += oriValueSz; + + /* pass oriOID and oriValue to user callback, expect back + decryptedKey and size */ + ret = pkcs7->oriDecryptCb(pkcs7, oriOID, (word32)oriOIDSz, oriValue, + oriValueSz, decryptedKey, decryptedKeySz, + pkcs7->oriDecryptCtx); + + if (ret != 0 || decryptedKey == NULL || *decryptedKeySz == 0) { + /* decrypt operation failed */ + *recipFound = 0; + return PKCS7_RECIP_E; + } + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + break; + + default: + WOLFSSL_MSG("PKCS7 ORI unknown state"); + ret = BAD_FUNC_ARG; - if (ret != 0 || decryptedKey == NULL || *decryptedKeySz == 0) { - /* decrypt operation failed */ - *recipFound = 0; - return PKCS7_RECIP_E; } - /* mark recipFound, since we only support one RecipientInfo for now */ - *recipFound = 1; - - return 0; + return ret; } /* decode ASN.1 PasswordRecipientInfo (pwri), return 0 on success, * < 0 on error */ -static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, +static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { @@ -6774,168 +7069,196 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte tmpIv[MAX_CONTENT_IV_SIZE]; - int ret, length, saltSz, iterations, blockSz; + int ret = 0, length, saltSz, iterations, blockSz; int hashOID = WC_SHA; /* default to SHA1 */ word32 kdfAlgoId, pwriEncAlgoId, keyEncAlgoId, cekSz; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + word32 tmpIdx = *idx; - /* remove KeyDerivationAlgorithmIdentifier */ - if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) - return ASN_PARSE_E; + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_PWRI: + //@TODO for now just get full buffer, needs divided up - if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + + pkcs7->stream->length, &pkiMsg, idx)) != 0) { + return ret; + } - /* get KeyDerivationAlgorithmIdentifier */ - if (wc_GetContentType(pkiMsg, idx, &kdfAlgoId, pkiMsgSz) < 0) - return ASN_PARSE_E; + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + #endif + /* remove KeyDerivationAlgorithmIdentifier */ + if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; - /* get KDF params SEQ */ - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; - /* get KDF salt OCTET STRING */ - if ( (pkiMsgSz > ((*idx) + 1)) && - (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { - return ASN_PARSE_E; + /* get KeyDerivationAlgorithmIdentifier */ + if (wc_GetContentType(pkiMsg, idx, &kdfAlgoId, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KDF params SEQ */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KDF salt OCTET STRING */ + if ( (pkiMsgSz > ((*idx) + 1)) && + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &saltSz, pkiMsgSz) < 0) + return ASN_PARSE_E; + + salt = (byte*)XMALLOC(saltSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (salt == NULL) + return MEMORY_E; + + XMEMCPY(salt, pkiMsg + (*idx), saltSz); + *idx += saltSz; + + /* get KDF iterations */ + if (GetMyVersion(pkiMsg, idx, &iterations, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get KeyEncAlgoId SEQ */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get KeyEncAlgoId */ + if (wc_GetContentType(pkiMsg, idx, &keyEncAlgoId, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get pwriEncAlgoId */ + if (GetAlgoId(pkiMsg, idx, &pwriEncAlgoId, oidBlkType, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + blockSz = wc_PKCS7_GetOIDBlockSize(pwriEncAlgoId); + if (blockSz < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockSz; + } + + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ + if ( (pkiMsgSz > ((*idx) + 1)) && + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (length != blockSz) { + WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + XMEMCPY(tmpIv, pkiMsg + (*idx), length); + *idx += length; + + /* get EncryptedKey */ + if ( (pkiMsgSz < ((*idx) + 1)) || + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* allocate temporary space for decrypted key */ + cekSz = length; + cek = (byte*)XMALLOC(cekSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cek == NULL) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* generate KEK */ + kek = (byte*)XMALLOC(blockSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (kek == NULL) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, pkcs7->pass, pkcs7->passSz, + salt, saltSz, kdfAlgoId, hashOID, + iterations, kek, blockSz); + if (ret < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* decrypt CEK with KEK */ + ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, blockSz, pkiMsg + (*idx), + length, cek, cekSz, tmpIv, + blockSz, pwriEncAlgoId); + if (ret < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + cekSz = ret; + + if (*decryptedKeySz < cekSz) { + WOLFSSL_MSG("Decrypted key buffer too small for CEK"); + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + XMEMCPY(decryptedKey, cek, cekSz); + *decryptedKeySz = cekSz; + + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + *idx += length; + ret = 0; /* success */ + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + break; + + default: + WOLFSSL_MSG("PKCS7 PWRI unknown state"); + ret = BAD_FUNC_ARG; } - if (GetLength(pkiMsg, idx, &saltSz, pkiMsgSz) < 0) - return ASN_PARSE_E; - - salt = (byte*)XMALLOC(saltSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - if (salt == NULL) - return MEMORY_E; - - XMEMCPY(salt, pkiMsg + (*idx), saltSz); - *idx += saltSz; - - /* get KDF iterations */ - if (GetMyVersion(pkiMsg, idx, &iterations, pkiMsgSz) < 0) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ASN_PARSE_E; - } - - /* get KeyEncAlgoId SEQ */ - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ASN_PARSE_E; - } - - /* get KeyEncAlgoId */ - if (wc_GetContentType(pkiMsg, idx, &keyEncAlgoId, pkiMsgSz) < 0) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ASN_PARSE_E; - } - - /* get pwriEncAlgoId */ - if (GetAlgoId(pkiMsg, idx, &pwriEncAlgoId, oidBlkType, pkiMsgSz) < 0) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ASN_PARSE_E; - } - - blockSz = wc_PKCS7_GetOIDBlockSize(pwriEncAlgoId); - if (blockSz < 0) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return blockSz; - } - - /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ - if ( (pkiMsgSz > ((*idx) + 1)) && - (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ASN_PARSE_E; - } - - if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ASN_PARSE_E; - } - - if (length != blockSz) { - WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ASN_PARSE_E; - } - - XMEMCPY(tmpIv, pkiMsg + (*idx), length); - *idx += length; - - /* get EncryptedKey */ - if ( (pkiMsgSz < ((*idx) + 1)) || - (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ASN_PARSE_E; - } - - if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ASN_PARSE_E; - } - - /* allocate temporary space for decrypted key */ - cekSz = length; - cek = (byte*)XMALLOC(cekSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (cek == NULL) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return MEMORY_E; - } - - /* generate KEK */ - kek = (byte*)XMALLOC(blockSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - if (kek == NULL) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return MEMORY_E; - } - - ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, pkcs7->pass, pkcs7->passSz, - salt, saltSz, kdfAlgoId, hashOID, - iterations, kek, blockSz); - if (ret < 0) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ASN_PARSE_E; - } - - /* decrypt CEK with KEK */ - ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, blockSz, pkiMsg + (*idx), - length, cek, cekSz, tmpIv, - blockSz, pwriEncAlgoId); - if (ret < 0) { - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return ret; - } - cekSz = ret; - - if (*decryptedKeySz < cekSz) { - WOLFSSL_MSG("Decrypted key buffer too small for CEK"); - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return BUFFER_E; - } - - XMEMCPY(decryptedKey, cek, cekSz); - *decryptedKeySz = cekSz; - - XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - - /* mark recipFound, since we only support one RecipientInfo for now */ - *recipFound = 1; - *idx += length; - - return 0; + return ret; } /* decode ASN.1 KEKRecipientInfo (kekri), return 0 on success, * < 0 on error */ -static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, +static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { @@ -6945,75 +7268,107 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte dateFormat; word32 keyIdSz, kekIdSz, keyWrapOID; - /* remove KEKIdentifier */ - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; + int ret = 0; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + word32 tmpIdx = *idx; - kekIdSz = length; + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_KEKRI: + //@TODO for now just get full buffer, needs divided up - if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) - return ASN_PARSE_E; + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + + pkcs7->stream->length, &pkiMsg, idx)) != 0) { + return ret; + } - if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + #endif + /* remove KEKIdentifier */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; - /* save keyIdentifier and length */ - keyId = pkiMsg; - keyIdSz = length; - *idx += keyIdSz; + kekIdSz = length; + + if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* save keyIdentifier and length */ + keyId = pkiMsg; + keyIdSz = length; + *idx += keyIdSz; + + /* may have OPTIONAL GeneralizedTime */ + if ((*idx < kekIdSz) && (pkiMsg[*idx] == ASN_GENERALIZED_TIME)) { + if (wc_GetDateInfo(pkiMsg + *idx, pkiMsgSz, &datePtr, &dateFormat, + &dateLen) != 0) { + return ASN_PARSE_E; + } + *idx += (dateLen + 1); + } + + /* may have OPTIONAL OtherKeyAttribute */ + if ((*idx < kekIdSz) && (pkiMsg[*idx] == + (ASN_SEQUENCE | ASN_CONSTRUCTED))) { + + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* skip it */ + *idx += length; + } + + /* get KeyEncryptionAlgorithmIdentifier */ + if (GetAlgoId(pkiMsg, idx, &keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get EncryptedKey */ + if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* decrypt CEK with KEK */ + keySz = wc_PKCS7_KeyWrap(pkiMsg + *idx, length, pkcs7->privateKey, + pkcs7->privateKeySz, decryptedKey, *decryptedKeySz, + keyWrapOID, AES_DECRYPTION); + if (keySz <= 0) + return keySz; + + *decryptedKeySz = (word32)keySz; + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + *idx += length; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + break; + + default: + WOLFSSL_MSG("PKCS7 KEKRI unknown state"); + ret = BAD_FUNC_ARG; - /* may have OPTIONAL GeneralizedTime */ - if ((*idx < kekIdSz) && (pkiMsg[*idx] == ASN_GENERALIZED_TIME)) { - if (wc_GetDateInfo(pkiMsg + *idx, pkiMsgSz, &datePtr, &dateFormat, - &dateLen) != 0) { - return ASN_PARSE_E; - } - *idx += (dateLen + 1); } - /* may have OPTIONAL OtherKeyAttribute */ - if ((*idx < kekIdSz) && (pkiMsg[*idx] == - (ASN_SEQUENCE | ASN_CONSTRUCTED))) { - - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* skip it */ - *idx += length; - } - - /* get KeyEncryptionAlgorithmIdentifier */ - if (GetAlgoId(pkiMsg, idx, &keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* get EncryptedKey */ - if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) - return ASN_PARSE_E; - - if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* decrypt CEK with KEK */ - keySz = wc_PKCS7_KeyWrap(pkiMsg + *idx, length, pkcs7->privateKey, - pkcs7->privateKeySz, decryptedKey, *decryptedKeySz, - keyWrapOID, AES_DECRYPTION); - if (keySz <= 0) - return keySz; - - *decryptedKeySz = (word32)keySz; - - /* mark recipFound, since we only support one RecipientInfo for now */ - *recipFound = 1; - *idx += length; - (void)keyId; - return 0; + return ret; } /* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success, * < 0 on error */ -static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, +static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { @@ -7029,141 +7384,171 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; #endif - WC_PKCS7_KARI* kari; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + word32 tmpIdx = *idx; - if (pkcs7 == NULL || pkcs7->singleCert == NULL || - pkcs7->singleCertSz == 0 || pkiMsg == NULL || - idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL) { - return BAD_FUNC_ARG; - } + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_KARI: { + //@TODO for now just get full buffer, needs divided up - kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_DECODE); - if (kari == NULL) - return MEMORY_E; + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + + pkcs7->stream->length, &pkiMsg, idx)) != 0) { + return ret; + } -#ifdef WOLFSSL_SMALL_STACK - encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, - DYNAMIC_TYPE_PKCS7); - if (encryptedKey == NULL) { - wc_PKCS7_KariFree(kari); - return MEMORY_E; - } -#endif - encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; - - /* parse cert and key */ - ret = wc_PKCS7_KariParseRecipCert(kari, (byte*)pkcs7->singleCert, - pkcs7->singleCertSz, pkcs7->privateKey, - pkcs7->privateKeySz); - if (ret != 0) { - wc_PKCS7_KariFree(kari); - #ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); #endif - return ret; - } + WC_PKCS7_KARI* kari; + + if (pkcs7 == NULL || pkcs7->singleCert == NULL || + pkcs7->singleCertSz == 0 || pkiMsg == NULL || + idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL) { + return BAD_FUNC_ARG; + } + + kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_DECODE); + if (kari == NULL) + return MEMORY_E; - /* remove OriginatorIdentifierOrKey */ - ret = wc_PKCS7_KariGetOriginatorIdentifierOrKey(kari, pkiMsg, - pkiMsgSz, idx); - if (ret != 0) { - wc_PKCS7_KariFree(kari); #ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedKey == NULL) { + wc_PKCS7_KariFree(kari); + return MEMORY_E; + } #endif - return ret; - } + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; - /* try and remove optional UserKeyingMaterial */ - ret = wc_PKCS7_KariGetUserKeyingMaterial(kari, pkiMsg, pkiMsgSz, idx); - if (ret != 0) { - wc_PKCS7_KariFree(kari); - #ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + /* parse cert and key */ + ret = wc_PKCS7_KariParseRecipCert(kari, (byte*)pkcs7->singleCert, + pkcs7->singleCertSz, pkcs7->privateKey, + pkcs7->privateKeySz); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* remove OriginatorIdentifierOrKey */ + ret = wc_PKCS7_KariGetOriginatorIdentifierOrKey(kari, pkiMsg, + pkiMsgSz, idx); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* try and remove optional UserKeyingMaterial */ + ret = wc_PKCS7_KariGetUserKeyingMaterial(kari, pkiMsg, pkiMsgSz, idx); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* remove KeyEncryptionAlgorithmIdentifier */ + ret = wc_PKCS7_KariGetKeyEncryptionAlgorithmId(kari, pkiMsg, pkiMsgSz, + idx, &keyAgreeOID, + &keyWrapOID); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* if user has not explicitly set keyAgreeOID, set from one in bundle */ + if (pkcs7->keyAgreeOID == 0) + pkcs7->keyAgreeOID = keyAgreeOID; + + /* set direction based on key wrap algorithm */ + switch (keyWrapOID) { + #ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + #endif + direction = AES_DECRYPTION; + break; #endif - return ret; - } + default: + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + WOLFSSL_MSG("AES key wrap algorithm unsupported"); + return BAD_KEYWRAP_ALG_E; + } - /* remove KeyEncryptionAlgorithmIdentifier */ - ret = wc_PKCS7_KariGetKeyEncryptionAlgorithmId(kari, pkiMsg, pkiMsgSz, - idx, &keyAgreeOID, - &keyWrapOID); - if (ret != 0) { - wc_PKCS7_KariFree(kari); - #ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - #endif - return ret; - } + /* remove RecipientEncryptedKeys */ + ret = wc_PKCS7_KariGetRecipientEncryptedKeys(kari, pkiMsg, pkiMsgSz, + idx, recipFound, encryptedKey, &encryptedKeySz); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } - /* if user has not explicitly set keyAgreeOID, set from one in bundle */ - if (pkcs7->keyAgreeOID == 0) - pkcs7->keyAgreeOID = keyAgreeOID; + /* create KEK */ + ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, pkcs7->keyAgreeOID); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* decrypt CEK with KEK */ + keySz = wc_PKCS7_KeyWrap(encryptedKey, encryptedKeySz, kari->kek, + kari->kekSz, decryptedKey, *decryptedKeySz, + keyWrapOID, direction); + if (keySz <= 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return keySz; + } + *decryptedKeySz = (word32)keySz; - /* set direction based on key wrap algorithm */ - switch (keyWrapOID) { -#ifndef NO_AES - #ifdef WOLFSSL_AES_128 - case AES128_WRAP: - #endif - #ifdef WOLFSSL_AES_192 - case AES192_WRAP: - #endif - #ifdef WOLFSSL_AES_256 - case AES256_WRAP: - #endif - direction = AES_DECRYPTION; - break; -#endif - default: wc_PKCS7_KariFree(kari); #ifdef WOLFSSL_SMALL_STACK XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #endif - WOLFSSL_MSG("AES key wrap algorithm unsupported"); - return BAD_KEYWRAP_ALG_E; + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + } + break; + + default: + WOLFSSL_MSG("PKCS7 kari unknown state"); + ret = BAD_FUNC_ARG; + } - - /* remove RecipientEncryptedKeys */ - ret = wc_PKCS7_KariGetRecipientEncryptedKeys(kari, pkiMsg, pkiMsgSz, - idx, recipFound, encryptedKey, &encryptedKeySz); - if (ret != 0) { - wc_PKCS7_KariFree(kari); - #ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - #endif - return ret; - } - - /* create KEK */ - ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, pkcs7->keyAgreeOID); - if (ret != 0) { - wc_PKCS7_KariFree(kari); - #ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - #endif - return ret; - } - - /* decrypt CEK with KEK */ - keySz = wc_PKCS7_KeyWrap(encryptedKey, encryptedKeySz, kari->kek, - kari->kekSz, decryptedKey, *decryptedKeySz, - keyWrapOID, direction); - if (keySz <= 0) { - wc_PKCS7_KariFree(kari); - #ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - #endif - return keySz; - } - *decryptedKeySz = (word32)keySz; - - wc_PKCS7_KariFree(kari); - #ifdef WOLFSSL_SMALL_STACK - XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - #endif - - return 0; + return ret; #else (void)pkcs7; (void)pkiMsg; @@ -7179,12 +7564,14 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, /* decode ASN.1 RecipientInfos SET, return 0 on success, < 0 on error */ -static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, - word32 pkiMsgSz, word32* idx, byte* decryptedKey, +static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, + word32 inSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { - word32 savedIdx; - int version, ret, length; + word32 savedIdx, tmpIdx = *idx; + int version, ret = 0, length; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; if (pkcs7 == NULL || pkiMsg == NULL || idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL || @@ -7192,7 +7579,49 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, return BAD_FUNC_ARG; } + /* check if in the process of decrypting */ + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_KTRI: + case WC_PKCS7_DECRYPT_KTRI_2: + case WC_PKCS7_DECRYPT_KTRI_3: + ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + break; + + case WC_PKCS7_DECRYPT_KARI: + ret = wc_PKCS7_DecryptKari(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + break; + + case WC_PKCS7_DECRYPT_KEKRI: + ret = wc_PKCS7_DecryptKekri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + break; + + case WC_PKCS7_DECRYPT_PWRI: + ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + break; + + case WC_PKCS7_DECRYPT_ORI: + ret = wc_PKCS7_DecryptOri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + break; + + default: + /* not in decrypting state */ + break; + } + + if (ret < 0) { + return ret; + } + savedIdx = *idx; +#ifndef NO_PKCS7_STREAM + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + if (pkiMsgSz != inSz) pkiMsg = pkcs7->stream->buffer; +#endif /* when looking for next recipient, use first sequence and version to * indicate there is another, if not, move on */ @@ -7204,7 +7633,13 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, #ifndef NO_RSA /* found ktri */ - ret = wc_PKCS7_DecryptKtri(pkcs7, pkiMsg, pkiMsgSz, idx, + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI); + ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx, decryptedKey, decryptedKeySz, recipFound); if (ret != 0) @@ -7232,7 +7667,13 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, return ASN_VERSION_E; /* found kari */ - ret = wc_PKCS7_DecryptKari(pkcs7, pkiMsg, pkiMsgSz, idx, + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KARI); + ret = wc_PKCS7_DecryptKari(pkcs7, in, inSz, idx, decryptedKey, decryptedKeySz, recipFound); if (ret != 0) @@ -7255,7 +7696,13 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, return ASN_VERSION_E; /* found kekri */ - ret = wc_PKCS7_DecryptKekri(pkcs7, pkiMsg, pkiMsgSz, idx, + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KEKRI); + ret = wc_PKCS7_DecryptKekri(pkcs7, in, inSz, idx, decryptedKey, decryptedKeySz, recipFound); if (ret != 0) @@ -7278,7 +7725,13 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, return ASN_VERSION_E; /* found pwri */ - ret = wc_PKCS7_DecryptPwri(pkcs7, pkiMsg, pkiMsgSz, idx, + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_PWRI); + ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx, decryptedKey, decryptedKeySz, recipFound); if (ret != 0) @@ -7290,7 +7743,13 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, (*idx)++; /* found ori */ - ret = wc_PKCS7_DecryptOri(pkcs7, pkiMsg, pkiMsgSz, idx, + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_ORI); + ret = wc_PKCS7_DecryptOri(pkcs7, in, inSz, idx, decryptedKey, decryptedKeySz, recipFound); if (ret != 0) @@ -7307,19 +7766,22 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* pkiMsg, savedIdx = *idx; } - return 0; + return ret; } /* Parse encoded EnvelopedData bundle up to RecipientInfo set. * * return size of RecipientInfo SET on success, negative upon error */ -static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* pkiMsg, - word32 pkiMsgSz, word32* idx, +static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, + word32 inSz, word32* idx, int type) { - int version, length, ret; + int version, length, ret = 0; word32 contentType; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + word32 tmpIdx = 0; if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || idx == NULL) return BAD_FUNC_ARG; @@ -7327,84 +7789,203 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* pkiMsg, if ((type != ENVELOPED_DATA) && (type != AUTH_ENVELOPED_DATA)) return BAD_FUNC_ARG; - /* read past ContentInfo, verify type is envelopedData */ - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (length == 0 && pkiMsg[(*idx)-1] == 0x80) { -#ifdef ASN_BER_TO_DER - word32 len = 0; - - ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); - if (ret != LENGTH_ONLY_E) +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { return ret; - pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - if (pkcs7->der == NULL) - return MEMORY_E; - ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); - if (ret < 0) - return ret; - - pkiMsg = pkcs7->der; - pkiMsgSz = len; - *idx = 0; - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; -#else - return BER_INDEF_E; + } + } #endif + + switch (pkcs7->state) { + case WC_PKCS7_INFOSET_START: + case WC_PKCS7_INFOSET_BER: + case WC_PKCS7_INFOSET_STAGE1: + case WC_PKCS7_INFOSET_STAGE2: + case WC_PKCS7_INFOSET_END: + break; + + default: + WOLFSSL_MSG("Warning, setting PKCS7 info state to start"); + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_START); } - if (wc_GetContentType(pkiMsg, idx, &contentType, pkiMsgSz) < 0) - return ASN_PARSE_E; + switch (pkcs7->state) { + case WC_PKCS7_INFOSET_START: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + ASN_TAG_SZ, &pkiMsg, idx)) != 0) { + return ret; + } - if (type == ENVELOPED_DATA && contentType != ENVELOPED_DATA) { - WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData"); - return PKCS7_OID_E; - - } else if (type == AUTH_ENVELOPED_DATA && - contentType != AUTH_ENVELOPED_DATA) { - WOLFSSL_MSG("PKCS#7 input not of type AuthEnvelopedData"); - return PKCS7_OID_E; - } - - if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) - return ASN_PARSE_E; - - if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* remove EnvelopedData and version */ - if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (type == ENVELOPED_DATA) { - /* TODO :: make this more accurate */ - if ((pkcs7->publicKeyOID == RSAk && version != 0) - #ifdef HAVE_ECC - || (pkcs7->publicKeyOID == ECDSAk && version != 2) + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); #endif - ) { - WOLFSSL_MSG("PKCS#7 envelopedData version incorrect"); - return ASN_VERSION_E; - } - } else { - /* AuthEnvelopedData version MUST be 0 */ - if (version != 0) { - WOLFSSL_MSG("PKCS#7 AuthEnvelopedData needs to be of version 0"); - return ASN_VERSION_E; - } + /* read past ContentInfo, verify type is envelopedData */ + if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + { + ret = ASN_PARSE_E; + } + + if (ret == 0 && length == 0 && pkiMsg[(*idx)-1] == 0x80) { + #ifdef ASN_BER_TO_DER + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_BER); + FALL_THROUGH; + + /* full buffer is needed for conversion */ + case WC_PKCS7_INFOSET_BER: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->maxLen - pkcs7->stream->length, + &pkiMsg, idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + #endif + + word32 len = 0; + + ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); + if (ret != LENGTH_ONLY_E) + return ret; + pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->der == NULL) + return MEMORY_E; + ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); + if (ret < 0) + return ret; + + pkiMsg = pkcs7->der; + pkiMsgSz = len; + *idx = 0; + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + #else + return BER_INDEF_E; + #endif + } + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_STAGE1); + FALL_THROUGH; + + case WC_PKCS7_INFOSET_STAGE1: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_OID_SZ + + MAX_LENGTH_SZ + ASN_TAG_SZ, &pkiMsg, idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + #endif + if (ret == 0 && wc_GetContentType(pkiMsg, idx, &contentType, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0) { + if (type == ENVELOPED_DATA && contentType != ENVELOPED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData"); + ret = PKCS7_OID_E; + } else if (type == AUTH_ENVELOPED_DATA && + contentType != AUTH_ENVELOPED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type AuthEnvelopedData"); + ret = PKCS7_OID_E; + } + } + + if (ret == 0 && pkiMsg[(*idx)++] != + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_STAGE2); + FALL_THROUGH; + + case WC_PKCS7_INFOSET_STAGE2: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_VERSION_SZ, &pkiMsg, idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + #endif + /* remove EnvelopedData and version */ + if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + + pkcs7->stream->varOne = version; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_END); + FALL_THROUGH; + + case WC_PKCS7_INFOSET_END: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + MAX_SET_SZ, &pkiMsg, idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + version = pkcs7->stream->varOne; + #endif + + if (type == ENVELOPED_DATA) { + /* TODO :: make this more accurate */ + if ((pkcs7->publicKeyOID == RSAk && version != 0) + #ifdef HAVE_ECC + || (pkcs7->publicKeyOID == ECDSAk && version != 2) + #endif + ) { + WOLFSSL_MSG("PKCS#7 envelopedData version incorrect"); + ret = ASN_VERSION_E; + } + } else { + /* AuthEnvelopedData version MUST be 0 */ + if (version != 0) { + WOLFSSL_MSG("PKCS#7 AuthEnvelopedData needs to be of version 0"); + ret = ASN_VERSION_E; + } + } + + /* remove RecipientInfo set, get length of set */ + if (ret == 0 && GetSet(pkiMsg, idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0) + ret = length; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + break; + + default: + WOLFSSL_MSG("Bad PKCS7 info set state"); + ret = BAD_FUNC_ARG; + break; } - /* remove RecipientInfo set, get length of set */ - if (GetSet(pkiMsg, idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - (void)ret; - return length; + return ret; } @@ -8066,29 +8647,31 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, /* unwrap and decrypt PKCS#7 AuthEnvelopedData object, return decoded size */ -WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, - word32 pkiMsgSz, byte* output, +WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, + word32 inSz, byte* output, word32 outputSz) { int recipFound = 0; int ret, length; - word32 idx = 0; + word32 idx = 0, tmpIdx = 0; word32 contentType, encOID; word32 decryptedKeySz; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; - int expBlockSz, blockKeySz; + int expBlockSz, blockKeySz = 0; byte authTag[AES_BLOCK_SIZE]; byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */ int nonceSz, authTagSz, macSz; #ifdef WOLFSSL_SMALL_STACK - byte* decryptedKey; + byte* decryptedKey = NULL; #else byte decryptedKey[MAX_ENCRYPTED_KEY_SZ]; #endif int encryptedContentSz; byte* encryptedContent = NULL; - int explicitOctet; + int explicitOctet = 0; byte authAttribSetByte = 0; byte* encodedAttribs = NULL; @@ -8102,244 +8685,476 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, if (pkiMsg == NULL || pkiMsgSz == 0 || output == NULL || outputSz == 0) return BAD_FUNC_ARG; - - length = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, &idx, - AUTH_ENVELOPED_DATA); - if (length < 0) - return length; - -#ifdef WOLFSSL_SMALL_STACK - decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, - DYNAMIC_TYPE_PKCS7); - if (decryptedKey == NULL) - return MEMORY_E; -#endif - decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; - - ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, pkiMsg, pkiMsgSz, &idx, - decryptedKey, &decryptedKeySz, - &recipFound); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ret; +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } } - - if (recipFound == 0) { - WOLFSSL_MSG("No recipient found in envelopedData that matches input"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #endif - return PKCS7_RECIP_E; - } - /* remove EncryptedContentInfo */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + switch (pkcs7->state) { + case WC_PKCS7_START: + case WC_PKCS7_INFOSET_START: + case WC_PKCS7_INFOSET_STAGE1: + case WC_PKCS7_INFOSET_STAGE2: + case WC_PKCS7_INFOSET_END: + ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, + &idx, AUTH_ENVELOPED_DATA); + if (ret < 0) + break; + +#ifndef NO_PKCS7_STREAM + tmpIdx = idx; #endif - return ASN_PARSE_E; - } + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_2); + FALL_THROUGH; - if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + case WC_PKCS7_AUTHENV_2: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); #endif - return ASN_PARSE_E; - } + #ifdef WOLFSSL_SMALL_STACK + decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (decryptedKey == NULL) + return MEMORY_E; + #endif + FALL_THROUGH; - if (GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + case WC_PKCS7_DECRYPT_KTRI: + case WC_PKCS7_DECRYPT_KTRI_2: + case WC_PKCS7_DECRYPT_KTRI_3: + case WC_PKCS7_DECRYPT_KARI: + case WC_PKCS7_DECRYPT_KEKRI: + case WC_PKCS7_DECRYPT_PWRI: + case WC_PKCS7_DECRYPT_ORI: + + decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + + ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx, + decryptedKey, &decryptedKeySz, + &recipFound); + if (ret != 0) { + return ret; + } + + if (recipFound == 0) { + WOLFSSL_MSG("No recipient found in envelopedData that matches input"); + return PKCS7_RECIP_E; + } + +#ifndef NO_PKCS7_STREAM + tmpIdx = idx; #endif - return ASN_PARSE_E; - } + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_3); + FALL_THROUGH; - blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); - if (blockKeySz < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + case WC_PKCS7_AUTHENV_3: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_ALGO_SZ + MAX_ALGO_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); #endif - return blockKeySz; - } - expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); - if (expBlockSz < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + /* remove EncryptedContentInfo */ + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); + if (ret == 0 && blockKeySz < 0) { + ret = blockKeySz; + } + + expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); + if (ret == 0 && expBlockSz < 0) { + ret = expBlockSz; + } + + /* get nonce, stored in OPTIONAL parameter of AlgoID */ + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + } + + if (ret < 0) + break; + +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, 0); #endif - return expBlockSz; - } + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_4); + FALL_THROUGH; - /* get nonce, stored in OPTIONAL parameter of AlgoID */ - if (pkiMsg[idx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + case WC_PKCS7_AUTHENV_4: + +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + MAX_VERSION_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); #endif - return ASN_PARSE_E; - } + if (ret == 0 && GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } - if (GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (ret == 0 && nonceSz > (int)sizeof(nonce)) { + WOLFSSL_MSG("AuthEnvelopedData nonce too large for buffer"); + ret = ASN_PARSE_E; + } + + if (ret == 0) { + XMEMCPY(nonce, &pkiMsg[idx], nonceSz); + idx += nonceSz; + } + + /* get mac size, also stored in OPTIONAL parameter of AlgoID */ + if (ret == 0 && GetMyVersion(pkiMsg, &idx, &macSz, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0) { + explicitOctet = pkiMsg[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); + } + + /* read encryptedContent, cont[0] */ + if (ret == 0 && pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) && + pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + ret = ASN_PARSE_E; + } + idx++; + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + } + + if (explicitOctet) { + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + } + } + + if (ret < 0) + break; + +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + + /* store nonce for later */ + if (nonceSz > 0) { + pkcs7->stream->nonceSz = nonceSz; + pkcs7->stream->nonce = (byte*)XMALLOC(nonceSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->nonce == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->nonce, nonce, nonceSz); + } + } + + pkcs7->stream->expected = encryptedContentSz; + wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, encryptedContentSz); #endif - return ASN_PARSE_E; - } - if (nonceSz > (int)sizeof(nonce)) { - WOLFSSL_MSG("AuthEnvelopedData nonce too large for buffer"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_5); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_5: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + ASN_TAG_SZ + ASN_TAG_SZ + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + encryptedContentSz = pkcs7->stream->expected; #endif - return ASN_PARSE_E; - } - XMEMCPY(nonce, &pkiMsg[idx], nonceSz); - idx += nonceSz; + encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (ret == 0 && encryptedContent == NULL) { + ret = MEMORY_E; + } + + if (ret == 0) { + XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); + idx += encryptedContentSz; + } + #ifndef NO_PKCS7_STREAM + pkcs7->stream->bufferPt = encryptedContent; + #endif + + /* may have IMPLICIT [1] authenticatedAttributes */ + if (ret == 0 && pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + encodedAttribIdx = idx; + encodedAttribs = pkiMsg + idx; + idx++; + + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->expected = length; + #endif + encodedAttribSz = length + (idx - encodedAttribIdx); + + if (ret != 0) break; + + #ifndef NO_PKCS7_STREAM + if (encodedAttribSz > 0) { + pkcs7->stream->aadSz = encodedAttribSz; + pkcs7->stream->aad = (byte*)XMALLOC(encodedAttribSz, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->aad == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->aad, encodedAttribs, + (idx - encodedAttribIdx)); + } + } + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRB); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_ATRB: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + length = pkcs7->stream->expected; + encodedAttribs = pkcs7->stream->aad; + #endif + + /* save pointer and length */ + authAttrib = &pkiMsg[idx]; + authAttribSz = length; + + if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, authAttrib, authAttribSz) < 0) { + WOLFSSL_MSG("Error parsing authenticated attributes"); + ret = ASN_PARSE_E; + } + + idx += length; + + #ifndef NO_PKCS7_STREAM + if (encodedAttribSz > 0) { + XMEMCPY(pkcs7->stream->aad + (encodedAttribSz - length), authAttrib, authAttribSz); + } + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRBEND); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_ATRBEND: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + + if (pkcs7->stream->aadSz > 0) { + encodedAttribSz = pkcs7->stream->aadSz; + encodedAttribs = pkcs7->stream->aad; + } + #endif + + } + + /* get authTag OCTET STRING */ + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, &authTagSz, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && authTagSz > (int)sizeof(authTag)) { + WOLFSSL_MSG("AuthEnvelopedData authTag too large for buffer"); + ret = ASN_PARSE_E; + } + + if (ret == 0) { + XMEMCPY(authTag, &pkiMsg[idx], authTagSz); + idx += authTagSz; + } + + if (ret == 0 && 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; + } + + if (ret < 0) + break; + +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + + + /* store tag for later */ + if (authTagSz > 0) { + pkcs7->stream->tagSz = authTagSz; + pkcs7->stream->tag = (byte*)XMALLOC(authTagSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->tag == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->tag, authTag, authTagSz); + } + } - /* get mac size, also stored in OPTIONAL parameter of AlgoID */ - if (GetMyVersion(pkiMsg, &idx, &macSz, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #endif - return ASN_PARSE_E; - } + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_6); + FALL_THROUGH; - explicitOctet = pkiMsg[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); + case WC_PKCS7_AUTHENV_6: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } - /* read encryptedContent, cont[0] */ - if (pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) && - pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + /* restore all variables needed */ + if (pkcs7->stream->nonceSz > 0) { + nonceSz = pkcs7->stream->nonceSz; + if (nonceSz > GCM_NONCE_MID_SZ) { + WOLFSSL_MSG("PKCS7 saved nonce is too large"); + ret = BUFFER_E; + break; + } + else { + XMEMCPY(nonce, pkcs7->stream->nonce, nonceSz); + } + } + + if (pkcs7->stream->tagSz > 0) { + authTagSz = pkcs7->stream->tagSz; + if (authTagSz > AES_BLOCK_SIZE) { + WOLFSSL_MSG("PKCS7 saved tag is too large"); + ret = BUFFER_E; + break; + } + else { + XMEMCPY(authTag, pkcs7->stream->tag, authTagSz); + } + } + + if (pkcs7->stream->aadSz > 0) { + encodedAttribSz = pkcs7->stream->aadSz; + encodedAttribs = pkcs7->stream->aad; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + wc_PKCS7_StreamGetVar(pkcs7, &encOID, &blockKeySz, &encryptedContentSz); + encryptedContent = pkcs7->stream->bufferPt; #endif - return ASN_PARSE_E; - } - idx++; - if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } + /* decrypt encryptedContent */ + ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, + nonce, nonceSz, encodedAttribs, + encodedAttribSz, authTag, authTagSz, + encryptedContent, encryptedContentSz, + encryptedContent); + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } - if (explicitOctet) { - if (pkiMsg[idx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK + if (authAttrib != NULL) { + /* restore authAttrib IMPLICIT [1] */ + encodedAttribs[0] = authAttribSetByte; + } + + /* copy plaintext to output */ + XMEMCPY(output, encryptedContent, encryptedContentSz); + + /* free memory, zero out keys */ + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (decryptedKey != NULL) { + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); + } + #ifdef WOLFSSL_SMALL_STACK XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; + decryptedKey = NULL; + #endif + ret = encryptedContentSz; + #ifndef NO_PKCS7_STREAM + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + break; + default: + WOLFSSL_MSG("Unknown PKCS7 state"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + if (decryptedKey != NULL) { + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); } - - if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } - } - - encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, - DYNAMIC_TYPE_PKCS7); - if (encryptedContent == NULL) { -#ifdef WOLFSSL_SMALL_STACK XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } #endif - return MEMORY_E; +#ifndef NO_PKCS7_STREAM + if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + wc_PKCS7_ResetStream(pkcs7); } - - 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 - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); #endif - return ASN_PARSE_E; - } - - if (GetLength(pkiMsg, &idx, &authTagSz, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } - - if (authTagSz > (int)sizeof(authTag)) { - WOLFSSL_MSG("AuthEnvelopedData authTag too large for buffer"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } - - 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, encodedAttribs, - encodedAttribSz, authTag, authTagSz, - encryptedContent, encryptedContentSz, - encryptedContent); - if (ret != 0) { - XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ret; - } - - if (authAttrib != NULL) { - /* restore authAttrib IMPLICIT [1] */ - encodedAttribs[0] = authAttribSetByte; - } - - /* copy plaintext to output */ - XMEMCPY(output, encryptedContent, encryptedContentSz); - - /* free memory, zero out keys */ - ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); - ForceZero(encryptedContent, encryptedContentSz); - XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - - return encryptedContentSz; + return ret; } @@ -8681,21 +9496,11 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, if (ret != 0) break; #ifndef NO_PKCS7_STREAM - if (pkcs7->stream->length > 0) { - if (pkcs7->stream->length < idx) { - ret = BUFFER_E; - break; - } - XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx, - pkcs7->stream->length - idx); - pkcs7->stream->length -= idx; - } - else { - pkcs7->stream->totalRd += idx - tmpIdx; - tmpIdx = idx; + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; } #endif - pkcs7->state = WC_PKCS7_STAGE2; + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE2); FALL_THROUGH; /* end of stage 1 */ @@ -8722,21 +9527,11 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, if (ret != 0) break; #ifndef NO_PKCS7_STREAM - if (pkcs7->stream->length > 0) { - if (pkcs7->stream->length < idx) { - ret = BUFFER_E; - break; - } - XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx, - pkcs7->stream->length - idx); - pkcs7->stream->length -= idx; - } - else { - pkcs7->stream->totalRd += idx - tmpIdx; - tmpIdx = idx; + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; } #endif - pkcs7->state = WC_PKCS7_STAGE3; + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE3); FALL_THROUGH; /* end of stage 2 */ @@ -8775,24 +9570,14 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, pkcs7->stream->varOne = expBlockSz; pkcs7->stream->varTwo = encOID; - if (pkcs7->stream->length > 0) { - if (pkcs7->stream->length < idx) { - ret = BUFFER_E; - break; - } - XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx, - pkcs7->stream->length - idx); - pkcs7->stream->length -= idx; - } - else { - pkcs7->stream->totalRd += idx - tmpIdx; - tmpIdx = idx; + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; } /* store version for later */ pkcs7->stream->vers = version; #endif - pkcs7->state = WC_PKCS7_STAGE4; + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE4); FALL_THROUGH; /* end of stage 3 */ @@ -8825,21 +9610,11 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, /* next chunk of data expected should have the IV */ pkcs7->stream->expected = length; - if (pkcs7->stream->length > 0) { - if (pkcs7->stream->length < idx) { - ret = BUFFER_E; - break; - } - XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx, - pkcs7->stream->length - idx); - pkcs7->stream->length -= idx; - } - else { - pkcs7->stream->totalRd += idx - tmpIdx; - tmpIdx = idx; + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; } #endif - pkcs7->state = WC_PKCS7_STAGE5; + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE5); FALL_THROUGH; /* end of stage 4 */ @@ -8872,18 +9647,8 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, #ifndef NO_PKCS7_STREAM /* next chunk of data should contain encrypted content */ pkcs7->stream->varThree = encryptedContentSz; - if (pkcs7->stream->length > 0) { - if (pkcs7->stream->length < idx) { - ret = BUFFER_E; - break; - } - XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + idx, - pkcs7->stream->length - idx); - pkcs7->stream->length -= idx; - } - else { - pkcs7->stream->totalRd += idx - tmpIdx; - tmpIdx = idx; + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; } if (pkcs7->stream->totalRd + encryptedContentSz < pkiMsgSz) { @@ -8894,7 +9659,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, pkcs7->stream->totalRd) + pkcs7->stream->length; #endif - pkcs7->state = WC_PKCS7_STAGE6; + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE6); FALL_THROUGH; /* end of stage 5 */ @@ -8975,7 +9740,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, #ifndef NO_PKCS7_STREAM wc_PKCS7_ResetStream(pkcs7); #endif - pkcs7->state = WC_PKCS7_START; + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); break; default: @@ -8986,7 +9751,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, if (ret != 0) { /* restart in error case */ wc_PKCS7_ResetStream(pkcs7); - pkcs7->state = WC_PKCS7_START; + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); } return ret; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 6d96b274e..1f46edea0 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19380,6 +19380,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, enveloped, envelopedSz, decoded, sizeof(decoded)); if (decodedSz <= 0) { + printf("ret = %d\n", decodedSz); wc_PKCS7_Free(pkcs7); return -9325; } @@ -19985,7 +19986,25 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, wc_PKCS7_Free(pkcs7); return -9385; } - +#ifndef NO_PKCS7_STREAM + { /* test reading byte by byte */ + int z; + for (z = 0; z < envelopedSz; z++) { + decodedSz = wc_PKCS7_DecodeAuthEnvelopedData(pkcs7, + enveloped + z, 1, decoded, sizeof(decoded)); + if (decodedSz <= 0 && decodedSz != WC_PKCS7_WANT_READ_E) { + printf("unexpected error %d\n", decodedSz); + return -9386; + } + } + /* test decode result */ + if (XMEMCMP(decoded, data, sizeof(data)) != 0) { + printf("stream read compare failed\n"); + wc_PKCS7_Free(pkcs7); + return -9387; + } + } +#endif /* decode envelopedData */ decodedSz = wc_PKCS7_DecodeAuthEnvelopedData(pkcs7, enveloped, envelopedSz, decoded, diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 4a5c052da..4a27602d3 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -88,11 +88,44 @@ enum PKCS7_TYPES { enum PKCS7_STATE { WC_PKCS7_START = 0, + + /* decode encrypted */ WC_PKCS7_STAGE2, WC_PKCS7_STAGE3, WC_PKCS7_STAGE4, WC_PKCS7_STAGE5, - WC_PKCS7_STAGE6 + WC_PKCS7_STAGE6, + + /* parse info set */ + WC_PKCS7_INFOSET_START, + WC_PKCS7_INFOSET_BER, + WC_PKCS7_INFOSET_STAGE1, + WC_PKCS7_INFOSET_STAGE2, + WC_PKCS7_INFOSET_END, + + /* decode auth enveloped */ + WC_PKCS7_AUTHENV_2, + WC_PKCS7_AUTHENV_3, + WC_PKCS7_AUTHENV_4, + WC_PKCS7_AUTHENV_5, + WC_PKCS7_AUTHENV_6, + WC_PKCS7_AUTHENV_ATRB, + WC_PKCS7_AUTHENV_ATRBEND, + WC_PKCS7_AUTHENV_7, + + /* decryption state types */ + WC_PKCS7_DECRYPT_KTRI, + WC_PKCS7_DECRYPT_KTRI_2, + WC_PKCS7_DECRYPT_KTRI_3, + + + WC_PKCS7_DECRYPT_KARI, + WC_PKCS7_DECRYPT_KEKRI, + WC_PKCS7_DECRYPT_PWRI, + WC_PKCS7_DECRYPT_ORI, + + WC_PKCS7_DECRYPT_DONE, + }; enum Pkcs7_Misc { @@ -235,7 +268,7 @@ typedef struct PKCS7 { #ifndef NO_PKCS7_STREAM PKCS7State* stream; #endif - enum PKCS7_STATE state; + word32 state; /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ } PKCS7; From b0e4cb3572f6fae67192b1af0526405f4e9cb449 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Fri, 12 Oct 2018 10:21:39 -0700 Subject: [PATCH 33/56] valgrind testing --- wolfcrypt/src/pkcs7.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index cd0c0734e..b2d52e3c7 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -5280,6 +5280,7 @@ int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (recip == NULL) return MEMORY_E; + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); /* get key size for content-encryption key based on algorithm */ blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); @@ -9439,7 +9440,7 @@ static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg, int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, byte* output, word32 outputSz) { - int ret = 0, version, length, haveAttribs; + int ret = 0, version, length, haveAttribs = 0; word32 idx = 0, tmpIdx = 0; word32 contentType, encOID; @@ -9632,7 +9633,8 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, expBlockSz = pkcs7->stream->varOne; /* use IV buffer from stream structure */ - tmpIv = pkcs7->stream->tmpIv; + tmpIv = pkcs7->stream->tmpIv; + length = pkcs7->stream->expected; #endif XMEMCPY(tmpIv, &pkiMsg[idx], length); idx += length; @@ -9705,6 +9707,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); /* get implicit[1] unprotected attributes, optional */ + wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); pkcs7->decodedAttrib = NULL; #ifndef NO_PKCS7_STREAM if (pkcs7->stream->hasAtrib) { From b4d02d6d9914f7f941464170af7fc02bb4fec2bc Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 12 Oct 2018 15:07:46 -0600 Subject: [PATCH 34/56] fix setting and checking CMS EnvelopedData version --- wolfcrypt/src/pkcs7.c | 145 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 129 insertions(+), 16 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index b2d52e3c7..4506229f8 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -663,6 +663,7 @@ typedef struct Pkcs7EncodedRecip { byte recip[MAX_RECIP_SZ]; word32 recipSz; int recipType; + int recipVersion; Pkcs7EncodedRecip* next; } Pkcs7EncodedRecip; @@ -735,6 +736,51 @@ static void wc_PKCS7_FreeEncodedRecipientSet(PKCS7* pkcs7) } +/* search through RecipientInfo list for specific type. + * return 1 if ANY recipient of type specified is present, otherwise + * return 0 */ +static int wc_PKCS7_RecipientListIncludesType(PKCS7* pkcs7, int type) +{ + Pkcs7EncodedRecip* tmp = NULL; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + tmp = pkcs7->recipList; + + while (tmp != NULL) { + if (tmp->recipType == type) + return 1; + + tmp = tmp->next; + } + + return 0; +} + + +/* searches through RecipientInfo list, returns 1 if all structure + * versions are set to 0, otherwise returns 0 */ +static int wc_PKCS7_RecipientListVersionsAllZero(PKCS7* pkcs7) +{ + Pkcs7EncodedRecip* tmp = NULL; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + tmp = pkcs7->recipList; + + while (tmp != NULL) { + if (tmp->recipVersion != 0) + return 0; + + tmp = tmp->next; + } + + return 1; +} + + /* Init PKCS7 struct with recipient cert, decode into DecodedCert * NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */ int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) @@ -3829,6 +3875,12 @@ static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, if (ret < 0) return ret; + /* only supports ECDSA for now */ + if (kari->decoded->keyOID != ECDSAk) { + WOLFSSL_MSG("CMS KARI only supports ECDSA key types"); + return BAD_FUNC_ARG; + } + /* make sure subject key id was read from cert */ if (kari->decoded->extSubjKeyIdSet == 0) { WOLFSSL_MSG("Failed to read subject key ID from recipient cert"); @@ -4142,6 +4194,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, int ret = 0; int keySz, direction = 0; + int blockKeySz = 0; /* ASN.1 layout */ int totalSz = 0; @@ -4204,14 +4257,24 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, } XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); - /* only supports ECDSA for now */ - if (pkcs7->publicKeyOID != ECDSAk) { - WOLFSSL_MSG("CMS KARI only supports ECDSA key types"); + /* get key size for content-encryption key based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - return BAD_FUNC_ARG; + return blockKeySz; + } + + /* generate random content encryption key, if needed */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; } /* set direction based on keyWrapAlgo */ @@ -4375,6 +4438,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, /* version, always 3 */ verSz = SetMyVersion(3, ver, 0); totalSz += verSz; + recip->recipVersion = 3; /* outer IMPLICIT [1] kari */ kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq); @@ -4608,6 +4672,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, /* version, must be 0 for IssuerAndSerialNumber */ verSz = SetMyVersion(0, ver, 0); + recip->recipVersion = 0; /* IssuerAndSerialNumber */ if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) { @@ -4647,6 +4712,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, /* version, must be 2 for SubjectKeyIdentifier */ verSz = SetMyVersion(2, ver, 0); + recip->recipVersion = 2; issuerSKIDSz = SetOctetString(KEYID_SIZE, issuerSKID); issuerSKIDSeqSz = SetExplicit(0, issuerSKIDSz + KEYID_SIZE, @@ -5327,6 +5393,7 @@ int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb, /* store recipient size */ recip->recipSz = idx; recip->recipType = PKCS7_ORI; + recip->recipVersion = 4; /* add recipient to recip list */ if (pkcs7->recipList == NULL) { @@ -5756,6 +5823,7 @@ int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, /* set PasswordRecipientInfo CMSVersion, MUST be 0 */ verSz = SetMyVersion(0, ver, 0); totalSz += verSz; + recip->recipVersion = 0; /* set PasswordRecipientInfo SEQ */ recipSeqSz = SetImplicit(ASN_SEQUENCE, 3, totalSz, recipSeq); @@ -5974,6 +6042,7 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, /* version */ verSz = SetMyVersion(4, ver, 0); totalSz += verSz; + recip->recipVersion = 4; /* KEKRecipientInfo SEQ */ recipSeqSz = SetImplicit(ASN_SEQUENCE, 2, totalSz, recipSeq); @@ -6035,6 +6104,47 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, } +static int wc_PKCS7_GetCMSVersion(PKCS7* pkcs7, int cmsContentType) +{ + int version = -1; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + switch (cmsContentType) { + case ENVELOPED_DATA: + + /* NOTE: EnvelopedData does not currently support + originatorInfo or unprotectedAttributes. When either of these + are added, version checking below needs to be updated to match + Section 6.1 of RFC 5652 */ + + /* if RecipientInfos include pwri or ori, version is 3 */ + if (wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_PWRI) || + wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_ORI)) { + version = 3; + break; + } + + /* if unprotectedAttrs is absent AND all RecipientInfo structs + are version 0, version is 0 */ + if (wc_PKCS7_RecipientListVersionsAllZero(pkcs7)) { + version = 0; + break; + } + + /* otherwise, version is 2 */ + version = 2; + break; + + default: + break; + } + + return version; +} + + /* build PKCS#7 envelopedData content type, return enveloped size */ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) { @@ -6046,6 +6156,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) byte outerContentType[MAX_ALGO_SZ]; byte outerContent[MAX_SEQ_SZ]; + int kariVersion; int envDataSeqSz, verSz; byte envDataSeq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; @@ -6090,16 +6201,6 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) outerContentTypeSz = ret; - /* version, defined as 0 in RFC 2315 */ -#ifdef HAVE_ECC - if (pkcs7->publicKeyOID == ECDSAk) { - verSz = SetMyVersion(2, ver, 0); - } else -#endif - { - verSz = SetMyVersion(0, ver, 0); - } - /* generate random content encryption key */ ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); if (ret != 0) { @@ -6146,6 +6247,15 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) } recipSetSz = SetSet(recipSz, recipSet); + /* version, defined in Section 6.1 of RFC 5652 */ + kariVersion = wc_PKCS7_GetCMSVersion(pkcs7, ENVELOPED_DATA); + if (kariVersion < 0) { + WOLFSSL_MSG("Failed to set CMS EnvelopedData version"); + return PKCS7_RECIP_E; + } + + verSz = SetMyVersion(kariVersion, ver, 0); + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); if (ret != 0) return ret; @@ -6477,6 +6587,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, pkcs7->stream->expected = encryptedKeySz; #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_3); + FALL_THROUGH; case WC_PKCS7_DECRYPT_KTRI_3: #ifndef NO_PKCS7_STREAM @@ -7950,9 +8061,11 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, if (type == ENVELOPED_DATA) { /* TODO :: make this more accurate */ - if ((pkcs7->publicKeyOID == RSAk && version != 0) + if ((pkcs7->publicKeyOID == RSAk && + (version != 0 && version != 2)) #ifdef HAVE_ECC - || (pkcs7->publicKeyOID == ECDSAk && version != 2) + || (pkcs7->publicKeyOID == ECDSAk && + (version != 0 && version != 2 && version != 3)) #endif ) { WOLFSSL_MSG("PKCS#7 envelopedData version incorrect"); From 47303ed445e8b672ff8b8e3ad3799e035838fdda Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 12 Oct 2018 15:51:16 -0600 Subject: [PATCH 35/56] fix decryption of EnvelopedData PWRI KEK size --- wolfcrypt/src/pkcs7.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 4506229f8..2af5561fc 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -7181,7 +7181,7 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, byte tmpIv[MAX_CONTENT_IV_SIZE]; - int ret = 0, length, saltSz, iterations, blockSz; + int ret = 0, length, saltSz, iterations, blockSz, kekKeySz; int hashOID = WC_SHA; /* default to SHA1 */ word32 kdfAlgoId, pwriEncAlgoId, keyEncAlgoId, cekSz; byte* pkiMsg = in; @@ -7262,6 +7262,13 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, return blockSz; } + /* get content-encryption key size, based on algorithm */ + kekKeySz = wc_PKCS7_GetOIDKeySize(pwriEncAlgoId); + if (kekKeySz < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return kekKeySz; + } + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ if ( (pkiMsgSz > ((*idx) + 1)) && (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { @@ -7304,7 +7311,7 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, } /* generate KEK */ - kek = (byte*)XMALLOC(blockSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + kek = (byte*)XMALLOC(kekKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (kek == NULL) { XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -7313,7 +7320,7 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, pkcs7->pass, pkcs7->passSz, salt, saltSz, kdfAlgoId, hashOID, - iterations, kek, blockSz); + iterations, kek, kekKeySz); if (ret < 0) { XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -7322,9 +7329,10 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, } /* decrypt CEK with KEK */ - ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, blockSz, pkiMsg + (*idx), - length, cek, cekSz, tmpIv, - blockSz, pwriEncAlgoId); + ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, kekKeySz, + pkiMsg + (*idx), length, cek, + cekSz, tmpIv, blockSz, + pwriEncAlgoId); if (ret < 0) { XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); From 5525f59852a13c4e4340cb22ebcb38321e91a118 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 18 Oct 2018 10:48:05 -0600 Subject: [PATCH 36/56] first addition of verify sign stream data --- tests/api.c | 19 +- wolfcrypt/src/pkcs7.c | 1086 +++++++++++++++++++++++-------------- wolfcrypt/test/test.c | 14 + wolfssl/wolfcrypt/pkcs7.h | 6 + 4 files changed, 706 insertions(+), 419 deletions(-) diff --git a/tests/api.c b/tests/api.c index 20b9dd7c6..ce7d13d63 100644 --- a/tests/api.c +++ b/tests/api.c @@ -15343,18 +15343,29 @@ static void test_wc_PKCS7_EncodeSignedData_ex(void) AssertIntEQ(wc_PKCS7_VerifySignedData_ex(NULL, hashBuf, hashSz, outputHead, outputHeadSz, outputFoot, outputFootSz), BAD_FUNC_ARG); + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, NULL, hashSz, outputHead, - outputHeadSz, outputFoot, outputFootSz), ASN_PARSE_E); + outputHeadSz, outputFoot, outputFootSz), BAD_FUNC_ARG); +#ifndef NO_PKCS7_STREAM AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, 0, outputHead, - outputHeadSz, outputFoot, outputFootSz), ASN_PARSE_E); + outputHeadSz, outputFoot, outputFootSz), WC_PKCS7_WANT_READ_E); +#else + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, 0, outputHead, + outputHeadSz, outputFoot, outputFootSz), BUFFER_E); +#endif AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, NULL, outputHeadSz, outputFoot, outputFootSz), BAD_FUNC_ARG); AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, outputHead, 0, outputFoot, outputFootSz), BAD_FUNC_ARG); AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, - outputHead, outputHeadSz, NULL, outputFootSz), ASN_PARSE_E); + outputHead, outputHeadSz, NULL, outputFootSz), BAD_FUNC_ARG); +#ifndef NO_PKCS7_STREAM AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, - outputHead, outputHeadSz, outputFoot, 0), ASN_PARSE_E); + outputHead, outputHeadSz, outputFoot, 0), WC_PKCS7_WANT_READ_E); +#else + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, outputHeadSz, outputFoot, 0), BUFFER_E); +#endif printf(resultFmt, passed); diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 2af5561fc..9a57ce8e6 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -58,7 +58,6 @@ typedef enum { WC_PKCS7_DECODE } pkcs7Direction; - #ifndef NO_PKCS7_STREAM #define MAX_PKCS7_STREAM_BUFFER 256 @@ -68,6 +67,8 @@ typedef struct PKCS7State { byte* nonce; /* stored nonce */ byte* aad; /* additional data for AEAD algos */ byte* tag; /* tag data for AEAD algos */ + byte* content; + byte multi; /* flag for if content is in multiple parts */ /* stack variables to store for when returning */ word32 varOne; @@ -85,6 +86,7 @@ typedef struct PKCS7State { word32 nonceSz; /* size of nonce stored */ word32 aadSz; /* size of additional AEAD data */ word32 tagSz; /* size of tag for AEAD */ + word32 contentSz; byte tmpIv[MAX_CONTENT_IV_SIZE]; /* store IV if needed */ #ifdef WC_PKCS7_STREAM_DEBUG word32 peakUsed; /* most bytes used for struct at any one time */ @@ -159,6 +161,10 @@ static void wc_PKCS7_FreeStream(PKCS7* pkcs7) { if (pkcs7 != NULL && pkcs7->stream != NULL) { wc_PKCS7_ResetStream(pkcs7); + + XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream, pkcs7->heap, DYNAMIC_TYPE_PKCS7); } } @@ -315,14 +321,14 @@ static const char* wc_PKCS7_GetStateName(int in) case WC_PKCS7_STAGE5: return "WC_PKCS7_STAGE5"; case WC_PKCS7_STAGE6: return "WC_PKCS7_STAGE6"; - /* parse info set */ - case WC_PKCS7_INFOSET_START: return "WC_PKCS7_INFOSET_START"; - case WC_PKCS7_INFOSET_BER: return "WC_PKCS7_INFOSET_BER"; + /* parse info set */ + case WC_PKCS7_INFOSET_START: return "WC_PKCS7_INFOSET_START"; + case WC_PKCS7_INFOSET_BER: return "WC_PKCS7_INFOSET_BER"; case WC_PKCS7_INFOSET_STAGE1: return "WC_PKCS7_INFOSET_STAGE1"; case WC_PKCS7_INFOSET_STAGE2: return "WC_PKCS7_INFOSET_STAGE2"; - case WC_PKCS7_INFOSET_END: return "WC_PKCS7_INFOSET_END"; + case WC_PKCS7_INFOSET_END: return "WC_PKCS7_INFOSET_END"; - /* decode auth enveloped */ + /* decode auth enveloped */ case WC_PKCS7_AUTHENV_2: return "WC_PKCS7_AUTHENV_2"; case WC_PKCS7_AUTHENV_3: return "WC_PKCS7_AUTHENV_3"; case WC_PKCS7_AUTHENV_4: return "WC_PKCS7_AUTHENV_4"; @@ -332,18 +338,22 @@ static const char* wc_PKCS7_GetStateName(int in) case WC_PKCS7_AUTHENV_ATRBEND: return "WC_PKCS7_AUTHENV_ATRBEND"; case WC_PKCS7_AUTHENV_7: return "WC_PKCS7_AUTHENV_7"; - /* decryption state types */ - case WC_PKCS7_DECRYPT_KTRI: return "WC_PKCS7_DECRYPT_KTRI"; + /* decryption state types */ + case WC_PKCS7_DECRYPT_KTRI: return "WC_PKCS7_DECRYPT_KTRI"; case WC_PKCS7_DECRYPT_KTRI_2: return "WC_PKCS7_DECRYPT_KTRI_2"; case WC_PKCS7_DECRYPT_KTRI_3: return "WC_PKCS7_DECRYPT_KTRI_3"; - - case WC_PKCS7_DECRYPT_KARI: return "WC_PKCS7_DECRYPT_KARI"; + case WC_PKCS7_DECRYPT_KARI: return "WC_PKCS7_DECRYPT_KARI"; case WC_PKCS7_DECRYPT_KEKRI: return "WC_PKCS7_DECRYPT_KEKRI"; - case WC_PKCS7_DECRYPT_PWRI: return "WC_PKCS7_DECRYPT_PWRI"; - case WC_PKCS7_DECRYPT_ORI: return "WC_PKCS7_DECRYPT_ORI"; + case WC_PKCS7_DECRYPT_PWRI: return "WC_PKCS7_DECRYPT_PWRI"; + case WC_PKCS7_DECRYPT_ORI: return "WC_PKCS7_DECRYPT_ORI"; + case WC_PKCS7_DECRYPT_DONE: return "WC_PKCS7_DECRYPT_DONE"; - case WC_PKCS7_DECRYPT_DONE: return "WC_PKCS7_DECRYPT_DONE"; + case WC_PKCS7_VERIFY_STAGE2: return "WC_PKCS7_VERIFY_STAGE2"; + case WC_PKCS7_VERIFY_STAGE3: return "WC_PKCS7_VERIFY_STAGE3"; + case WC_PKCS7_VERIFY_STAGE4: return "WC_PKCS7_VERIFY_STAGE4"; + case WC_PKCS7_VERIFY_STAGE5: return "WC_PKCS7_VERIFY_STAGE5"; + case WC_PKCS7_VERIFY_STAGE6: return "WC_PKCS7_VERIFY_STAGE6"; default: return "Unknown state"; @@ -2583,7 +2593,6 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, } ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, key); - FreeDecodedCert(dCert); wc_FreeRsaKey(key); @@ -3130,10 +3139,10 @@ void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag) * signer is required. In this case the PKCS7 flag noDegenerate could be set. */ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, - word32 hashSz, byte* pkiMsg, word32 pkiMsgSz, + word32 hashSz, byte* in, word32 inSz, byte* pkiMsg2, word32 pkiMsg2Sz) { - word32 idx, outerContentType, hashOID, sigOID, contentTypeSz, totalSz; + word32 idx, outerContentType, hashOID, sigOID, contentTypeSz = 0, totalSz = 0; int length, version, ret; byte* content = NULL; byte* contentDynamic = NULL; @@ -3143,443 +3152,687 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, byte* contentType = NULL; int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0; word32 localIdx, start; - byte degenerate; + byte degenerate = 0; #ifdef ASN_BER_TO_DER byte* der; #endif int multiPart = 0, keepContent; int contentLen; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + word32 stateIdx = 0; + if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0) return BAD_FUNC_ARG; + if ((hashSz > 0 && hashBuf == NULL) || (pkiMsg2Sz > 0 && pkiMsg2 == NULL)) { + return BAD_FUNC_ARG; + } idx = 0; - /* determine total message size */ - totalSz = pkiMsgSz; - if (pkiMsg2 && pkiMsg2Sz > 0) { - totalSz += pkiMsg2Sz + pkcs7->contentSz; +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } } - - /* Get the contentInfo sequence */ - if (GetSequence(pkiMsg, &idx, &length, totalSz) < 0) - return ASN_PARSE_E; - - if (length == 0 && pkiMsg[idx-1] == 0x80) { -#ifdef ASN_BER_TO_DER - word32 len = 0; - - ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); - if (ret != LENGTH_ONLY_E) - return ret; - pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - if (pkcs7->der == NULL) - return MEMORY_E; - ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); - if (ret < 0) - return ret; - - pkiMsg = pkcs7->der; - pkiMsgSz = len; - idx = 0; - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; -#else - return BER_INDEF_E; #endif - } - /* Get the contentInfo contentType */ - if (wc_GetContentType(pkiMsg, &idx, &outerContentType, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (outerContentType != SIGNED_DATA) { - WOLFSSL_MSG("PKCS#7 input not of type SignedData"); - return PKCS7_OID_E; - } - - /* get the ContentInfo content */ - if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) - return ASN_PARSE_E; - - if (GetLength(pkiMsg, &idx, &length, totalSz) < 0) - return ASN_PARSE_E; - - /* Get the signedData sequence */ - if (GetSequence(pkiMsg, &idx, &length, totalSz) < 0) - return ASN_PARSE_E; - - /* Get the version */ - if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) - return ASN_PARSE_E; - - if (version != 1) { - WOLFSSL_MSG("PKCS#7 signedData needs to be of version 1"); - return ASN_VERSION_E; - } - - /* Get the set of DigestAlgorithmIdentifiers */ - if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* Skip the set. */ - idx += length; - degenerate = (length == 0)? 1 : 0; - if (pkcs7->noDegenerate == 1 && degenerate == 1) { - return PKCS7_NO_SIGNER_E; - } - - /* Get the inner ContentInfo sequence */ - if (GetSequence(pkiMsg, &idx, &length, totalSz) < 0) - return ASN_PARSE_E; - - /* Get the inner ContentInfo contentType */ - { - word32 tmpIdx = idx; - - if (GetASNObjectId(pkiMsg, &idx, &length, pkiMsgSz) != 0) - return ASN_PARSE_E; - - contentType = pkiMsg + tmpIdx; - contentTypeSz = length + (idx - tmpIdx); - - idx += length; - } - - /* Check for content info, it could be omitted when degenerate */ - localIdx = idx; - ret = 0; - if (pkiMsg[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) - ret = ASN_PARSE_E; - - if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) <= 0) - ret = ASN_PARSE_E; - - if (ret == 0 && pkiMsg[localIdx] == (ASN_OCTET_STRING | ASN_CONSTRUCTED)) { - multiPart = 1; - - localIdx++; - /* Get length of all OCTET_STRINGs. */ - if (GetLength(pkiMsg, &localIdx, &contentLen, totalSz) < 0) - ret = ASN_PARSE_E; - - /* Check whether there is one OCTET_STRING inside. */ - start = localIdx; - if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING) - ret = ASN_PARSE_E; - - if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) - ret = ASN_PARSE_E; - - if (ret == 0) { - /* Use single OCTET_STRING directly. */ - if (localIdx - start + length == (word32)contentLen) - multiPart = 0; - localIdx = start; - } - } - if (ret == 0 && multiPart) { - int i = 0; - keepContent = !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0); - - if (keepContent) { - /* Create a buffer to hold content of OCTET_STRINGs. */ - pkcs7->contentDynamic = (byte*)XMALLOC(contentLen, pkcs7->heap, - DYNAMIC_TYPE_PKCS7); - if (pkcs7->contentDynamic == NULL) - ret = MEMORY_E; - } - - start = localIdx; - /* Use the data from each OCTET_STRING. */ - while (ret == 0 && localIdx < start + contentLen) { - if (pkiMsg[localIdx++] != ASN_OCTET_STRING) - ret = ASN_PARSE_E; - - if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) - ret = ASN_PARSE_E; - if (ret == 0 && length + localIdx > start + contentLen) - ret = ASN_PARSE_E; - - if (ret == 0) { - if (keepContent) { - XMEMCPY(pkcs7->contentDynamic + i, pkiMsg + localIdx, - length); - } - i += length; - localIdx += length; + switch (pkcs7->state) { + case WC_PKCS7_START: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_LENGTH_SZ + + ASN_TAG_SZ + MAX_OID_SZ + MAX_SEQ_SZ, + &pkiMsg, &idx)) != 0) { + return ret; } - } - length = i; - if (ret == 0 && length > 0) { - contentSz = length; + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + #endif - /* support using header and footer without content */ - if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) { - /* Content not provided, use provided pkiMsg2 footer */ - content = NULL; - localIdx = 0; - if (contentSz != (int)pkcs7->contentSz) { - WOLFSSL_MSG("Data signed does not match contentSz provided"); - return BUFFER_E; - } + /* determine total message size */ + totalSz = pkiMsgSz; + if (pkiMsg2 && pkiMsg2Sz > 0) { + totalSz += pkiMsg2Sz + pkcs7->contentSz; } - else { - /* Content pointer for calculating hashes later */ - content = pkcs7->contentDynamic; - pkiMsg2 = pkiMsg; - pkiMsg2Sz = pkiMsgSz; + + /* Get the contentInfo sequence */ + if (GetSequence(pkiMsg, &idx, &length, totalSz) < 0) + return ASN_PARSE_E; + + if (length == 0 && pkiMsg[idx-1] == 0x80) { + #ifdef ASN_BER_TO_DER + word32 len = 0; + + ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); + if (ret != LENGTH_ONLY_E) + return ret; + pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->der == NULL) + return MEMORY_E; + ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); + if (ret < 0) + return ret; + + pkiMsg = pkcs7->der; + pkiMsgSz = len; + idx = 0; + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + #else + return BER_INDEF_E; + #endif } - } - else { - pkiMsg2 = pkiMsg; - } - } - if (ret == 0 && !multiPart) { - if (pkiMsg[localIdx++] != ASN_OCTET_STRING) - ret = ASN_PARSE_E; - if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) - ret = ASN_PARSE_E; + /* Get the contentInfo contentType */ + if (wc_GetContentType(pkiMsg, &idx, &outerContentType, pkiMsgSz) < 0) + return ASN_PARSE_E; - /* Save the inner data as the content. */ - if (ret == 0 && length > 0) { - contentSz = length; - - /* support using header and footer without content */ - if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) { - /* Content not provided, use provided pkiMsg2 footer */ - content = NULL; - localIdx = 0; - if (contentSz != (int)pkcs7->contentSz) { - WOLFSSL_MSG("Data signed does not match contentSz provided"); - return BUFFER_E; - } + if (outerContentType != SIGNED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type SignedData"); + return PKCS7_OID_E; } - else { - /* Content pointer for calculating hashes later */ - content = &pkiMsg[localIdx]; - localIdx += length; - pkiMsg2 = pkiMsg; - pkiMsg2Sz = pkiMsgSz; + /* get the ContentInfo content */ + if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &length, totalSz) < 0) + return ASN_PARSE_E; + + /* Get the signedData sequence */ + if (GetSequence(pkiMsg, &idx, &length, totalSz) < 0) + return ASN_PARSE_E; + + /* Get the version */ + if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (version != 1) { + WOLFSSL_MSG("PKCS#7 signedData needs to be of version 1"); + return ASN_VERSION_E; } - } - else { - pkiMsg2 = pkiMsg; - } - } - /* update idx if successful */ - if (ret == 0) - idx = localIdx; - else { - pkiMsg2 = pkiMsg; - pkiMsg2Sz = pkiMsgSz; - } + /* Get the set of DigestAlgorithmIdentifiers */ + if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; - /* If getting the content info failed with non degenerate then return the - * error case. Otherwise with a degenerate it is ok if the content - * info was omitted */ - if (!degenerate && ret != 0) { - return ret; - } + /* Skip the set. */ + idx += length; + degenerate = (length == 0)? 1 : 0; + if (pkcs7->noDegenerate == 1 && degenerate == 1) { + return PKCS7_NO_SIGNER_E; + } - /* Get the implicit[0] set of certificates */ - if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { - idx++; - if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + pkcs7->stream->maxLen = totalSz; + wc_PKCS7_StreamStoreVar(pkcs7, totalSz, 0, 0); + #endif - if (length > 0) { - /* At this point, idx is at the first certificate in - * a set of certificates. There may be more than one, - * or none, or they may be a PKCS 6 extended - * certificate. We want to save the first cert if it - * is X.509. */ + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE2); + FALL_THROUGH; - word32 certIdx = idx; + case WC_PKCS7_VERIFY_STAGE2: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ + ASN_TAG_SZ + + MAX_LENGTH_SZ, + &pkiMsg, &idx)) != 0) { + return ret; + } - if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { - if (GetLength(pkiMsg2, &certIdx, &certSz, pkiMsg2Sz) < 0) + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + wc_PKCS7_StreamGetVar(pkcs7, &totalSz, 0, 0); + #endif + + /* Get the inner ContentInfo sequence */ + if (GetSequence(pkiMsg, &idx, &length, totalSz) < 0) + return ASN_PARSE_E; + + /* Get the inner ContentInfo contentType */ + { + word32 tmpIdx = idx; + + if (GetASNObjectId(pkiMsg, &idx, &length, pkiMsgSz) != 0) return ASN_PARSE_E; - cert = &pkiMsg2[idx]; - certSz += (certIdx - idx); + contentType = pkiMsg + tmpIdx; + contentTypeSz = length + (idx - tmpIdx); + + idx += length; } -#ifdef ASN_BER_TO_DER - der = pkcs7->der; -#endif - contentDynamic = pkcs7->contentDynamic; - /* This will reset PKCS7 structure and then set the certificate */ - wc_PKCS7_InitWithCert(pkcs7, cert, certSz); - pkcs7->contentDynamic = contentDynamic; -#ifdef ASN_BER_TO_DER - pkcs7->der = der; -#endif + /* Check for content info, it could be omitted when degenerate */ + localIdx = idx; + ret = 0; + if (pkiMsg[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; - /* iterate through any additional certificates */ - if (MAX_PKCS7_CERTS > 0) { - int sz = 0; - int i; + if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) <= 0) + ret = ASN_PARSE_E; - pkcs7->cert[0] = cert; - pkcs7->certSz[0] = certSz; - certIdx = idx + certSz; - for (i = 1; i < MAX_PKCS7_CERTS && certIdx + 1 < pkiMsg2Sz; i++) { - localIdx = certIdx; + /* get length of content in the case that there is multiple parts */ + if (ret == 0 && pkiMsg[localIdx] == (ASN_OCTET_STRING | ASN_CONSTRUCTED)) { + multiPart = 1; - if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { - if (GetLength(pkiMsg2, &certIdx, &sz, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + localIdx++; + /* Get length of all OCTET_STRINGs. */ + if (GetLength(pkiMsg, &localIdx, &contentLen, totalSz) < 0) + ret = ASN_PARSE_E; - pkcs7->cert[i] = &pkiMsg2[localIdx]; - pkcs7->certSz[i] = sz + (certIdx - localIdx); - certIdx += sz; - } + /* Check whether there is one OCTET_STRING inside. */ + start = localIdx; + if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0) { + /* Use single OCTET_STRING directly. */ + if (localIdx - start + length == (word32)contentLen) + multiPart = 0; + localIdx = start; } } - } - idx += length; - } - /* set content and size after init of PKCS7 structure */ - pkcs7->content = content; - pkcs7->contentSz = contentSz; + /* get length of content in case of single part */ + if (ret == 0 && !multiPart) { + if (pkiMsg[localIdx++] != ASN_OCTET_STRING) + ret = ASN_PARSE_E; - /* set contentType and size after init of PKCS7 structure */ - if (wc_PKCS7_SetContentType(pkcs7, contentType, contentTypeSz) < 0) - return ASN_PARSE_E; - - /* Get the implicit[1] set of crls */ - if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { - idx++; - if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; - - /* Skip the set */ - idx += length; - } - - /* Get the set of signerInfos */ - if (GetSet(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; - - /* require a signer if degenerate case not allowed */ - if (length == 0 && pkcs7->noDegenerate == 1) - return PKCS7_NO_SIGNER_E; - - if (degenerate == 0 && length == 0) { - WOLFSSL_MSG("PKCS7 signers expected"); - return PKCS7_NO_SIGNER_E; - } - - if (length > 0 && degenerate == 0) { - /* Get the sequence of the first signerInfo */ - if (GetSequence(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; - - /* Get the version */ - if (GetMyVersion(pkiMsg2, &idx, &version, pkiMsg2Sz) < 0) - return ASN_PARSE_E; - - if (version == 1) { - /* Get the sequence of IssuerAndSerialNumber */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; - - /* Skip it */ - idx += length; - - } else if (version == 3) { - /* Get the sequence of SubjectKeyIdentifier */ - if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { - ret = ASN_PARSE_E; + if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) + ret = ASN_PARSE_E; } - if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) <= 0) { - ret = ASN_PARSE_E; + /* update idx if successful */ + if (ret == 0) { + /* support using header and footer without content */ + if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) { + localIdx = 0; + } + idx = localIdx; } - if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) - ret = ASN_PARSE_E; - - if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) - ret = ASN_PARSE_E; - - /* Skip it */ - idx += length; - - } else { - WOLFSSL_MSG("PKCS#7 signerInfo version must be 1 or 3"); - return ASN_VERSION_E; - } - - /* Get the sequence of digestAlgorithm */ - if (GetAlgoId(pkiMsg2, &idx, &hashOID, oidHashType, pkiMsg2Sz) < 0) { - return ASN_PARSE_E; - } - pkcs7->hashOID = (int)hashOID; - - /* Get the IMPLICIT[0] SET OF signedAttributes */ - if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { - idx++; - - if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; - - /* save pointer and length */ - signedAttrib = &pkiMsg2[idx]; - signedAttribSz = length; - - if (wc_PKCS7_ParseAttribs(pkcs7, signedAttrib, signedAttribSz) <0) { - WOLFSSL_MSG("Error parsing signed attributes"); - return ASN_PARSE_E; + #ifndef NO_PKCS7_STREAM + /* save contentType */ + pkcs7->stream->nonce = (byte*)XMALLOC(contentTypeSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->nonce == NULL) { + ret = MEMORY_E; + } + else { + pkcs7->stream->nonceSz = contentTypeSz; + XMEMCPY(pkcs7->stream->nonce, contentType, contentTypeSz); } - idx += length; - } + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, localIdx, length); - /* Get digestEncryptionAlgorithm */ - if (GetAlgoId(pkiMsg2, &idx, &sigOID, oidSigType, pkiMsg2Sz) < 0) { - return ASN_PARSE_E; - } + /* content expected? */ + if ((ret == 0 && length > 0) && + !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0)) { + pkcs7->stream->expected = length; + } + else { + pkcs7->stream->expected = 0; + } - /* store public key type based on digestEncryptionAlgorithm */ - ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID); - if (ret <= 0) { - WOLFSSL_MSG("Failed to set public key OID from signature"); - return ret; - } + /* content length is in multiple parts */ + if (multiPart) { + pkcs7->stream->expected = contentLen; + } + pkcs7->stream->multi = multiPart; - /* Get the signature */ - if (pkiMsg2[idx] == ASN_OCTET_STRING) { - idx++; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE3); + FALL_THROUGH; - if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + case WC_PKCS7_VERIFY_STAGE3: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, + &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, (int*)&localIdx, &length); + + if (pkcs7->stream->length > 0) { + localIdx = 0; + } + multiPart = pkcs7->stream->multi; + #endif + + /* get parts of content */ + if (ret == 0 && multiPart) { + int i = 0; + keepContent = !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0); + + if (keepContent) { + /* Create a buffer to hold content of OCTET_STRINGs. */ + pkcs7->contentDynamic = (byte*)XMALLOC(contentLen, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->contentDynamic == NULL) + ret = MEMORY_E; + } + + start = localIdx; + /* Use the data from each OCTET_STRING. */ + while (ret == 0 && localIdx < start + contentLen) { + if (pkiMsg[localIdx++] != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && length + localIdx > start + contentLen) + ret = ASN_PARSE_E; + + if (ret == 0) { + if (keepContent) { + XMEMCPY(pkcs7->contentDynamic + i, pkiMsg + localIdx, + length); + } + i += length; + localIdx += length; + } + } + localIdx = start; /* reset for sanity check, increment later */ + length = i; + } + + /* Save the inner data as the content. */ + if (ret == 0 && length > 0) { + contentSz = length; + + /* support using header and footer without content */ + if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) { + /* Content not provided, use provided pkiMsg2 footer */ + content = NULL; + localIdx = 0; + if (contentSz != (int)pkcs7->contentSz) { + WOLFSSL_MSG("Data signed does not match contentSz provided"); + return BUFFER_E; + } + } + else { + if ((word32)length > pkiMsgSz - localIdx) { + return BUFFER_E; + } + + /* Content pointer for calculating hashes later */ + if (ret == 0 && !multiPart) { + content = &pkiMsg[localIdx]; + } + if (ret == 0 && multiPart) { + content = pkcs7->contentDynamic; + } + idx += length; + + pkiMsg2 = pkiMsg; + pkiMsg2Sz = pkiMsgSz; + } + } + else { + pkiMsg2 = pkiMsg; + } + + /* If getting the content info failed with non degenerate then return the + * error case. Otherwise with a degenerate it is ok if the content + * info was omitted */ + if (!degenerate && ret != 0) { + return ret; + } + + /* Get the implicit[0] set of certificates */ + if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + idx++; + if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + return ASN_PARSE_E; + + #ifndef NO_PKCS7_STREAM + /* save content */ + if (content != NULL) { + XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->content = (byte*)XMALLOC(contentSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->content == NULL) { + ret = MEMORY_E; + } + else { + XMEMCPY(pkcs7->stream->content, content, contentSz); + pkcs7->stream->contentSz = contentSz; + } + } + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); + if (length > 0) { + pkcs7->stream->expected = length; + } + else { + pkcs7->stream->expected = MAX_SEQ_SZ; + } + pkcs7->stream->bufferPt = pkiMsg2; + #endif + if (ret != 0) { + break; + } + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE4); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE4: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + pkiMsg2Sz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); + pkiMsg2 = pkcs7->stream->bufferPt; + + /* restore content */ + content = pkcs7->stream->content; + contentSz = pkcs7->stream->contentSz; + + /* store certificate */ + if (length > 0) { + pkcs7->stream->tmpCert = (byte*)XMALLOC(length, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->tmpCert == NULL) { + return MEMORY_E; + } + XMEMCPY(pkcs7->stream->tmpCert, pkiMsg2 + idx, length); + pkiMsg2 = pkcs7->stream->tmpCert; + idx = 0; + } + #endif + + if (length > 0) { + /* At this point, idx is at the first certificate in + * a set of certificates. There may be more than one, + * or none, or they may be a PKCS 6 extended + * certificate. We want to save the first cert if it + * is X.509. */ + + word32 certIdx = idx; + + if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { + if (GetLength(pkiMsg2, &certIdx, &certSz, pkiMsg2Sz) < 0) + return ASN_PARSE_E; + + cert = &pkiMsg2[idx]; + certSz += (certIdx - idx); + } + #ifdef ASN_BER_TO_DER + der = pkcs7->der; + #endif + contentDynamic = pkcs7->contentDynamic; + + { + PKCS7State* stream = pkcs7->stream; + /* This will reset PKCS7 structure and then set the + * certificate */ + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + if (ret != 0) + return ret; + pkcs7->stream = stream; + } + pkcs7->contentDynamic = contentDynamic; + #ifdef ASN_BER_TO_DER + pkcs7->der = der; + #endif + + /* iterate through any additional certificates */ + if (MAX_PKCS7_CERTS > 0) { + int sz = 0; + int i; + + pkcs7->cert[0] = cert; + pkcs7->certSz[0] = certSz; + certIdx = idx + certSz; + + for (i = 1; i < MAX_PKCS7_CERTS && certIdx + 1 < pkiMsg2Sz; i++) { + localIdx = certIdx; + + if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { + if (GetLength(pkiMsg2, &certIdx, &sz, pkiMsg2Sz) < 0) + return ASN_PARSE_E; + + pkcs7->cert[i] = &pkiMsg2[localIdx]; + pkcs7->certSz[i] = sz + (certIdx - localIdx); + certIdx += sz; + } + } + } + } + idx += length; + } + + /* set content and size after init of PKCS7 structure */ + pkcs7->content = content; + pkcs7->contentSz = contentSz; + + #ifndef NO_PKCS7_STREAM + idx = stateIdx + idx; + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); + #endif + if (ret != 0) { + break; + } + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE5); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE5: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_OID_SZ + + ASN_TAG_SZ + MAX_LENGTH_SZ + MAX_SET_SZ, + &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); + pkiMsg2 = pkcs7->stream->bufferPt; + + /* restore content type */ + contentType = pkcs7->stream->nonce; + contentTypeSz = pkcs7->stream->nonceSz; + #endif + + /* set contentType and size after init of PKCS7 structure */ + if (wc_PKCS7_SetContentType(pkcs7, contentType, contentTypeSz) < 0) return ASN_PARSE_E; - /* save pointer and length */ - sig = &pkiMsg2[idx]; - sigSz = length; + /* Get the implicit[1] set of crls */ + if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + idx++; + if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + return ASN_PARSE_E; - idx += length; - } + /* Skip the set */ + idx += length; + } - pkcs7->content = content; - pkcs7->contentSz = contentSz; + /* Get the set of signerInfos */ + if (GetSet(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + return ASN_PARSE_E; - ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, - signedAttrib, signedAttribSz, - hashBuf, hashSz); - if (ret < 0) - return ret; + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); + if (length > 0) { + pkcs7->stream->expected = length; + } + else { + pkcs7->stream->expected = 0; + } + pkcs7->stream->bufferPt = pkiMsg2; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE6); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE6: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + pkiMsg2Sz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); + pkiMsg2 = pkcs7->stream->bufferPt; + + /* restore content */ + content = pkcs7->stream->content; + contentSz = pkcs7->stream->contentSz; + #endif + + /* require a signer if degenerate case not allowed */ + if (length == 0 && pkcs7->noDegenerate == 1) + return PKCS7_NO_SIGNER_E; + + if (degenerate == 0 && length == 0) { + WOLFSSL_MSG("PKCS7 signers expected"); + return PKCS7_NO_SIGNER_E; + } + + if (length > 0 && degenerate == 0) { + /* Get the sequence of the first signerInfo */ + if (GetSequence(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + return ASN_PARSE_E; + + /* Get the version */ + if (GetMyVersion(pkiMsg2, &idx, &version, pkiMsg2Sz) < 0) + return ASN_PARSE_E; + + if (version == 1) { + /* Get the sequence of IssuerAndSerialNumber */ + if (GetSequence(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + return ASN_PARSE_E; + + /* Skip it */ + idx += length; + + } else if (version == 3) { + /* Get the sequence of SubjectKeyIdentifier */ + if (pkiMsg2[idx++] != (ASN_CONSTRUCTED | + ASN_CONTEXT_SPECIFIC | 0)) { + return ASN_PARSE_E; + } + + if (ret == 0 && GetLength(pkiMsg2, &idx, &length, + pkiMsg2Sz) <= 0) { + return ASN_PARSE_E; + } + + if (ret == 0 && pkiMsg2[idx++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + return ASN_PARSE_E; + + /* Skip it */ + idx += length; + + } else { + WOLFSSL_MSG("PKCS#7 signerInfo version must be 1 or 3"); + return ASN_VERSION_E; + } + + /* Get the sequence of digestAlgorithm */ + if (GetAlgoId(pkiMsg2, &idx, &hashOID, oidHashType, pkiMsg2Sz) < 0) { + return ASN_PARSE_E; + } + pkcs7->hashOID = (int)hashOID; + + /* Get the IMPLICIT[0] SET OF signedAttributes */ + if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + idx++; + + if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + return ASN_PARSE_E; + + /* save pointer and length */ + signedAttrib = &pkiMsg2[idx]; + signedAttribSz = length; + + if (wc_PKCS7_ParseAttribs(pkcs7, signedAttrib, signedAttribSz) <0) { + WOLFSSL_MSG("Error parsing signed attributes"); + return ASN_PARSE_E; + } + + idx += length; + } + + /* Get digestEncryptionAlgorithm */ + if (GetAlgoId(pkiMsg2, &idx, &sigOID, oidSigType, pkiMsg2Sz) < 0) { + return ASN_PARSE_E; + } + + /* store public key type based on digestEncryptionAlgorithm */ + ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID); + if (ret <= 0) { + WOLFSSL_MSG("Failed to set public key OID from signature"); + return ret; + } + + /* Get the signature */ + if (pkiMsg2[idx] == ASN_OCTET_STRING) { + idx++; + + if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + return ASN_PARSE_E; + + /* save pointer and length */ + sig = &pkiMsg2[idx]; + sigSz = length; + + idx += length; + } + + pkcs7->content = content; + pkcs7->contentSz = contentSz; + + ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, + signedAttrib, signedAttribSz, + hashBuf, hashSz); + if (ret < 0) { + return ret; + } + } + + ret = 0; /* success */ + wc_PKCS7_ResetStream(pkcs7); + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + break; + + default: + WOLFSSL_MSG("PKCS7 Unknown verify state"); + ret = BAD_FUNC_ARG; } - return 0; + if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + wc_PKCS7_ResetStream(pkcs7); + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + } + return ret; } @@ -9822,30 +10075,31 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, } if (ret == 0) { - padLen = encryptedContent[encryptedContentSz-1]; + padLen = encryptedContent[encryptedContentSz-1]; - /* copy plaintext to output */ - XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); + /* copy plaintext to output */ + XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); - /* get implicit[1] unprotected attributes, optional */ - wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); - pkcs7->decodedAttrib = NULL; -#ifndef NO_PKCS7_STREAM - if (pkcs7->stream->hasAtrib) { -#else - if (idx < pkiMsgSz) { -#endif - haveAttribs = 1; + /* get implicit[1] unprotected attributes, optional */ + wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); + pkcs7->decodedAttrib = NULL; + #ifndef NO_PKCS7_STREAM + if (pkcs7->stream->hasAtrib) + #else + if (idx < pkiMsgSz) + #endif + { + haveAttribs = 1; - ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg, - pkiMsgSz, &idx); - if (ret != 0) { - ForceZero(encryptedContent, encryptedContentSz); - XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - ret = ASN_PARSE_E; + ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg, + pkiMsgSz, &idx); + if (ret != 0) { + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + ret = ASN_PARSE_E; + } } } - } if (ret == 0) { /* go back and check the version now that attribs have been processed */ @@ -9861,20 +10115,22 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, } if (ret != 0) break; -#ifndef NO_PKCS7_STREAM + #ifndef NO_PKCS7_STREAM wc_PKCS7_ResetStream(pkcs7); -#endif + #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); break; default: - WOLFSSL_MSG("Error in unknown PKCS#7 state"); + WOLFSSL_MSG("Error in unknown PKCS#7 Decode Encrypted Data state"); return BAD_STATE_E; } if (ret != 0) { + #ifndef NO_PKCS7_STREAM /* restart in error case */ wc_PKCS7_ResetStream(pkcs7); + #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); } return ret; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 1f46edea0..9ec3417e9 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -21411,6 +21411,20 @@ static int pkcs7signed_run_SingleShotVectors( wc_PKCS7_Free(pkcs7); return -9565; } +#ifndef NO_PKCS7_STREAM + { + word32 z; + for (z = 0; z < outSz && ret != 0; z++) { + ret = wc_PKCS7_VerifySignedData(pkcs7, out + z, 1); + if (ret < 0 && ret != WC_PKCS7_WANT_READ_E) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(pkcs7); + printf("unexpected error %d\n", ret); + return -9565; + } + } + } +#endif if (pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 4a27602d3..1349f58d3 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -96,6 +96,12 @@ enum PKCS7_STATE { WC_PKCS7_STAGE5, WC_PKCS7_STAGE6, + WC_PKCS7_VERIFY_STAGE2, + WC_PKCS7_VERIFY_STAGE3, + WC_PKCS7_VERIFY_STAGE4, + WC_PKCS7_VERIFY_STAGE5, + WC_PKCS7_VERIFY_STAGE6, + /* parse info set */ WC_PKCS7_INFOSET_START, WC_PKCS7_INFOSET_BER, From 752259e343fa6f25eeb467607fc30bbfa7d083aa Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Fri, 19 Oct 2018 09:55:20 -0600 Subject: [PATCH 37/56] first addition of decode enveloped stream --- wolfcrypt/src/pkcs7.c | 414 ++++++++++++++++++++++++-------------- wolfcrypt/test/test.c | 20 +- wolfssl/wolfcrypt/pkcs7.h | 6 + 3 files changed, 289 insertions(+), 151 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 9a57ce8e6..1780398fe 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -328,6 +328,12 @@ static const char* wc_PKCS7_GetStateName(int in) case WC_PKCS7_INFOSET_STAGE2: return "WC_PKCS7_INFOSET_STAGE2"; case WC_PKCS7_INFOSET_END: return "WC_PKCS7_INFOSET_END"; + /* decode enveloped data */ + case WC_PKCS7_ENV_2: return "WC_PKCS7_ENV_2"; + case WC_PKCS7_ENV_3: return "WC_PKCS7_ENV_3"; + case WC_PKCS7_ENV_4: return "WC_PKCS7_ENV_4"; + case WC_PKCS7_ENV_5: return "WC_PKCS7_ENV_5"; + /* decode auth enveloped */ case WC_PKCS7_AUTHENV_2: return "WC_PKCS7_AUTHENV_2"; case WC_PKCS7_AUTHENV_3: return "WC_PKCS7_AUTHENV_3"; @@ -3603,7 +3609,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkcs7->certSz[0] = certSz; certIdx = idx + certSz; - for (i = 1; i < MAX_PKCS7_CERTS && certIdx + 1 < pkiMsg2Sz; i++) { + for (i = 1; i < MAX_PKCS7_CERTS && certIdx + 1 < pkiMsg2Sz + && certIdx + 1 < (word32)length; i++) { localIdx = certIdx; if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { @@ -8381,24 +8388,23 @@ WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz) /* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */ -WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, - word32 pkiMsgSz, byte* output, +WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, + word32 inSz, byte* output, word32 outputSz) { int recipFound = 0; int ret, length; - word32 idx = 0; + word32 idx = 0, tmpIdx = 0; word32 contentType, encOID; word32 decryptedKeySz; - int expBlockSz, blockKeySz; - byte tmpIv[MAX_CONTENT_IV_SIZE]; + int expBlockSz = 0, blockKeySz = 0; + byte tmpIvBuf[MAX_CONTENT_IV_SIZE]; + byte* tmpIv = tmpIvBuf; -#ifdef WOLFSSL_SMALL_STACK - byte* decryptedKey; -#else - byte decryptedKey[MAX_ENCRYPTED_KEY_SZ]; -#endif + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + byte* decryptedKey = NULL; int encryptedContentSz; byte padLen; byte* encryptedContent = NULL; @@ -8411,174 +8417,282 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, output == NULL || outputSz == 0) return BAD_FUNC_ARG; - length = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, &idx, - ENVELOPED_DATA); - if (length < 0) - return length; - -#ifdef WOLFSSL_SMALL_STACK - decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, - DYNAMIC_TYPE_PKCS7); - if (decryptedKey == NULL) - return MEMORY_E; +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } + } #endif - decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; - ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, pkiMsg, pkiMsgSz, &idx, + switch (pkcs7->state) { + case WC_PKCS7_START: + case WC_PKCS7_INFOSET_START: + case WC_PKCS7_INFOSET_BER: + case WC_PKCS7_INFOSET_STAGE1: + case WC_PKCS7_INFOSET_STAGE2: + case WC_PKCS7_INFOSET_END: + ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, + &idx, ENVELOPED_DATA); + if (ret < 0) { + break; + } + tmpIdx = idx; + + decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (decryptedKey == NULL) + return MEMORY_E; + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_2); + #ifndef NO_PKCS7_STREAM + pkcs7->stream->aad = decryptedKey; + #endif + FALL_THROUGH; + + case WC_PKCS7_ENV_2: + #ifndef NO_PKCS7_STREAM + /* store up enough buffer for initial info set decode */ + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + #endif + FALL_THROUGH; + + case WC_PKCS7_DECRYPT_KTRI: + case WC_PKCS7_DECRYPT_KTRI_2: + case WC_PKCS7_DECRYPT_KTRI_3: + case WC_PKCS7_DECRYPT_KARI: + case WC_PKCS7_DECRYPT_KEKRI: + case WC_PKCS7_DECRYPT_PWRI: + case WC_PKCS7_DECRYPT_ORI: + #ifndef NO_PKCS7_STREAM + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + inSz); + decryptedKey = pkcs7->stream->aad; + decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + #endif + + + ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx, decryptedKey, &decryptedKeySz, &recipFound); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ret; - } + if (ret == 0 && recipFound == 0) { + WOLFSSL_MSG("No recipient found in envelopedData that matches input"); + ret = PKCS7_RECIP_E; + } - if (recipFound == 0) { - WOLFSSL_MSG("No recipient found in envelopedData that matches input"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return PKCS7_RECIP_E; - } + if (ret != 0) + break; + #ifndef NO_PKCS7_STREAM + tmpIdx = idx; + pkcs7->stream->aadSz = decryptedKeySz; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_3); + FALL_THROUGH; - /* remove EncryptedContentInfo */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } + case WC_PKCS7_ENV_3: - if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + MAX_VERSION_SZ + ASN_TAG_SZ + + MAX_LENGTH_SZ, &pkiMsg, &idx)) + != 0) { + return ret; + } - if (GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + #endif - blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); - if (blockKeySz < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return blockKeySz; - } + /* remove EncryptedContentInfo */ + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } - expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); - if (expBlockSz < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return expBlockSz; - } + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, + pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } - /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ - if (pkiMsg[idx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } + if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, + pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } - if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } + blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); + if (ret == 0 && blockKeySz < 0) { + ret = blockKeySz; + } - if (length != expBlockSz) { - WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } + expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); + if (ret == 0 && expBlockSz < 0) { + ret = expBlockSz; + } - XMEMCPY(tmpIv, &pkiMsg[idx], length); - idx += length; + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + } - explicitOctet = pkiMsg[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } - /* read encryptedContent, cont[0] */ - if (pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) && - pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } - idx++; + if (ret == 0 && length != expBlockSz) { + WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); + ret = ASN_PARSE_E; + } - if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } + if (ret != 0) + break; + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, length); + pkcs7->stream->contentSz = blockKeySz; + pkcs7->stream->expected = length + MAX_LENGTH_SZ + MAX_LENGTH_SZ + + ASN_TAG_SZ + ASN_TAG_SZ; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_4); + FALL_THROUGH; - if (explicitOctet) { - if (pkiMsg[idx++] != ASN_OCTET_STRING) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } + case WC_PKCS7_ENV_4: - if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ASN_PARSE_E; - } - } + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } - encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length); + tmpIv = pkcs7->stream->tmpIv; + #endif + + XMEMCPY(tmpIv, &pkiMsg[idx], length); + idx += length; + + explicitOctet = pkiMsg[idx] == + (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); + + /* read encryptedContent, cont[0] */ + if (ret == 0 && pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) && + pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + ret = ASN_PARSE_E; + } + idx++; + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && explicitOctet) { + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + break; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + break; + } + } + + if (ret != 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + pkcs7->stream->expected = encryptedContentSz; + wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, 0); + wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, + encryptedContentSz); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_5); + FALL_THROUGH; + + case WC_PKCS7_ENV_5: + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, + &encryptedContentSz); + tmpIv = pkcs7->stream->tmpIv; + + /* restore decrypted key */ + decryptedKey = pkcs7->stream->aad; + decryptedKeySz = pkcs7->stream->aadSz; + blockKeySz = pkcs7->stream->contentSz; + #endif + encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - if (encryptedContent == NULL) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return MEMORY_E; - } + if (ret == 0 && encryptedContent == NULL) { + ret = MEMORY_E; + break; + } - XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); + if (ret == 0) { + XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); + } - /* decrypt encryptedContent */ - ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, + /* decrypt encryptedContent */ + ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, tmpIv, expBlockSz, NULL, 0, NULL, 0, encryptedContent, encryptedContentSz, encryptedContent); - if (ret != 0) { - XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#endif - return ret; + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + break; + } + + padLen = encryptedContent[encryptedContentSz-1]; + + /* copy plaintext to output */ + XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); + + /* free memory, zero out keys */ + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + ret = encryptedContentSz - padLen; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->aad = NULL; + pkcs7->stream->aadSz = 0; + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + break; + + default: + WOLFSSL_MSG("PKCS#7 unknown decode enveloped state"); + ret = BAD_FUNC_ARG; } - padLen = encryptedContent[encryptedContentSz-1]; - - /* copy plaintext to output */ - XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); - - /* free memory, zero out keys */ - ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); - ForceZero(encryptedContent, encryptedContentSz); - XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); -#ifdef WOLFSSL_SMALL_STACK - XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#ifndef NO_PKCS7_STREAM + if (ret < 0 && ret != WC_PKCS7_WANT_READ_E) { + wc_PKCS7_ResetStream(pkcs7); + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + } +#else + if (decryptedKey != NULL && ret < 0) { + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); + } + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } #endif - - return encryptedContentSz - padLen; + return ret; } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 9ec3417e9..cad0d9ed1 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19380,7 +19380,6 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, enveloped, envelopedSz, decoded, sizeof(decoded)); if (decodedSz <= 0) { - printf("ret = %d\n", decodedSz); wc_PKCS7_Free(pkcs7); return -9325; } @@ -19391,6 +19390,25 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, return -9326; } +#ifndef NO_PKCS7_STREAM + { /* test reading byte by byte */ + int z; + for (z = 0; z < envelopedSz; z++) { + decodedSz = wc_PKCS7_DecodeEnvelopedData(pkcs7, enveloped + z, 1, + decoded, sizeof(decoded)); + if (decodedSz <= 0 && decodedSz != WC_PKCS7_WANT_READ_E) { + printf("unexpected error %d\n", decodedSz); + return -9325; + } + } + /* test decode result */ + if (XMEMCMP(decoded, data, sizeof(data)) != 0) { + printf("stream read compare failed\n"); + wc_PKCS7_Free(pkcs7); + return -9326; + } + } +#endif #ifdef PKCS7_OUTPUT_TEST_BUNDLES /* output pkcs7 envelopedData for external testing */ pkcs7File = fopen(testVectors[i].outFileName, "wb"); diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index 1349f58d3..b381542ff 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -109,6 +109,12 @@ enum PKCS7_STATE { WC_PKCS7_INFOSET_STAGE2, WC_PKCS7_INFOSET_END, + /* decode enveloped data */ + WC_PKCS7_ENV_2, + WC_PKCS7_ENV_3, + WC_PKCS7_ENV_4, + WC_PKCS7_ENV_5, + /* decode auth enveloped */ WC_PKCS7_AUTHENV_2, WC_PKCS7_AUTHENV_3, From 98efc1e9de61fbe3b265c5d1c9232e239405ad18 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 24 Oct 2018 09:08:37 -0600 Subject: [PATCH 38/56] testing with verify signed stream function --- tests/api.c | 12 +++ wolfcrypt/src/pkcs7.c | 226 ++++++++++++++++++++++++++++-------------- 2 files changed, 166 insertions(+), 72 deletions(-) diff --git a/tests/api.c b/tests/api.c index ce7d13d63..fa9773e79 100644 --- a/tests/api.c +++ b/tests/api.c @@ -15355,8 +15355,14 @@ static void test_wc_PKCS7_EncodeSignedData_ex(void) #endif AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, NULL, outputHeadSz, outputFoot, outputFootSz), BAD_FUNC_ARG); +#ifndef NO_PKCS7_STREAM + /* can pass in 0 buffer length with streaming API */ + AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, + outputHead, 0, outputFoot, outputFootSz), WC_PKCS7_WANT_READ_E); +#else AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, outputHead, 0, outputFoot, outputFootSz), BAD_FUNC_ARG); +#endif AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, outputHead, outputHeadSz, NULL, outputFootSz), BAD_FUNC_ARG); #ifndef NO_PKCS7_STREAM @@ -15481,8 +15487,14 @@ static void test_wc_PKCS7_VerifySignedData(void) /* Test bad args. */ AssertIntEQ(wc_PKCS7_VerifySignedData(NULL, output, outputSz), BAD_FUNC_ARG); AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, NULL, outputSz), BAD_FUNC_ARG); +#ifndef NO_PKCS7_STREAM + /* can pass in 0 buffer length with streaming API */ + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, badOut, + badOutSz), WC_PKCS7_WANT_READ_E); +#else AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, badOut, badOutSz), BAD_FUNC_ARG); +#endif printf(resultFmt, passed); diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 1780398fe..5945ce9fe 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -92,7 +92,7 @@ typedef struct PKCS7State { word32 peakUsed; /* most bytes used for struct at any one time */ word32 peakRead; /* most bytes used by read buffer */ #endif - byte hasAtrib:1; + byte flagOne:1; } PKCS7State; @@ -173,33 +173,40 @@ static void wc_PKCS7_FreeStream(PKCS7* pkcs7) /* pt gets set to the buffer that is holding data in the case that stream struct * is used. * + * Sets idx to be the current offset into "pt" buffer * returns 0 on success */ static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, word32 expected, byte** pt, word32* idx) { - word32 rdSz; + word32 rdSz = pkcs7->stream->idx; - if (inSz >= expected && pkcs7->stream->length == 0) { + /* If the input size minus current index into input buffer is greater than + * the expected size then use the input buffer. If data is already stored + * in stream buffer or if there is not enough input data available then use + * the stream buffer. */ + if (inSz - rdSz >= expected && pkcs7->stream->length == 0) { /* storing input buffer is not needed */ + *pt = in; /* reset in case previously used internal buffer */ + *idx = rdSz; return 0; } /* is there enough stored in buffer already? */ if (pkcs7->stream->length >= expected) { - *idx = 0; + *idx = 0; /* start reading from beginning of stream buffer */ *pt = pkcs7->stream->buffer; return 0; } /* check if all data has been read from input */ - rdSz = pkcs7->stream->idx; if (rdSz >= inSz) { - /* no more input to read */ + /* no more input to read, reset input index and request more data */ pkcs7->stream->idx = 0; return WC_PKCS7_WANT_READ_E; } + /* try to store input data into stream buffer */ if (inSz - rdSz > 0 && pkcs7->stream->length < expected) { int len = min(inSz - rdSz, expected - pkcs7->stream->length); XMEMCPY(pkcs7->stream->buffer + pkcs7->stream->length, in + rdSz, len); @@ -209,6 +216,7 @@ static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, } #ifdef WC_PKCS7_STREAM_DEBUG + /* collects memory usage for debugging */ if (pkcs7->stream->length > pkcs7->stream->peakRead) { pkcs7->stream->peakRead = pkcs7->stream->length; } @@ -218,12 +226,14 @@ static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, pkcs7->stream->nonceSz + pkcs7->stream->tagSz; } #endif + + /* if not enough data was read in then request more */ if (pkcs7->stream->length < expected) { pkcs7->stream->idx = 0; return WC_PKCS7_WANT_READ_E; } - /* read from stored buffer */ + /* adjust pointer to read from stored buffer */ *idx = 0; *pt = pkcs7->stream->buffer; return 0; @@ -237,18 +247,35 @@ static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, * if no flag value is set then the stored max length is returned. * returns length found on success and defSz if no stored data is found */ -static word32 wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, word32 defSz) +static word32 wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, byte* in, + word32 defSz) { /* check there is a buffer to read from */ - if (pkcs7 && pkcs7->stream->length > 0) { + if (pkcs7) { int length = 0, ret; word32 idx = 0; - if (flag == PKCS7_SEQ_PEEK) { - if ((ret = GetSequence(pkcs7->stream->buffer, &idx, - &length, (word32)-1)) < 0) { - return ret; + byte* pt; + + if (flag != PKCS7_DEFAULT_PEEK) { + if (pkcs7->stream->length > 0) { + length = pkcs7->stream->length; + pt = pkcs7->stream->buffer; + } + else { + length = defSz; + pt = in; + } + + if (length < MAX_SEQ_SZ) { + WOLFSSL_MSG("PKCS7 Error not enough data for SEQ peek\n"); + return 0; + } + if (flag == PKCS7_SEQ_PEEK) { + if ((ret = GetSequence(pt, &idx, &length, (word32)-1)) < 0) { + return ret; + } + pkcs7->stream->maxLen = length + idx; } - pkcs7->stream->maxLen = length + idx; } return pkcs7->stream->maxLen; } @@ -291,6 +318,7 @@ static int wc_PKCS7_StreamEndCase(PKCS7* pkcs7, word32* tmpIdx, word32* idx) if (pkcs7->stream->length > 0) { if (pkcs7->stream->length < *idx) { + WOLFSSL_MSG("PKCS7 read too much data from internal buffer"); ret = BUFFER_E; } else { @@ -301,6 +329,7 @@ static int wc_PKCS7_StreamEndCase(PKCS7* pkcs7, word32* tmpIdx, word32* idx) } else { pkcs7->stream->totalRd += *idx - *tmpIdx; + pkcs7->stream->idx = *idx; /* adjust index into input buffer */ *tmpIdx = *idx; } @@ -3146,7 +3175,7 @@ void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag) */ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, word32 hashSz, byte* in, word32 inSz, - byte* pkiMsg2, word32 pkiMsg2Sz) + byte* in2, word32 in2Sz) { word32 idx, outerContentType, hashOID, sigOID, contentTypeSz = 0, totalSz = 0; int length, version, ret; @@ -3169,9 +3198,23 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, word32 pkiMsgSz = inSz; word32 stateIdx = 0; - if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0) + byte* pkiMsg2 = in2; + word32 pkiMsg2Sz = in2Sz; + + if (pkcs7 == NULL) return BAD_FUNC_ARG; +#ifndef NO_PKCS7_STREAM + /* allow for 0 size inputs with stream mode */ + if (pkcs7 == NULL || (pkiMsg == NULL && pkiMsgSz > 0)) + return BAD_FUNC_ARG; + +#else + if (pkiMsg == NULL || pkiMsgSz == 0) + return BAD_FUNC_ARG; + +#endif + if ((hashSz > 0 && hashBuf == NULL) || (pkiMsg2Sz > 0 && pkiMsg2 == NULL)) { return BAD_FUNC_ARG; } @@ -3195,7 +3238,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); #endif /* determine total message size */ @@ -3285,14 +3328,13 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, case WC_PKCS7_VERIFY_STAGE2: #ifndef NO_PKCS7_STREAM - if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + - MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ + ASN_TAG_SZ - + MAX_LENGTH_SZ, - &pkiMsg, &idx)) != 0) { + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, + MAX_SEQ_SZ + MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ + + ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &totalSz, 0, 0); #endif @@ -3404,12 +3446,12 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, case WC_PKCS7_VERIFY_STAGE3: #ifndef NO_PKCS7_STREAM - if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, (int*)&localIdx, &length); if (pkcs7->stream->length > 0) { @@ -3485,10 +3527,16 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkiMsg2 = pkiMsg; pkiMsg2Sz = pkiMsgSz; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->flagOne = 1; + #endif } } else { pkiMsg2 = pkiMsg; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->flagOne = 1; + #endif } /* If getting the content info failed with non degenerate then return the @@ -3519,6 +3567,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } } + if (pkcs7->stream->flagOne) { + stateIdx = idx; /* case where all data was read from in2 */ + } + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { break; } @@ -3529,7 +3581,6 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, else { pkcs7->stream->expected = MAX_SEQ_SZ; } - pkcs7->stream->bufferPt = pkiMsg2; #endif if (ret != 0) { break; @@ -3539,21 +3590,23 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, case WC_PKCS7_VERIFY_STAGE4: #ifndef NO_PKCS7_STREAM - if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + pkiMsg2Sz, + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); - pkiMsg2 = pkcs7->stream->bufferPt; + if (pkcs7->stream->flagOne) { + pkiMsg2 = pkiMsg; + } /* restore content */ content = pkcs7->stream->content; contentSz = pkcs7->stream->contentSz; - /* store certificate */ - if (length > 0) { + /* store certificate if needed */ + if (length > 0 && in2Sz == 0) { pkcs7->stream->tmpCert = (byte*)XMALLOC(length, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (pkcs7->stream->tmpCert == NULL) { @@ -3580,6 +3633,11 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, cert = &pkiMsg2[idx]; certSz += (certIdx - idx); + + // @TODO + //if (certSz > pkiMsg2Sz) { + // error out here ? + //} } #ifdef ASN_BER_TO_DER der = pkcs7->der; @@ -3632,10 +3690,22 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkcs7->contentSz = contentSz; #ifndef NO_PKCS7_STREAM - idx = stateIdx + idx; + /* factor in that recent idx was in cert buffer. If in2 buffer was + * used then don't advance idx. */ + if (pkcs7->stream->flagOne && pkcs7->stream->length == 0) { + idx = stateIdx + idx; + } + else { + stateIdx = idx; /* didn't read any from internal buffer */ + } + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { break; } + if (pkcs7->stream->flagOne && pkcs7->stream->length > 0) { + idx = stateIdx + idx; + } + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); #endif if (ret != 0) { @@ -3651,10 +3721,11 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, &pkiMsg, &idx)) != 0) { return ret; } - - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); - pkiMsg2 = pkcs7->stream->bufferPt; + if (pkcs7->stream->flagOne) { + pkiMsg2 = pkiMsg; + } /* restore content type */ contentType = pkcs7->stream->nonce; @@ -3666,6 +3737,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, return ASN_PARSE_E; /* Get the implicit[1] set of crls */ + if (idx > pkiMsg2Sz) { + return BUFFER_E; + } + if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { idx++; if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) @@ -3680,31 +3755,36 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, return ASN_PARSE_E; #ifndef NO_PKCS7_STREAM + if (!pkcs7->stream->flagOne) { + stateIdx = idx; /* didn't read any from internal buffer */ + } if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { break; } wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); + if (length > 0) { pkcs7->stream->expected = length; } else { pkcs7->stream->expected = 0; } - pkcs7->stream->bufferPt = pkiMsg2; #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE6); FALL_THROUGH; case WC_PKCS7_VERIFY_STAGE6: #ifndef NO_PKCS7_STREAM - if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + pkiMsg2Sz, + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); - pkiMsg2 = pkcs7->stream->bufferPt; + if (pkcs7->stream->flagOne) { + pkiMsg2 = pkiMsg; + } /* restore content */ content = pkcs7->stream->content; @@ -3825,6 +3905,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } } + if (ret < 0) + break; + ret = 0; /* success */ wc_PKCS7_ResetStream(pkcs7); wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); @@ -6696,7 +6779,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) @@ -6731,7 +6814,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, NULL, &sidType, &version); /* @TODO get expected size for next part, does not account for @@ -6856,7 +6939,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif #ifdef WOLFSSL_SMALL_STACK @@ -7376,7 +7459,7 @@ static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif /* get OtherRecipientInfo sequence length */ if (GetLength(pkiMsg, idx, &seqSz, pkiMsgSz) < 0) @@ -7459,7 +7542,7 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif /* remove KeyDerivationAlgorithmIdentifier */ if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) @@ -7664,7 +7747,7 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif /* remove KEKIdentifier */ if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -7779,7 +7862,7 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif WC_PKCS7_KARI* kari; @@ -7999,8 +8082,8 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, savedIdx = *idx; #ifndef NO_PKCS7_STREAM - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); - if (pkiMsgSz != inSz) pkiMsg = pkcs7->stream->buffer; + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + if (pkcs7->stream->length > 0) pkiMsg = pkcs7->stream->buffer; #endif /* when looking for next recipient, use first sequence and version to @@ -8198,7 +8281,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); #endif /* read past ContentInfo, verify type is envelopedData */ if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -8220,7 +8303,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif word32 len = 0; @@ -8259,7 +8342,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif if (ret == 0 && wc_GetContentType(pkiMsg, idx, &contentType, pkiMsgSz) < 0) ret = ASN_PARSE_E; @@ -8297,7 +8380,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif /* remove EnvelopedData and version */ if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -8323,7 +8406,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); version = pkcs7->stream->varOne; #endif @@ -8467,13 +8550,12 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, case WC_PKCS7_DECRYPT_PWRI: case WC_PKCS7_DECRYPT_ORI: #ifndef NO_PKCS7_STREAM - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); decryptedKey = pkcs7->stream->aad; decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; #endif - ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx, decryptedKey, &decryptedKeySz, &recipFound); @@ -8501,7 +8583,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); #endif /* remove EncryptedContentInfo */ @@ -8565,7 +8647,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length); tmpIv = pkcs7->stream->tmpIv; #endif @@ -8624,7 +8706,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, &encryptedContentSz); tmpIv = pkcs7->stream->tmpIv; @@ -9206,7 +9288,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif #ifdef WOLFSSL_SMALL_STACK decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, @@ -9251,7 +9333,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif /* remove EncryptedContentInfo */ @@ -9302,7 +9384,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); #endif if (ret == 0 && GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) { ret = ASN_PARSE_E; @@ -9384,7 +9466,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); encryptedContentSz = pkcs7->stream->expected; #endif @@ -9447,7 +9529,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); length = pkcs7->stream->expected; encodedAttribs = pkcs7->stream->aad; #endif @@ -9482,7 +9564,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); if (pkcs7->stream->aadSz > 0) { encodedAttribSz = pkcs7->stream->aadSz; @@ -9585,7 +9667,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, encodedAttribs = pkcs7->stream->aad; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &encOID, &blockKeySz, &encryptedContentSz); encryptedContent = pkcs7->stream->bufferPt; #endif @@ -9967,7 +10049,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); #endif /* read past ContentInfo, verify type is encrypted-data */ @@ -10001,7 +10083,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif if (ret == 0 && pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) @@ -10032,7 +10114,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif /* get version, check later */ haveAttribs = 0; @@ -10078,7 +10160,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); /* restore saved variables */ expBlockSz = pkcs7->stream->varOne; @@ -10115,7 +10197,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); /* restore saved variables */ expBlockSz = pkcs7->stream->varOne; @@ -10142,7 +10224,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, } if (pkcs7->stream->totalRd + encryptedContentSz < pkiMsgSz) { - pkcs7->stream->hasAtrib = 1; + pkcs7->stream->flagOne = 1; } pkcs7->stream->expected = (pkcs7->stream->maxLen - @@ -10161,7 +10243,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); /* restore saved variables */ expBlockSz = pkcs7->stream->varOne; @@ -10198,7 +10280,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); pkcs7->decodedAttrib = NULL; #ifndef NO_PKCS7_STREAM - if (pkcs7->stream->hasAtrib) + if (pkcs7->stream->flagOne) #else if (idx < pkiMsgSz) #endif From b3506c836ca70407535fe6821f496612c5bf2f85 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 24 Oct 2018 14:34:08 -0600 Subject: [PATCH 39/56] remove content type restriction and fix build with compkey --- wolfcrypt/src/pkcs7.c | 11 ++++++++++- wolfcrypt/test/test.c | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 5945ce9fe..f951eb2d3 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -5754,7 +5754,6 @@ int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb, return idx; } - #ifndef NO_PWDBASED @@ -7511,6 +7510,7 @@ static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } +#ifndef NO_PWDBASED /* decode ASN.1 PasswordRecipientInfo (pwri), return 0 on success, * < 0 on error */ @@ -7718,6 +7718,7 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } +#endif /* NO_PWDBASED */ /* decode ASN.1 KEKRecipientInfo (kekri), return 0 on success, * < 0 on error */ @@ -8062,8 +8063,12 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, break; case WC_PKCS7_DECRYPT_PWRI: + #ifndef NO_PWDBASED ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx, decryptedKey, decryptedKeySz, recipFound); + #else + return NOT_COMPILED_IN; + #endif break; case WC_PKCS7_DECRYPT_ORI: @@ -8174,6 +8179,7 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, /* pwri is IMPLICIT[3] */ } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 3)) { + #ifndef NO_PWDBASED (*idx)++; if (GetLength(pkiMsg, idx, &version, pkiMsgSz) < 0) @@ -8199,6 +8205,9 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, recipFound); if (ret != 0) return ret; + #else + return NOT_COMPILED_IN; + #endif /* ori is IMPLICIT[4] */ } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index cad0d9ed1..b2657bf72 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19263,6 +19263,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, } } else if (testVectors[i].password != NULL) { + #ifndef NO_PWDBASED /* PWRI recipient type */ ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); @@ -19297,6 +19298,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, wc_PKCS7_Free(pkcs7); return -9317; } + #endif /* NO_PWDBASED */ } else if (testVectors[i].isOri == 1) { /* ORI recipient type */ @@ -19880,6 +19882,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, } } else if (testVectors[i].password != NULL) { + #ifndef NO_PWDBASED /* PWRI recipient type */ ret = wc_PKCS7_Init(pkcs7, pkcs7->heap, pkcs7->devId); @@ -19919,6 +19922,7 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, return -9378; } + #endif /* NO_PWDBASED */ } else if (testVectors[i].isOri == 1) { /* ORI recipient type */ From 5a59fdd6fda3d09b8f3422f8f8ebf0859bd6d161 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 24 Oct 2018 17:20:00 -0600 Subject: [PATCH 40/56] scan-build warnings --- wolfcrypt/src/asn.c | 4 +++ wolfcrypt/src/pkcs7.c | 62 +++++++++++++++++++++---------------------- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 3caa915d2..0963b8b57 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -4980,6 +4980,10 @@ int GetAsnTimeString(void* currTime, byte* buf, word32 len) } else if (ts->tm_year >= 100 && ts->tm_year < 150) { year = ts->tm_year - 100; } + else { + WOLFSSL_MSG("unsupported year range"); + return BAD_FUNC_ARG; + } mon = ts->tm_mon + 1; day = ts->tm_mday; hour = ts->tm_hour; diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index f951eb2d3..a1557ed52 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -3414,6 +3414,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, DYNAMIC_TYPE_PKCS7); if (pkcs7->stream->nonce == NULL) { ret = MEMORY_E; + break; } else { pkcs7->stream->nonceSz = contentTypeSz; @@ -3560,6 +3561,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, DYNAMIC_TYPE_PKCS7); if (pkcs7->stream->content == NULL) { ret = MEMORY_E; + break; } else { XMEMCPY(pkcs7->stream->content, content, contentSz); @@ -3595,7 +3597,6 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); if (pkcs7->stream->flagOne) { pkiMsg2 = pkiMsg; @@ -3721,7 +3722,6 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, &pkiMsg, &idx)) != 0) { return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); if (pkcs7->stream->flagOne) { pkiMsg2 = pkiMsg; @@ -3780,7 +3780,6 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); if (pkcs7->stream->flagOne) { pkiMsg2 = pkiMsg; @@ -6746,7 +6745,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { - int length, encryptedKeySz, ret = 0; + int length, encryptedKeySz = 0, ret = 0; int keySz, version, sidType = 0; word32 encOID; word32 keyIdx; @@ -6937,8 +6936,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, pkcs7->stream->expected, &pkiMsg, idx)) != 0) { return ret; } - - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + encryptedKeySz = pkcs7->stream->expected; #endif #ifdef WOLFSSL_SMALL_STACK @@ -7702,12 +7700,12 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, /* mark recipFound, since we only support one RecipientInfo for now */ *recipFound = 1; *idx += length; - ret = 0; /* success */ #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { break; } #endif + ret = 0; /* success */ break; default: @@ -8249,7 +8247,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, word32 inSz, word32* idx, int type) { - int version, length, ret = 0; + int version = 0, length, ret = 0; word32 contentType; byte* pkiMsg = in; word32 pkiMsgSz = inSz; @@ -8374,6 +8372,9 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, if (ret == 0 && GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) ret = ASN_PARSE_E; + if (ret < 0) + break; + #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { break; @@ -8398,6 +8399,9 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, if (ret == 0 && GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) ret = ASN_PARSE_E; + if (ret < 0) + break; + #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { break; @@ -8443,14 +8447,18 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, if (ret == 0 && GetSet(pkiMsg, idx, &length, pkiMsgSz) < 0) ret = ASN_PARSE_E; - if (ret == 0) - ret = length; + if (ret < 0) + break; #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { break; } #endif + + if (ret == 0) + ret = length; + break; default: @@ -8485,9 +8493,9 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, word32 outputSz) { int recipFound = 0; - int ret, length; + int ret, length = 0; word32 idx = 0, tmpIdx = 0; - word32 contentType, encOID; + word32 contentType, encOID = 0; word32 decryptedKeySz; int expBlockSz = 0, blockKeySz = 0; @@ -8510,6 +8518,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, return BAD_FUNC_ARG; #ifndef NO_PKCS7_STREAM + (void)tmpIv; /* help out static analysis */ if (pkcs7->stream == NULL) { if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { return ret; @@ -8559,8 +8568,6 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, case WC_PKCS7_DECRYPT_PWRI: case WC_PKCS7_DECRYPT_ORI: #ifndef NO_PKCS7_STREAM - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, - inSz); decryptedKey = pkcs7->stream->aad; decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; #endif @@ -8715,7 +8722,6 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, &encryptedContentSz); tmpIv = pkcs7->stream->tmpIv; @@ -9234,15 +9240,15 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, int recipFound = 0; int ret, length; word32 idx = 0, tmpIdx = 0; - word32 contentType, encOID; - word32 decryptedKeySz; + word32 contentType, encOID = 0; + word32 decryptedKeySz = 0; byte* pkiMsg = in; word32 pkiMsgSz = inSz; - int expBlockSz, blockKeySz = 0; + int expBlockSz = 0, blockKeySz = 0; byte authTag[AES_BLOCK_SIZE]; byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */ - int nonceSz, authTagSz, macSz; + int nonceSz = 0, authTagSz = 0, macSz = 0; #ifdef WOLFSSL_SMALL_STACK byte* decryptedKey = NULL; @@ -9296,8 +9302,6 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { return ret; } - - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif #ifdef WOLFSSL_SMALL_STACK decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, @@ -9538,7 +9542,6 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); length = pkcs7->stream->expected; encodedAttribs = pkcs7->stream->aad; #endif @@ -9549,7 +9552,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, authAttrib, authAttribSz) < 0) { WOLFSSL_MSG("Error parsing authenticated attributes"); - ret = ASN_PARSE_E; + return ASN_PARSE_E; } idx += length; @@ -9676,7 +9679,6 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, encodedAttribs = pkcs7->stream->aad; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &encOID, &blockKeySz, &encryptedContentSz); encryptedContent = pkcs7->stream->bufferPt; #endif @@ -9703,9 +9705,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, /* free memory, zero out keys */ ForceZero(encryptedContent, encryptedContentSz); XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - if (decryptedKey != NULL) { - ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); - } + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); #ifdef WOLFSSL_SMALL_STACK XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); decryptedKey = NULL; @@ -10027,7 +10027,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, byte tmpIvBuf[MAX_CONTENT_IV_SIZE]; byte *tmpIv = tmpIvBuf; - int encryptedContentSz; + int encryptedContentSz = 0; byte padLen; byte* encryptedContent = NULL; @@ -10043,6 +10043,7 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, return BAD_FUNC_ARG; #ifndef NO_PKCS7_STREAM + (void)tmpIv; /* help out static analysis */ if (pkcs7->stream == NULL) { if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { return ret; @@ -10208,9 +10209,6 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); - /* restore saved variables */ - expBlockSz = pkcs7->stream->varOne; - /* use IV buffer from stream structure */ tmpIv = pkcs7->stream->tmpIv; length = pkcs7->stream->expected; @@ -10225,6 +10223,8 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, pkiMsgSz) <= 0) ret = ASN_PARSE_E; + if (ret < 0) + break; #ifndef NO_PKCS7_STREAM /* next chunk of data should contain encrypted content */ pkcs7->stream->varThree = encryptedContentSz; From 048a7f4c57f6ab8c3c9c8bade9b9519fb455ced7 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 24 Oct 2018 19:16:27 -0600 Subject: [PATCH 41/56] fix for memory leak after resetting stream state --- wolfcrypt/src/pkcs7.c | 271 +++++++++++++++++++++++++----------------- 1 file changed, 164 insertions(+), 107 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index a1557ed52..5c6be8bb5 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -150,9 +150,22 @@ static void wc_PKCS7_ResetStream(PKCS7* pkcs7) XFREE(pkcs7->stream->aad, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(pkcs7->stream->tag, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(pkcs7->stream->nonce, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->aad = NULL; + pkcs7->stream->tag = NULL; + pkcs7->stream->nonce = NULL; - /* reset values */ - XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State)); + /* reset values, note that content and tmpCert are saved */ + pkcs7->stream->maxLen = 0; + pkcs7->stream->length = 0; + pkcs7->stream->idx = 0; + pkcs7->stream->expected = 0; + pkcs7->stream->totalRd = 0; + + pkcs7->stream->multi = 0; + pkcs7->stream->flagOne = 0; + pkcs7->stream->varOne = 0; + pkcs7->stream->varTwo = 0; + pkcs7->stream->varThree = 0; } } @@ -164,8 +177,11 @@ static void wc_PKCS7_FreeStream(PKCS7* pkcs7) XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->content = NULL; + pkcs7->stream->tmpCert = NULL; XFREE(pkcs7->stream, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream = NULL; } } @@ -3235,7 +3251,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_LENGTH_SZ + ASN_TAG_SZ + MAX_OID_SZ + MAX_SEQ_SZ, &pkiMsg, &idx)) != 0) { - return ret; + break; } pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); @@ -3248,10 +3264,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } /* Get the contentInfo sequence */ - if (GetSequence(pkiMsg, &idx, &length, totalSz) < 0) - return ASN_PARSE_E; + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, totalSz) < 0) + ret = ASN_PARSE_E; - if (length == 0 && pkiMsg[idx-1] == 0x80) { + if (ret == 0 && length == 0 && pkiMsg[idx-1] == 0x80) { #ifdef ASN_BER_TO_DER word32 len = 0; @@ -3271,50 +3287,55 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; #else - return BER_INDEF_E; + ret = BER_INDEF_E; #endif } /* Get the contentInfo contentType */ - if (wc_GetContentType(pkiMsg, &idx, &outerContentType, pkiMsgSz) < 0) - return ASN_PARSE_E; + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &outerContentType, + pkiMsgSz) < 0) + ret = ASN_PARSE_E; - if (outerContentType != SIGNED_DATA) { + if (ret == 0 && outerContentType != SIGNED_DATA) { WOLFSSL_MSG("PKCS#7 input not of type SignedData"); - return PKCS7_OID_E; + ret = PKCS7_OID_E; } /* get the ContentInfo content */ - if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) - return ASN_PARSE_E; + if (ret == 0 && pkiMsg[idx++] != + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; - if (GetLength(pkiMsg, &idx, &length, totalSz) < 0) - return ASN_PARSE_E; + if (ret == 0 && GetLength(pkiMsg, &idx, &length, totalSz) < 0) + ret = ASN_PARSE_E; /* Get the signedData sequence */ - if (GetSequence(pkiMsg, &idx, &length, totalSz) < 0) - return ASN_PARSE_E; + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, totalSz) < 0) + ret = ASN_PARSE_E; /* Get the version */ - if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) - return ASN_PARSE_E; + if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) + ret = ASN_PARSE_E; - if (version != 1) { + if (ret == 0 && version != 1) { WOLFSSL_MSG("PKCS#7 signedData needs to be of version 1"); - return ASN_VERSION_E; + ret = ASN_VERSION_E; } /* Get the set of DigestAlgorithmIdentifiers */ - if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) - return ASN_PARSE_E; + if (ret == 0 && GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; /* Skip the set. */ idx += length; degenerate = (length == 0)? 1 : 0; if (pkcs7->noDegenerate == 1 && degenerate == 1) { - return PKCS7_NO_SIGNER_E; + ret = PKCS7_NO_SIGNER_E; } + if (ret != 0) + break; + #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { break; @@ -3331,7 +3352,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, MAX_SEQ_SZ + MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { - return ret; + break; } pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); @@ -3340,14 +3361,14 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, /* Get the inner ContentInfo sequence */ if (GetSequence(pkiMsg, &idx, &length, totalSz) < 0) - return ASN_PARSE_E; + ret = ASN_PARSE_E; /* Get the inner ContentInfo contentType */ - { + if (ret == 0) { word32 tmpIdx = idx; if (GetASNObjectId(pkiMsg, &idx, &length, pkiMsgSz) != 0) - return ASN_PARSE_E; + ret = ASN_PARSE_E; contentType = pkiMsg + tmpIdx; contentTypeSz = length + (idx - tmpIdx); @@ -3355,6 +3376,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, idx += length; } + if (ret != 0) + break; + /* Check for content info, it could be omitted when degenerate */ localIdx = idx; ret = 0; @@ -3449,7 +3473,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { - return ret; + break; } pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); @@ -3461,6 +3485,11 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, multiPart = pkcs7->stream->multi; #endif + /* Break out before content because it can be optional in degenerate + * cases. */ + if (ret != 0) + break; + /* get parts of content */ if (ret == 0 && multiPart) { int i = 0; @@ -3509,12 +3538,12 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, localIdx = 0; if (contentSz != (int)pkcs7->contentSz) { WOLFSSL_MSG("Data signed does not match contentSz provided"); - return BUFFER_E; + ret = BUFFER_E; } } else { if ((word32)length > pkiMsgSz - localIdx) { - return BUFFER_E; + ret = BUFFER_E; } /* Content pointer for calculating hashes later */ @@ -3524,13 +3553,16 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (ret == 0 && multiPart) { content = pkcs7->contentDynamic; } - idx += length; - pkiMsg2 = pkiMsg; - pkiMsg2Sz = pkiMsgSz; - #ifndef NO_PKCS7_STREAM - pkcs7->stream->flagOne = 1; - #endif + if (ret == 0) { + idx += length; + + pkiMsg2 = pkiMsg; + pkiMsg2Sz = pkiMsgSz; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->flagOne = 1; + #endif + } } } else { @@ -3544,15 +3576,21 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, * error case. Otherwise with a degenerate it is ok if the content * info was omitted */ if (!degenerate && ret != 0) { - return ret; + break; + } + else { + ret = 0; /* reset ret state on degenerate case */ } /* Get the implicit[0] set of certificates */ if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { idx++; if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + ret = ASN_PARSE_E; + if (ret != 0) { + break; + } #ifndef NO_PKCS7_STREAM /* save content */ if (content != NULL) { @@ -3584,9 +3622,6 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkcs7->stream->expected = MAX_SEQ_SZ; } #endif - if (ret != 0) { - break; - } wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE4); FALL_THROUGH; @@ -3594,7 +3629,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { - return ret; + break; } wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); @@ -3608,10 +3643,13 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, /* store certificate if needed */ if (length > 0 && in2Sz == 0) { + /* free tmpCert if not NULL */ + XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7); pkcs7->stream->tmpCert = (byte*)XMALLOC(length, pkcs7->heap, DYNAMIC_TYPE_PKCS7); if (pkcs7->stream->tmpCert == NULL) { - return MEMORY_E; + ret = MEMORY_E; + break; } XMEMCPY(pkcs7->stream->tmpCert, pkiMsg2 + idx, length); pkiMsg2 = pkcs7->stream->tmpCert; @@ -3630,7 +3668,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { if (GetLength(pkiMsg2, &certIdx, &certSz, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + ret = ASN_PARSE_E; cert = &pkiMsg2[idx]; certSz += (certIdx - idx); @@ -3645,22 +3683,22 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, #endif contentDynamic = pkcs7->contentDynamic; - { + if (ret == 0) { PKCS7State* stream = pkcs7->stream; /* This will reset PKCS7 structure and then set the * certificate */ ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); - if (ret != 0) - return ret; pkcs7->stream = stream; } pkcs7->contentDynamic = contentDynamic; #ifdef ASN_BER_TO_DER pkcs7->der = der; #endif + if (ret != 0) + break; /* iterate through any additional certificates */ - if (MAX_PKCS7_CERTS > 0) { + if (ret == 0 && MAX_PKCS7_CERTS > 0) { int sz = 0; int i; @@ -3668,13 +3706,18 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkcs7->certSz[0] = certSz; certIdx = idx + certSz; - for (i = 1; i < MAX_PKCS7_CERTS && certIdx + 1 < pkiMsg2Sz - && certIdx + 1 < (word32)length; i++) { + for (i = 1; i < MAX_PKCS7_CERTS && + certIdx + 1 < pkiMsg2Sz && + certIdx + 1 < (word32)length; i++) { localIdx = certIdx; - if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { - if (GetLength(pkiMsg2, &certIdx, &sz, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + if (pkiMsg2[certIdx++] == + (ASN_CONSTRUCTED | ASN_SEQUENCE)) { + if (GetLength(pkiMsg2, &certIdx, &sz, + pkiMsg2Sz) < 0) { + ret = ASN_PARSE_E; + break; + } pkcs7->cert[i] = &pkiMsg2[localIdx]; pkcs7->certSz[i] = sz + (certIdx - localIdx); @@ -3690,6 +3733,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkcs7->content = content; pkcs7->contentSz = contentSz; + if (ret != 0) { + break; + } #ifndef NO_PKCS7_STREAM /* factor in that recent idx was in cert buffer. If in2 buffer was * used then don't advance idx. */ @@ -3707,20 +3753,24 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, idx = stateIdx + idx; } + pkcs7->stream->expected = MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ + + MAX_SET_SZ; + + if (pkcs7->stream->expected > (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length) + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); #endif - if (ret != 0) { - break; - } wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE5); FALL_THROUGH; case WC_PKCS7_VERIFY_STAGE5: #ifndef NO_PKCS7_STREAM - if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_OID_SZ + - ASN_TAG_SZ + MAX_LENGTH_SZ + MAX_SET_SZ, - &pkiMsg, &idx)) != 0) { - return ret; + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + break; } wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); if (pkcs7->stream->flagOne) { @@ -3733,33 +3783,36 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, #endif /* set contentType and size after init of PKCS7 structure */ - if (wc_PKCS7_SetContentType(pkcs7, contentType, contentTypeSz) < 0) - return ASN_PARSE_E; + if (ret == 0 && wc_PKCS7_SetContentType(pkcs7, contentType, + contentTypeSz) < 0) + ret = ASN_PARSE_E; /* Get the implicit[1] set of crls */ - if (idx > pkiMsg2Sz) { - return BUFFER_E; - } + if (ret == 0 && idx > pkiMsg2Sz) + ret = BUFFER_E; - if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + if (ret == 0 && pkiMsg2[idx] == + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { idx++; if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + ret = ASN_PARSE_E; /* Skip the set */ idx += length; } /* Get the set of signerInfos */ - if (GetSet(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + if (ret == 0 && GetSet(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + ret = ASN_PARSE_E; + if (ret != 0) + break; #ifndef NO_PKCS7_STREAM if (!pkcs7->stream->flagOne) { stateIdx = idx; /* didn't read any from internal buffer */ } if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { - break; + break; } wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); @@ -3777,7 +3830,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { - return ret; + break; } wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); @@ -3791,100 +3844,105 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, #endif /* require a signer if degenerate case not allowed */ - if (length == 0 && pkcs7->noDegenerate == 1) - return PKCS7_NO_SIGNER_E; + if (ret == 0 && length == 0 && pkcs7->noDegenerate == 1) + ret = PKCS7_NO_SIGNER_E; - if (degenerate == 0 && length == 0) { + if (ret == 0 && degenerate == 0 && length == 0) { WOLFSSL_MSG("PKCS7 signers expected"); - return PKCS7_NO_SIGNER_E; + ret = PKCS7_NO_SIGNER_E; } - if (length > 0 && degenerate == 0) { + if (ret == 0 && length > 0 && degenerate == 0) { /* Get the sequence of the first signerInfo */ - if (GetSequence(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + if (ret == 0 && GetSequence(pkiMsg2, &idx, &length, + pkiMsg2Sz) < 0) + ret = ASN_PARSE_E; /* Get the version */ - if (GetMyVersion(pkiMsg2, &idx, &version, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + if (ret == 0 && GetMyVersion(pkiMsg2, &idx, &version, + pkiMsg2Sz) < 0) + ret = ASN_PARSE_E; - if (version == 1) { + if (ret == 0 && version == 1) { /* Get the sequence of IssuerAndSerialNumber */ if (GetSequence(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + ret = ASN_PARSE_E; /* Skip it */ idx += length; - } else if (version == 3) { + } else if (ret == 0 && version == 3) { /* Get the sequence of SubjectKeyIdentifier */ if (pkiMsg2[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { - return ASN_PARSE_E; + ret = ASN_PARSE_E; } if (ret == 0 && GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) <= 0) { - return ASN_PARSE_E; + ret = ASN_PARSE_E; } if (ret == 0 && pkiMsg2[idx++] != ASN_OCTET_STRING) - return ASN_PARSE_E; + ret = ASN_PARSE_E; if (ret == 0 && GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + ret = ASN_PARSE_E; /* Skip it */ idx += length; } else { WOLFSSL_MSG("PKCS#7 signerInfo version must be 1 or 3"); - return ASN_VERSION_E; + ret = ASN_VERSION_E; } /* Get the sequence of digestAlgorithm */ - if (GetAlgoId(pkiMsg2, &idx, &hashOID, oidHashType, pkiMsg2Sz) < 0) { - return ASN_PARSE_E; + if (ret == 0 && GetAlgoId(pkiMsg2, &idx, &hashOID, oidHashType, + pkiMsg2Sz) < 0) { + ret = ASN_PARSE_E; } pkcs7->hashOID = (int)hashOID; /* Get the IMPLICIT[0] SET OF signedAttributes */ - if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + if (ret == 0 && pkiMsg2[idx] == + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { idx++; if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + ret = ASN_PARSE_E; /* save pointer and length */ signedAttrib = &pkiMsg2[idx]; signedAttribSz = length; - if (wc_PKCS7_ParseAttribs(pkcs7, signedAttrib, signedAttribSz) <0) { + if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, signedAttrib, + signedAttribSz) < 0) { WOLFSSL_MSG("Error parsing signed attributes"); - return ASN_PARSE_E; + ret = ASN_PARSE_E; } idx += length; } /* Get digestEncryptionAlgorithm */ - if (GetAlgoId(pkiMsg2, &idx, &sigOID, oidSigType, pkiMsg2Sz) < 0) { - return ASN_PARSE_E; + if (ret == 0 && GetAlgoId(pkiMsg2, &idx, &sigOID, oidSigType, + pkiMsg2Sz) < 0) { + ret = ASN_PARSE_E; } /* store public key type based on digestEncryptionAlgorithm */ - ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID); - if (ret <= 0) { + if ((ret = 0) && ((ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID)) + <= 0)) { WOLFSSL_MSG("Failed to set public key OID from signature"); - return ret; } /* Get the signature */ - if (pkiMsg2[idx] == ASN_OCTET_STRING) { + if (ret == 0 && pkiMsg2[idx] == ASN_OCTET_STRING) { idx++; if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) - return ASN_PARSE_E; + ret = ASN_PARSE_E; /* save pointer and length */ sig = &pkiMsg2[idx]; @@ -3896,11 +3954,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkcs7->content = content; pkcs7->contentSz = contentSz; - ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, - signedAttrib, signedAttribSz, - hashBuf, hashSz); - if (ret < 0) { - return ret; + if (ret == 0) { + ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, + signedAttrib, signedAttribSz, + hashBuf, hashSz); } } From 62a2847d754063f48f08eef4a4e4d5fc3330ce4c Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 24 Oct 2018 22:40:26 -0600 Subject: [PATCH 42/56] make internal stream buffer dynamic formating and build without stream api --- tests/api.c | 2 +- wolfcrypt/src/pkcs7.c | 368 ++++++++++++++++++++++++++---------------- 2 files changed, 229 insertions(+), 141 deletions(-) diff --git a/tests/api.c b/tests/api.c index fa9773e79..8cf1c6204 100644 --- a/tests/api.c +++ b/tests/api.c @@ -15370,7 +15370,7 @@ static void test_wc_PKCS7_EncodeSignedData_ex(void) outputHead, outputHeadSz, outputFoot, 0), WC_PKCS7_WANT_READ_E); #else AssertIntEQ(wc_PKCS7_VerifySignedData_ex(pkcs7, hashBuf, hashSz, - outputHead, outputHeadSz, outputFoot, 0), BUFFER_E); + outputHead, outputHeadSz, outputFoot, 0), ASN_PARSE_E); #endif printf(resultFmt, passed); diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 5c6be8bb5..db558b415 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -69,6 +69,7 @@ typedef struct PKCS7State { byte* tag; /* tag data for AEAD algos */ byte* content; byte multi; /* flag for if content is in multiple parts */ + byte* buffer; /* main internal read buffer */ /* stack variables to store for when returning */ word32 varOne; @@ -80,9 +81,9 @@ typedef struct PKCS7State { word32 maxLen; /* sanity cap on maximum amount of data to allow * needed for GetSequence and other calls */ word32 length; /* amount of data stored */ + word32 bufferSz; /* size of internal buffer */ word32 expected; /* next amount of data expected, if needed */ word32 totalRd; /* total amount of bytes read */ - byte buffer[4096]; word32 nonceSz; /* size of nonce stored */ word32 aadSz; /* size of additional AEAD data */ word32 tagSz; /* size of tag for AEAD */ @@ -126,10 +127,10 @@ static void wc_PKCS7_ResetStream(PKCS7* pkcs7) if (pkcs7->stream->length > pkcs7->stream->peakRead) { pkcs7->stream->peakRead = pkcs7->stream->length; } - if (pkcs7->stream->length + pkcs7->stream->aadSz + + if (pkcs7->stream->bufferSz + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + pkcs7->stream->tagSz > pkcs7->stream->peakUsed) { - pkcs7->stream->peakUsed = pkcs7->stream->length + + pkcs7->stream->peakUsed = pkcs7->stream->bufferSz + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + pkcs7->stream->tagSz; } @@ -150,9 +151,11 @@ static void wc_PKCS7_ResetStream(PKCS7* pkcs7) XFREE(pkcs7->stream->aad, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(pkcs7->stream->tag, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(pkcs7->stream->nonce, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - pkcs7->stream->aad = NULL; - pkcs7->stream->tag = NULL; - pkcs7->stream->nonce = NULL; + XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->aad = NULL; + pkcs7->stream->tag = NULL; + pkcs7->stream->nonce = NULL; + pkcs7->stream->buffer = NULL; /* reset values, note that content and tmpCert are saved */ pkcs7->stream->maxLen = 0; @@ -160,6 +163,7 @@ static void wc_PKCS7_ResetStream(PKCS7* pkcs7) pkcs7->stream->idx = 0; pkcs7->stream->expected = 0; pkcs7->stream->totalRd = 0; + pkcs7->stream->bufferSz = 0; pkcs7->stream->multi = 0; pkcs7->stream->flagOne = 0; @@ -186,6 +190,29 @@ static void wc_PKCS7_FreeStream(PKCS7* pkcs7) } +/* used to increase the max size for internal buffer + * returns 0 on success */ +static int wc_PKCS7_GrowStream(PKCS7* pkcs7, word32 newSz) +{ + byte* pt; + + pt = (byte*)XMALLOC(newSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pt == NULL) { + return MEMORY_E; + } + XMEMCPY(pt, pkcs7->stream->buffer, pkcs7->stream->bufferSz); + +#ifdef WC_PKCS7_STREAM_DEBUG + printf("PKCS7 increasing internal stream buffer %d -> %d\n", + pkcs7->stream->bufferSz, newSz); +#endif + pkcs7->stream->bufferSz = newSz; + XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->buffer = pt; + return 0; +} + + /* pt gets set to the buffer that is holding data in the case that stream struct * is used. * @@ -225,6 +252,14 @@ static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, /* try to store input data into stream buffer */ if (inSz - rdSz > 0 && pkcs7->stream->length < expected) { int len = min(inSz - rdSz, expected - pkcs7->stream->length); + + /* check if internal buffer size needs to be increased */ + if (len + pkcs7->stream->length > pkcs7->stream->bufferSz) { + int ret = wc_PKCS7_GrowStream(pkcs7, expected); + if (ret < 0) { + return ret; + } + } XMEMCPY(pkcs7->stream->buffer + pkcs7->stream->length, in + rdSz, len); pkcs7->stream->length += len; pkcs7->stream->idx += len; @@ -236,10 +271,10 @@ static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, if (pkcs7->stream->length > pkcs7->stream->peakRead) { pkcs7->stream->peakRead = pkcs7->stream->length; } - if (pkcs7->stream->length + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + + if (pkcs7->stream->bufferSz + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + pkcs7->stream->tagSz > pkcs7->stream->peakUsed) { - pkcs7->stream->peakUsed = pkcs7->stream->length + pkcs7->stream->aadSz + - pkcs7->stream->nonceSz + pkcs7->stream->tagSz; + pkcs7->stream->peakUsed = pkcs7->stream->bufferSz + + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + pkcs7->stream->tagSz; } #endif @@ -3193,8 +3228,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, word32 hashSz, byte* in, word32 inSz, byte* in2, word32 in2Sz) { - word32 idx, outerContentType, hashOID, sigOID, contentTypeSz = 0, totalSz = 0; - int length, version, ret; + word32 idx, outerContentType, hashOID = 0, sigOID, contentTypeSz = 0, totalSz = 0; + int length, version, ret = 0; byte* content = NULL; byte* contentDynamic = NULL; byte* sig = NULL; @@ -3212,7 +3247,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, byte* pkiMsg = in; word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM word32 stateIdx = 0; +#endif byte* pkiMsg2 = in2; word32 pkiMsg2Sz = in2Sz; @@ -3672,11 +3709,6 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, cert = &pkiMsg2[idx]; certSz += (certIdx - idx); - - // @TODO - //if (certSz > pkiMsg2Sz) { - // error out here ? - //} } #ifdef ASN_BER_TO_DER der = pkcs7->der; @@ -3684,11 +3716,15 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, contentDynamic = pkcs7->contentDynamic; if (ret == 0) { + #ifndef NO_PKCS7_STREAM PKCS7State* stream = pkcs7->stream; + #endif /* This will reset PKCS7 structure and then set the * certificate */ ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + #ifndef NO_PKCS7_STREAM pkcs7->stream = stream; + #endif } pkcs7->contentDynamic = contentDynamic; #ifdef ASN_BER_TO_DER @@ -3965,7 +4001,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, break; ret = 0; /* success */ + #ifndef NO_PKCS7_STREAM wc_PKCS7_ResetStream(pkcs7); + #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); break; @@ -3975,7 +4013,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + #ifndef NO_PKCS7_STREAM wc_PKCS7_ResetStream(pkcs7); + #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); } return ret; @@ -4095,7 +4135,6 @@ static int wc_PKCS7_KeyWrap(byte* cek, word32 cekSz, byte* kek, if (ret <= 0) return ret; - break; #endif /* NO_AES */ @@ -6807,11 +6846,13 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, word32 encOID; word32 keyIdx; byte issuerHash[KEYID_SIZE]; - byte* outKey = NULL; - word32 tmpIdx = *idx; - byte* pkiMsg = in; + byte* outKey = NULL; + byte* pkiMsg = in; word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = *idx; +#endif #ifdef WC_RSA_BLINDING WC_RNG rng; #endif @@ -7488,13 +7529,14 @@ static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* in, word32 inSz, { int ret, seqSz, oriOIDSz; word32 oriValueSz, tmpIdx; - byte* oriValue; byte oriOID[MAX_OID_SZ]; byte* pkiMsg = in; word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM word32 stateIdx = *idx; +#endif if (pkcs7->oriDecryptCb == NULL) { WOLFSSL_MSG("You must register an ORI Decrypt callback"); @@ -7504,16 +7546,16 @@ static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* in, word32 inSz, switch (pkcs7->state) { case WC_PKCS7_DECRYPT_ORI: - //@TODO for now just get full buffer, needs divided up - #ifndef NO_PKCS7_STREAM + /* @TODO for now just get full buffer, needs divided up */ if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + pkcs7->stream->length, &pkiMsg, idx)) != 0) { return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); #endif /* get OtherRecipientInfo sequence length */ if (GetLength(pkiMsg, idx, &seqSz, pkiMsgSz) < 0) @@ -7584,13 +7626,14 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, word32 kdfAlgoId, pwriEncAlgoId, keyEncAlgoId, cekSz; byte* pkiMsg = in; word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM word32 tmpIdx = *idx; +#endif switch (pkcs7->state) { case WC_PKCS7_DECRYPT_PWRI: - //@TODO for now just get full buffer, needs divided up - #ifndef NO_PKCS7_STREAM + /*@TODO for now just get full buffer, needs divided up */ if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + pkcs7->stream->length, &pkiMsg, idx)) != 0) { @@ -7790,7 +7833,9 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, int ret = 0; byte* pkiMsg = in; word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM word32 tmpIdx = *idx; +#endif switch (pkcs7->state) { case WC_PKCS7_DECRYPT_KEKRI: @@ -7905,7 +7950,15 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, byte* pkiMsg = in; word32 pkiMsgSz = inSz; - word32 tmpIdx = *idx; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = (idx)? *idx : 0; +#endif + + if (pkcs7 == NULL || pkcs7->singleCert == NULL || + pkcs7->singleCertSz == 0 || pkiMsg == NULL || + idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL) { + return BAD_FUNC_ARG; + } switch (pkcs7->state) { case WC_PKCS7_DECRYPT_KARI: { @@ -7922,12 +7975,6 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, #endif WC_PKCS7_KARI* kari; - if (pkcs7 == NULL || pkcs7->singleCert == NULL || - pkcs7->singleCertSz == 0 || pkiMsg == NULL || - idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL) { - return BAD_FUNC_ARG; - } - kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_DECODE); if (kari == NULL) return MEMORY_E; @@ -8087,10 +8134,13 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, word32 inSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { - word32 savedIdx, tmpIdx = *idx; + word32 savedIdx; int version, ret = 0, length; byte* pkiMsg = in; word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = *idx; +#endif if (pkcs7 == NULL || pkiMsg == NULL || idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL || @@ -8308,7 +8358,9 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, word32 contentType; byte* pkiMsg = in; word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM word32 tmpIdx = 0; +#endif if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || idx == NULL) return BAD_FUNC_ARG; @@ -8355,6 +8407,8 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, if (ret == 0 && length == 0 && pkiMsg[(*idx)-1] == 0x80) { #ifdef ASN_BER_TO_DER + word32 len; + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_BER); FALL_THROUGH; @@ -8370,7 +8424,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif - word32 len = 0; + len = 0; ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); if (ret != LENGTH_ONLY_E) @@ -8551,9 +8605,12 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, { int recipFound = 0; int ret, length = 0; - word32 idx = 0, tmpIdx = 0; + word32 idx = 0; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = 0; +#endif word32 contentType, encOID = 0; - word32 decryptedKeySz; + word32 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; int expBlockSz = 0, blockKeySz = 0; byte tmpIvBuf[MAX_CONTENT_IV_SIZE]; @@ -8595,7 +8652,6 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, if (ret < 0) { break; } - tmpIdx = idx; decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -8603,6 +8659,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, return MEMORY_E; wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_2); #ifndef NO_PKCS7_STREAM + tmpIdx = idx; pkcs7->stream->aad = decryptedKey; #endif FALL_THROUGH; @@ -8841,8 +8898,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, } #else if (decryptedKey != NULL && ret < 0) { - ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); - } + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); } #endif @@ -9295,8 +9351,11 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, word32 outputSz) { int recipFound = 0; - int ret, length; - word32 idx = 0, tmpIdx = 0; + int ret = 0, length; + word32 idx = 0; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = 0; +#endif word32 contentType, encOID = 0; word32 decryptedKeySz = 0; byte* pkiMsg = in; @@ -9347,24 +9406,26 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, if (ret < 0) break; -#ifndef NO_PKCS7_STREAM + #ifndef NO_PKCS7_STREAM tmpIdx = idx; -#endif + #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_2); FALL_THROUGH; case WC_PKCS7_AUTHENV_2: -#ifndef NO_PKCS7_STREAM + #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { - return ret; + break; } -#endif + #endif #ifdef WOLFSSL_SMALL_STACK decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, DYNAMIC_TYPE_PKCS7); - if (decryptedKey == NULL) - return MEMORY_E; + if (decryptedKey == NULL) { + ret = MEMORY_E; + break; + } #endif FALL_THROUGH; @@ -9382,40 +9443,45 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, decryptedKey, &decryptedKeySz, &recipFound); if (ret != 0) { - return ret; + break; } if (recipFound == 0) { WOLFSSL_MSG("No recipient found in envelopedData that matches input"); - return PKCS7_RECIP_E; + ret = PKCS7_RECIP_E; + break; } -#ifndef NO_PKCS7_STREAM + #ifndef NO_PKCS7_STREAM tmpIdx = idx; -#endif + #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_3); FALL_THROUGH; case WC_PKCS7_AUTHENV_3: -#ifndef NO_PKCS7_STREAM + #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + - MAX_ALGO_SZ + MAX_ALGO_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { - return ret; + MAX_ALGO_SZ + MAX_ALGO_SZ + ASN_TAG_SZ, + &pkiMsg, &idx)) != 0) { + break; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); -#endif + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + #endif /* remove EncryptedContentInfo */ if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { ret = ASN_PARSE_E; } - if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) { + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, + pkiMsgSz) < 0) { ret = ASN_PARSE_E; } - if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, pkiMsgSz) < 0) { + if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, + pkiMsgSz) < 0) { ret = ASN_PARSE_E; } @@ -9437,25 +9503,26 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, if (ret < 0) break; -#ifndef NO_PKCS7_STREAM + #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { break; } wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, 0); -#endif + #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_4); FALL_THROUGH; case WC_PKCS7_AUTHENV_4: -#ifndef NO_PKCS7_STREAM + #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + - MAX_VERSION_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { - return ret; + MAX_VERSION_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ, + &pkiMsg, &idx)) != 0) { + break; } pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); -#endif + #endif if (ret == 0 && GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) { ret = ASN_PARSE_E; } @@ -9476,7 +9543,8 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } if (ret == 0) { - explicitOctet = pkiMsg[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); + explicitOctet = pkiMsg[idx] == + (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); } /* read encryptedContent, cont[0] */ @@ -9486,7 +9554,8 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } idx++; - if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) { ret = ASN_PARSE_E; } @@ -9495,7 +9564,8 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, ret = ASN_PARSE_E; } - if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) <= 0) { + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) { ret = ASN_PARSE_E; } } @@ -9503,7 +9573,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, if (ret < 0) break; -#ifndef NO_PKCS7_STREAM + #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { break; } @@ -9523,22 +9593,24 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } pkcs7->stream->expected = encryptedContentSz; - wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, encryptedContentSz); -#endif + wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, + encryptedContentSz); + #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_5); FALL_THROUGH; case WC_PKCS7_AUTHENV_5: -#ifndef NO_PKCS7_STREAM + #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + - ASN_TAG_SZ + ASN_TAG_SZ + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { - return ret; + ASN_TAG_SZ + ASN_TAG_SZ + pkcs7->stream->expected, + &pkiMsg, &idx)) != 0) { + break; } pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); encryptedContentSz = pkcs7->stream->expected; -#endif + #endif encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -9555,93 +9627,105 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, #endif /* may have IMPLICIT [1] authenticatedAttributes */ - if (ret == 0 && pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + if (ret == 0 && pkiMsg[idx] == + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { encodedAttribIdx = idx; encodedAttribs = pkiMsg + idx; idx++; if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) ret = ASN_PARSE_E; - #ifndef NO_PKCS7_STREAM + #ifndef NO_PKCS7_STREAM pkcs7->stream->expected = length; - #endif + #endif encodedAttribSz = length + (idx - encodedAttribIdx); - if (ret != 0) break; + if (ret != 0) + break; - #ifndef NO_PKCS7_STREAM - if (encodedAttribSz > 0) { - pkcs7->stream->aadSz = encodedAttribSz; - pkcs7->stream->aad = (byte*)XMALLOC(encodedAttribSz, - pkcs7->heap, DYNAMIC_TYPE_PKCS7); - if (pkcs7->stream->aad == NULL) { - ret = MEMORY_E; - break; - } - else { - XMEMCPY(pkcs7->stream->aad, encodedAttribs, - (idx - encodedAttribIdx)); - } + #ifndef NO_PKCS7_STREAM + if (encodedAttribSz > 0) { + pkcs7->stream->aadSz = encodedAttribSz; + pkcs7->stream->aad = (byte*)XMALLOC(encodedAttribSz, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->aad == NULL) { + ret = MEMORY_E; + break; } + else { + XMEMCPY(pkcs7->stream->aad, encodedAttribs, + (idx - encodedAttribIdx)); + } + } - if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { - break; - } - - #endif + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRB); FALL_THROUGH; - - case WC_PKCS7_AUTHENV_ATRB: - #ifndef NO_PKCS7_STREAM - if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, - pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { - return ret; + } + else { + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; } + #endif + goto authenv_atrbend; /* jump over attribute cases */ + } - length = pkcs7->stream->expected; - encodedAttribs = pkcs7->stream->aad; - #endif + case WC_PKCS7_AUTHENV_ATRB: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } - /* save pointer and length */ - authAttrib = &pkiMsg[idx]; - authAttribSz = length; + length = pkcs7->stream->expected; + encodedAttribs = pkcs7->stream->aad; + #endif - if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, authAttrib, authAttribSz) < 0) { - WOLFSSL_MSG("Error parsing authenticated attributes"); - return ASN_PARSE_E; - } + /* save pointer and length */ + authAttrib = &pkiMsg[idx]; + authAttribSz = length; - idx += length; + if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, authAttrib, authAttribSz) < 0) { + WOLFSSL_MSG("Error parsing authenticated attributes"); + ret = ASN_PARSE_E; + break; + } - #ifndef NO_PKCS7_STREAM - if (encodedAttribSz > 0) { - XMEMCPY(pkcs7->stream->aad + (encodedAttribSz - length), authAttrib, authAttribSz); - } + idx += length; + + #ifndef NO_PKCS7_STREAM + if (encodedAttribSz > 0) { + XMEMCPY(pkcs7->stream->aad + (encodedAttribSz - length), + authAttrib, authAttribSz); + } if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { break; } - #endif - wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRBEND); - FALL_THROUGH; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRBEND); + FALL_THROUGH; - case WC_PKCS7_AUTHENV_ATRBEND: +authenv_atrbend: + case WC_PKCS7_AUTHENV_ATRBEND: #ifndef NO_PKCS7_STREAM - if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + - ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { - return ret; - } + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); - - if (pkcs7->stream->aadSz > 0) { - encodedAttribSz = pkcs7->stream->aadSz; - encodedAttribs = pkcs7->stream->aad; - } + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (pkcs7->stream->aadSz > 0) { + encodedAttribSz = pkcs7->stream->aadSz; + encodedAttribs = pkcs7->stream->aad; + } #endif - } /* get authTag OCTET STRING */ if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { @@ -9673,7 +9757,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, if (ret < 0) break; -#ifndef NO_PKCS7_STREAM + #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { break; } @@ -9695,15 +9779,15 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } } -#endif + #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_6); FALL_THROUGH; case WC_PKCS7_AUTHENV_6: -#ifndef NO_PKCS7_STREAM + #ifndef NO_PKCS7_STREAM if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { - return ret; + break; } /* restore all variables needed */ @@ -9738,7 +9822,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, wc_PKCS7_StreamGetVar(pkcs7, &encOID, &blockKeySz, &encryptedContentSz); encryptedContent = pkcs7->stream->bufferPt; -#endif + #endif /* decrypt encryptedContent */ ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, @@ -10077,7 +10161,11 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, byte* output, word32 outputSz) { int ret = 0, version, length, haveAttribs = 0; - word32 idx = 0, tmpIdx = 0; + word32 idx = 0; + +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = 0; +#endif word32 contentType, encOID; int expBlockSz = 0; From 77a1dafed08f232814da2b6c5f7a96099a92bdc8 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 25 Oct 2018 09:21:47 -0600 Subject: [PATCH 43/56] fix for fall through with gcc-7 --- wolfcrypt/src/pkcs7.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index db558b415..1988b546e 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -9663,7 +9663,6 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, } #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRB); - FALL_THROUGH; } else { #ifndef NO_PKCS7_STREAM @@ -9673,6 +9672,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, #endif goto authenv_atrbend; /* jump over attribute cases */ } + FALL_THROUGH; case WC_PKCS7_AUTHENV_ATRB: #ifndef NO_PKCS7_STREAM From 867bcb454554a2ee8c65e5a9bc83ed70e3618292 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Thu, 25 Oct 2018 14:37:44 -0600 Subject: [PATCH 44/56] small stack memory management --- wolfcrypt/src/pkcs7.c | 83 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 8 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 1988b546e..68004353b 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -64,11 +64,11 @@ typedef enum { typedef struct PKCS7State { byte* tmpCert; byte* bufferPt; + byte* key; byte* nonce; /* stored nonce */ byte* aad; /* additional data for AEAD algos */ byte* tag; /* tag data for AEAD algos */ byte* content; - byte multi; /* flag for if content is in multiple parts */ byte* buffer; /* main internal read buffer */ /* stack variables to store for when returning */ @@ -93,6 +93,7 @@ typedef struct PKCS7State { word32 peakUsed; /* most bytes used for struct at any one time */ word32 peakRead; /* most bytes used by read buffer */ #endif + byte multi:1; /* flag for if content is in multiple parts */ byte flagOne:1; } PKCS7State; @@ -152,10 +153,12 @@ static void wc_PKCS7_ResetStream(PKCS7* pkcs7) XFREE(pkcs7->stream->tag, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(pkcs7->stream->nonce, pkcs7->heap, DYNAMIC_TYPE_PKCS7); XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->key, pkcs7->heap, DYNAMIC_TYPE_PKCS7); pkcs7->stream->aad = NULL; pkcs7->stream->tag = NULL; pkcs7->stream->nonce = NULL; pkcs7->stream->buffer = NULL; + pkcs7->stream->key = NULL; /* reset values, note that content and tmpCert are saved */ pkcs7->stream->maxLen = 0; @@ -1829,6 +1832,9 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, esd->hashType = wc_OidGetHash(pkcs7->hashOID); if (wc_HashGetDigestSize(esd->hashType) != (int)hashSz) { WOLFSSL_MSG("hashSz did not match hashOID"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif return BUFFER_E; } @@ -1869,6 +1875,9 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, /* version MUST be 3 */ esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0); } else { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif return SKID_E; } @@ -1881,6 +1890,9 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId, &digEncAlgoType); if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif return ret; } esd->digEncAlgoIdSz = SetAlgoID(digEncAlgoId, esd->digEncAlgoId, @@ -1897,6 +1909,9 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, signingTimeOid, sizeof(signingTimeOid), signingTime, sizeof(signingTime)); if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif return ret; } @@ -1904,6 +1919,9 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, DYNAMIC_TYPE_PKCS7); flatSignedAttribsSz = esd->signedAttribsSz; if (flatSignedAttribs == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif return MEMORY_E; } @@ -1919,6 +1937,9 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, if (ret < 0) { if (pkcs7->signedAttribsSz != 0) XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif return ret; } @@ -1968,6 +1989,9 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, if (total2Sz > *output2Sz) { if (pkcs7->signedAttribsSz != 0) XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif return BUFFER_E; } totalSz -= pkcs7->contentSz; @@ -1976,6 +2000,9 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, if (totalSz > *outputSz) { if (pkcs7->signedAttribsSz != 0) XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif return BUFFER_E; } @@ -2051,6 +2078,9 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, XMEMCPY(output2 + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE); idx += KEYID_SIZE; } else { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif return SKID_E; } XMEMCPY(output2 + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz); @@ -2080,6 +2110,9 @@ static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, *outputSz = idx; } +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif return idx; } @@ -2656,6 +2689,7 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, #ifdef WOLFSSL_SMALL_STACK XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); #endif return ret; } @@ -2698,6 +2732,7 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, #ifdef WOLFSSL_SMALL_STACK XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); #endif return ret; @@ -2767,6 +2802,7 @@ static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, #ifdef WOLFSSL_SMALL_STACK XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); #endif return ret; } @@ -2808,6 +2844,7 @@ static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, #ifdef WOLFSSL_SMALL_STACK XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); #endif return ret; @@ -3965,6 +4002,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (ret == 0 && GetAlgoId(pkiMsg2, &idx, &sigOID, oidSigType, pkiMsg2Sz) < 0) { ret = ASN_PARSE_E; + break; } /* store public key type based on digestEncryptionAlgorithm */ @@ -5010,7 +5048,7 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, - DYNAMIC_TYPE_TPM_BUFFER); + DYNAMIC_TYPE_TMP_BUFFER); decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -5188,7 +5226,8 @@ int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, } #ifdef WOLFSSL_SMALL_STACK - pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_TMP_BUFFER); + pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); if (pubKey == NULL) { FreeDecodedCert(decoded); XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -6439,6 +6478,9 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, encryptedKey, encryptedKeySz, keyWrapOID, AES_ENCRYPTION); if (encryptedKeySz <= 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return encryptedKeySz; } @@ -6460,6 +6502,9 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, timeSz = GetAsnTimeString(tm, genTime, sizeof(genTime)); if (timeSz < 0) { XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif return timeSz; } totalSz += timeSz; @@ -6488,6 +6533,9 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, if (totalSz > MAX_RECIP_SZ) { WOLFSSL_MSG("CMS Recipient output buffer too small"); XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif return BUFFER_E; } @@ -6520,6 +6568,10 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); idx += encryptedKeySz; +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + /* store recipient size */ recip->recipSz = idx; recip->recipType = PKCS7_KEKRI; @@ -6858,9 +6910,9 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, #endif #ifdef WOLFSSL_SMALL_STACK - mp_int* serialNum; - byte* encryptedKey; - RsaKey* privKey; + mp_int* serialNum = NULL; + byte* encryptedKey = NULL; + RsaKey* privKey = NULL; #else mp_int serialNum[1]; byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; @@ -6905,6 +6957,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, case WC_PKCS7_DECRYPT_KTRI_2: #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, &pkiMsg, idx)) != 0) { return ret; @@ -7104,7 +7157,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, wc_FreeRsaKey(privKey); if (keySz <= 0 || outKey == NULL) { - ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ); + ForceZero(encryptedKey, encryptedKeySz); #ifdef WOLFSSL_SMALL_STACK XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -7113,7 +7166,7 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, } else { *decryptedKeySz = keySz; XMEMCPY(decryptedKey, outKey, keySz); - ForceZero(encryptedKey, MAX_ENCRYPTED_KEY_SZ); + ForceZero(encryptedKey, encryptedKeySz); } #ifdef WOLFSSL_SMALL_STACK @@ -9426,6 +9479,9 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, ret = MEMORY_E; break; } + #ifndef NO_PKCS7_STREAM + pkcs7->stream->key = decryptedKey; + #endif #endif FALL_THROUGH; @@ -9438,6 +9494,11 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, case WC_PKCS7_DECRYPT_ORI: decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + #ifdef WOLFSSL_SMALL_STACK + #ifndef NO_PKCS7_STREAM + decryptedKey = pkcs7->stream->key; + #endif + #endif ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx, decryptedKey, &decryptedKeySz, @@ -9822,6 +9883,9 @@ authenv_atrbend: wc_PKCS7_StreamGetVar(pkcs7, &encOID, &blockKeySz, &encryptedContentSz); encryptedContent = pkcs7->stream->bufferPt; + #ifdef WOLFSSL_SMALL_STACK + decryptedKey = pkcs7->stream->key; + #endif #endif /* decrypt encryptedContent */ @@ -9850,6 +9914,9 @@ authenv_atrbend: #ifdef WOLFSSL_SMALL_STACK XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); decryptedKey = NULL; + #ifdef WOLFSSL_SMALL_STACK + pkcs7->stream->key = NULL; + #endif #endif ret = encryptedContentSz; #ifndef NO_PKCS7_STREAM From 004b0d3793aff03e681e127ae01f84ede2fb95a9 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 25 Oct 2018 15:45:50 -0600 Subject: [PATCH 45/56] PKCS7/CMS build fixes when disabling RSA, ECC, or AES-GCM/CCM --- wolfcrypt/src/pkcs7.c | 11 ++++++-- wolfcrypt/test/test.c | 59 ++++++++++++++++--------------------------- 2 files changed, 31 insertions(+), 39 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 68004353b..a9fc26539 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -8168,10 +8168,13 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, } return ret; -#else - (void)pkcs7; + (void)pkiMsg; (void)pkiMsgSz; +#else + (void)in; + (void)inSz; + (void)pkcs7; (void)idx; (void)decryptedKey; (void)decryptedKeySz; @@ -8206,8 +8209,12 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, case WC_PKCS7_DECRYPT_KTRI: case WC_PKCS7_DECRYPT_KTRI_2: case WC_PKCS7_DECRYPT_KTRI_3: + #ifndef NO_RSA ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx, decryptedKey, decryptedKeySz, recipFound); + #else + return NOT_COMPILED_IN; + #endif break; case WC_PKCS7_DECRYPT_KARI: diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index b2657bf72..aa2412455 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -329,7 +329,9 @@ int scrypt_test(void); #endif int pkcs7signed_test(void); int pkcs7enveloped_test(void); - int pkcs7authenveloped_test(void); + #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + int pkcs7authenveloped_test(void); + #endif #endif #if !defined(NO_ASN_TIME) && !defined(NO_RSA) && defined(WOLFSSL_TEST_CERT) int cert_test(void); @@ -974,10 +976,12 @@ initDefaultName(); else printf( "PKCS7enveloped test passed!\n"); - if ( (ret = pkcs7authenveloped_test()) != 0) - return err_sys("PKCS7authenveloped test failed!\n", ret); - else - printf( "PKCS7authenveloped test passed!\n"); + #if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + if ( (ret = pkcs7authenveloped_test()) != 0) + return err_sys("PKCS7authenveloped test failed!\n", ret); + else + printf( "PKCS7authenveloped test passed!\n"); + #endif #endif #ifdef HAVE_VALGRIND @@ -19538,6 +19542,8 @@ int pkcs7enveloped_test(void) } +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + typedef struct { const byte* content; word32 contentSz; @@ -20168,6 +20174,8 @@ int pkcs7authenveloped_test(void) return ret; } +#endif /* HAVE_AESGCM || HAVE_AESCCM */ + #ifndef NO_PKCS7_ENCRYPTED_DATA @@ -21011,13 +21019,6 @@ static int pkcs7signed_run_vectors( if (ret > 0) return 0; -#ifndef HAVE_ECC - (void)eccCert; - (void)eccCertSz; - (void)eccPrivKey; - (void)eccPrivKeySz; -#endif -#ifdef NO_RSA (void)rsaClientCertBuf; (void)rsaClientCertBufSz; (void)rsaClientPrivKeyBuf; @@ -21030,16 +21031,11 @@ static int pkcs7signed_run_vectors( (void)rsaCaCertBufSz; (void)rsaCaPrivKeyBuf; (void)rsaCaPrivKeyBufSz; -#endif + (void)eccClientCertBuf; + (void)eccClientCertBufSz; + (void)eccClientPrivKeyBuf; + (void)eccClientPrivKeyBufSz; - (void)rsaServerCertBuf; - (void)rsaServerCertBufSz; - (void)rsaServerPrivKeyBuf; - (void)rsaServerPrivKeyBufSz; - (void)rsaCaCertBuf; - (void)rsaCaCertBufSz; - (void)rsaCaPrivKeyBuf; - (void)rsaCaPrivKeyBufSz; return ret; } @@ -21570,13 +21566,11 @@ static int pkcs7signed_run_SingleShotVectors( if (ret > 0) return 0; -#ifndef HAVE_ECC - (void)eccCert; - (void)eccCertSz; - (void)eccPrivKey; - (void)eccPrivKeySz; -#endif -#ifdef NO_RSA + (void)eccClientCertBuf; + (void)eccClientCertBufSz; + (void)eccClientPrivKeyBuf; + (void)eccClientPrivKeyBufSz; + (void)rsaClientCertBuf; (void)rsaClientCertBufSz; (void)rsaClientPrivKeyBuf; @@ -21589,16 +21583,7 @@ static int pkcs7signed_run_SingleShotVectors( (void)rsaCaCertBufSz; (void)rsaCaPrivKeyBuf; (void)rsaCaPrivKeyBufSz; -#endif - (void)rsaServerCertBuf; - (void)rsaServerCertBufSz; - (void)rsaServerPrivKeyBuf; - (void)rsaServerPrivKeyBufSz; - (void)rsaCaCertBuf; - (void)rsaCaCertBufSz; - (void)rsaCaPrivKeyBuf; - (void)rsaCaPrivKeyBufSz; return ret; } From 4d9375b862278dd0fa948921545a59133a59460b Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 25 Oct 2018 16:10:12 -0600 Subject: [PATCH 46/56] PKCS7/CMS build fixes when disabling AES --- wolfcrypt/src/pkcs7.c | 43 +++++++++++++++++++++++++++++++++++++++---- wolfcrypt/test/test.c | 9 +++------ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index a9fc26539..b041687f3 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -6427,7 +6427,7 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; #endif - int blockKeySz = 0, ret = 0; + int blockKeySz = 0, ret = 0, direction; word32 idx = 0; word32 totalSz = 0; word32 recipSeqSz = 0, verSz = 0; @@ -6474,9 +6474,15 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; XMEMSET(encryptedKey, 0, encryptedKeySz); + #ifndef NO_AES + direction = AES_ENCRYPTION; + #else + direction = DES_ENCRYPTION; + #endif + encryptedKeySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kek, kekSz, encryptedKey, encryptedKeySz, keyWrapOID, - AES_ENCRYPTION); + direction); if (encryptedKeySz <= 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); @@ -7877,7 +7883,7 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { - int length, keySz, dateLen; + int length, keySz, dateLen, direction; byte* keyId = NULL; const byte* datePtr = NULL; byte dateFormat; @@ -7951,10 +7957,16 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; + #ifndef NO_AES + direction = AES_DECRYPTION; + #else + direction = DES_DECRYPTION; + #endif + /* decrypt CEK with KEK */ keySz = wc_PKCS7_KeyWrap(pkiMsg + *idx, length, pkcs7->privateKey, pkcs7->privateKeySz, decryptedKey, *decryptedKeySz, - keyWrapOID, AES_DECRYPTION); + keyWrapOID, direction); if (keySz <= 0) return keySz; @@ -8970,6 +8982,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) { +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) int ret, idx = 0; int totalSz, encryptedOutSz; @@ -9402,6 +9415,15 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); return idx; + +#else + WOLFSSL_MSG("AuthEnvelopedData requires AES-GCM or AES-CCM to be enabled"); + (void)pkcs7; + (void)output; + (void)outputSz; + + return NOT_COMPILED_IN; +#endif /* HAVE_AESGCM | HAVE_AESCCM */ } @@ -9410,6 +9432,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, word32 inSz, byte* output, word32 outputSz) { +#if defined(HAVE_AESGCM) || defined(HAVE_AESCC) int recipFound = 0; int ret = 0, length; word32 idx = 0; @@ -9949,7 +9972,19 @@ authenv_atrbend: wc_PKCS7_ResetStream(pkcs7); } #endif + return ret; + +#else + WOLFSSL_MSG("AuthEnvelopedData requires AES-GCM or AES-CCM to be enabled"); + (void)pkcs7; + (void)in; + (void)inSz; + (void)output; + (void)outputSz; + + return NOT_COMPILED_IN; +#endif /* HAVE_AESGCM | HAVE_AESCCM */ } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index aa2412455..090612f3a 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19211,10 +19211,12 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #endif #endif +#ifndef NO_AES /* ori (OtherRecipientInfo) recipient types */ {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0, 0, 0, 0, 0, 1, 0, "pkcs7envelopedDataAES128CBC_ORI.der"}, +#endif }; testSz = sizeof(testVectors) / sizeof(pkcs7EnvelopedVector); @@ -19435,20 +19437,15 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, pkcs7 = NULL; } -#if !defined(HAVE_ECC) || defined(NO_AES) (void)eccCert; (void)eccCertSz; (void)eccPrivKey; (void)eccPrivKeySz; - (void)secretKey; - (void)secretKeyId; -#endif -#ifdef NO_RSA (void)rsaCert; (void)rsaCertSz; (void)rsaPrivKey; (void)rsaPrivKeySz; -#endif + return 0; } From 9bef9bad8e702ff1e60fbc6d068961ca3c04d031 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 25 Oct 2018 16:39:56 -0600 Subject: [PATCH 47/56] PKCS7/CMS build fixes when disabling individual AES sizes --- tests/api.c | 24 +++++++++++++++++++++--- wolfcrypt/test/test.c | 2 +- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/tests/api.c b/tests/api.c index 8cf1c6204..d62e18232 100644 --- a/tests/api.c +++ b/tests/api.c @@ -15642,28 +15642,34 @@ static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void) rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz}, #endif /* NO_DES3 */ #ifndef NO_AES + #ifndef NO_AES_128 {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, AES128CBCb, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz}, + #endif + #ifndef NO_AES_192 {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, AES192CBCb, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz}, + #endif + #ifndef NO_AES_256 {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, AES256CBCb, 0, 0, rsaCert, rsaCertSz, rsaPrivKey, rsaPrivKeySz}, + #endif #endif /* NO_AES */ #endif /* NO_RSA */ #if defined(HAVE_ECC) #ifndef NO_AES - #ifndef NO_SHA + #if !defined(NO_SHA) && !defined(NO_AES_128) {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, AES128CBCb, AES128_WRAP, dhSinglePass_stdDH_sha1kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz}, #endif - #ifndef NO_SHA256 + #if !defined(NO_SHA256) && !defined(NO_AES_256) {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha256kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz}, #endif - #ifdef WOLFSSL_SHA512 + #if !defined(WOLFSSL_SHA512) && !defined(NO_AES_256) {(byte*)input, (word32)(sizeof(input)/sizeof(char)), DATA, AES256CBCb, AES256_WRAP, dhSinglePass_stdDH_sha512kdf_scheme, eccCert, eccCertSz, eccPrivKey, eccPrivKeySz}, @@ -15807,21 +15813,27 @@ static void test_wc_PKCS7_EncodeEncryptedData (void) #endif #ifndef NO_AES + #ifndef NO_AES_128 byte aes128Key[] = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 }; + #endif + #ifndef NO_AES_192 byte aes192Key[] = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 }; + #endif + #ifndef NO_AES_256 byte aes256Key[] = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08 }; + #endif #endif const pkcs7EncryptedVector testVectors[] = { @@ -15831,14 +15843,20 @@ static void test_wc_PKCS7_EncodeEncryptedData (void) {data, (word32)sizeof(data), DATA, DESb, desKey, sizeof(desKey)}, #endif /* NO_DES3 */ #ifndef NO_AES + #ifndef NO_AES_128 {data, (word32)sizeof(data), DATA, AES128CBCb, aes128Key, sizeof(aes128Key)}, + #endif + #ifndef NO_AES_192 {data, (word32)sizeof(data), DATA, AES192CBCb, aes192Key, sizeof(aes192Key)}, + #endif + #ifndef NO_AES_256 {data, (word32)sizeof(data), DATA, AES256CBCb, aes256Key, sizeof(aes256Key)}, + #endif #endif /* NO_AES */ }; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 090612f3a..001523075 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -19211,7 +19211,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, #endif #endif -#ifndef NO_AES +#if !defined(NO_AES) && !defined(NO_AES_128) /* ori (OtherRecipientInfo) recipient types */ {data, (word32)sizeof(data), DATA, AES128CBCb, 0, 0, NULL, 0, NULL, 0, NULL, 0, 0, 0, NULL, 0, NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL, 0, From cc324666033f3eced38c9f9b6944810830816d3c Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 25 Oct 2018 17:22:37 -0600 Subject: [PATCH 48/56] build fix for test.c when disabling CMS EncryptedData content type --- wolfcrypt/test/test.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 001523075..c4a8d34a3 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -21062,7 +21062,7 @@ static int pkcs7signed_run_SingleShotVectors( 0x72,0x6c,0x64 }; -#ifdef WOLFSSL_AES_256 +#if defined(WOLFSSL_AES_256) && !defined(NO_PKCS7_ENCRYPTED_DATA) byte aes256Key[] = { 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, @@ -21330,6 +21330,8 @@ static int pkcs7signed_run_SingleShotVectors( return -9557; } + #ifndef NO_PKCS7_ENCRYPTED_DATA + } else if (testVectors[i].encCompFlag == 1) { /* encode Signed Encrypted FirmwarePkgData */ @@ -21348,6 +21350,7 @@ static int pkcs7signed_run_SingleShotVectors( wc_PKCS7_Free(pkcs7); return -9558; } + #endif #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) } else if (testVectors[i].encCompFlag == 2) { @@ -21457,7 +21460,9 @@ static int pkcs7signed_run_SingleShotVectors( return -9567; } - } else if (testVectors[i].encCompFlag == 1) { + } + #ifndef NO_PKCS7_ENCRYPTED_DATA + else if (testVectors[i].encCompFlag == 1) { /* decrypt inner encryptedData */ pkcs7->encryptionKey = testVectors[i].encryptKey; @@ -21479,6 +21484,7 @@ static int pkcs7signed_run_SingleShotVectors( return -9569; } } + #endif #if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) else if (testVectors[i].encCompFlag == 2) { From 448f91b56d6d8b007b9426330c0cf4d112a05659 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Fri, 26 Oct 2018 10:06:54 -0600 Subject: [PATCH 49/56] fixes after more fuzz testing --- wolfcrypt/src/asn.c | 60 ++++++++++++++++++-------- wolfcrypt/src/pkcs7.c | 93 ++++++++++++++++++++++++++++++++--------- wolfssl/wolfcrypt/asn.h | 4 ++ 3 files changed, 119 insertions(+), 38 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 0963b8b57..a327d060a 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -137,6 +137,14 @@ ASN Options: WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) +{ + return GetLength_ex(input, inOutIdx, len, maxIdx, 1); +} + + +/* give option to check length value found against index. 1 to check 0 to not */ +WOLFSSL_LOCAL int GetLength_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check) { int length = 0; word32 idx = *inOutIdx; @@ -166,7 +174,7 @@ WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, else length = b; - if ((idx + length) > maxIdx) { /* for user of length */ + if (check && (idx + length) > maxIdx) { /* for user of length */ WOLFSSL_MSG("GetLength value exceeds buffer length"); return BUFFER_E; } @@ -179,6 +187,29 @@ WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, } +static int GetASNHeader_ex(const byte* input, byte tag, word32* inOutIdx, int* len, + word32 maxIdx, int check) +{ + word32 idx = *inOutIdx; + byte b; + int length; + + if ((idx + 1) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != tag) + return ASN_PARSE_E; + + if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0) + return ASN_PARSE_E; + + *len = length; + *inOutIdx = idx; + return length; +} + + /* Get the DER/BER encoding of an ASN.1 header. * * input Buffer holding DER/BER encoded data. @@ -193,25 +224,10 @@ WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len, word32 maxIdx) { - word32 idx = *inOutIdx; - byte b; - int length; - - if ((idx + 1) > maxIdx) - return BUFFER_E; - - b = input[idx++]; - if (b != tag) - return ASN_PARSE_E; - - if (GetLength(input, &idx, &length, maxIdx) < 0) - return ASN_PARSE_E; - - *len = length; - *inOutIdx = idx; - return length; + return GetASNHeader_ex(input, tag, inOutIdx, len, maxIdx, 1); } + WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) { @@ -220,6 +236,14 @@ WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, } +WOLFSSL_LOCAL int GetSequence_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check) +{ + return GetASNHeader_ex(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx, check); +} + + WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, word32 maxIdx) { diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index b041687f3..8c5130380 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -58,6 +58,8 @@ typedef enum { WC_PKCS7_DECODE } pkcs7Direction; +#define NO_USER_CHECK 0 + #ifndef NO_PKCS7_STREAM #define MAX_PKCS7_STREAM_BUFFER 256 @@ -301,13 +303,13 @@ static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, * if no flag value is set then the stored max length is returned. * returns length found on success and defSz if no stored data is found */ -static word32 wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, byte* in, +static long wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, byte* in, word32 defSz) { /* check there is a buffer to read from */ if (pkcs7) { int length = 0, ret; - word32 idx = 0; + word32 idx = 0, maxIdx; byte* pt; if (flag != PKCS7_DEFAULT_PEEK) { @@ -319,13 +321,15 @@ static word32 wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, byte* in, length = defSz; pt = in; } + maxIdx = (word32)length; if (length < MAX_SEQ_SZ) { WOLFSSL_MSG("PKCS7 Error not enough data for SEQ peek\n"); return 0; } if (flag == PKCS7_SEQ_PEEK) { - if ((ret = GetSequence(pt, &idx, &length, (word32)-1)) < 0) { + if ((ret = GetSequence_ex(pt, &idx, &length, maxIdx, + NO_USER_CHECK)) < 0) { return ret; } pkcs7->stream->maxLen = length + idx; @@ -3328,7 +3332,15 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, break; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + { + long rc; + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + } + pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz; #endif /* determine total message size */ @@ -3358,7 +3370,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkiMsg = pkcs7->der; pkiMsgSz = len; idx = 0; - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) return ASN_PARSE_E; #else ret = BER_INDEF_E; @@ -3429,12 +3442,13 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, break; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, &totalSz, 0, 0); + pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz; #endif /* Get the inner ContentInfo sequence */ - if (GetSequence(pkiMsg, &idx, &length, totalSz) < 0) + if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) ret = ASN_PARSE_E; /* Get the inner ContentInfo contentType */ @@ -3459,7 +3473,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (pkiMsg[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ret = ASN_PARSE_E; - if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) <= 0) + if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz, + NO_USER_CHECK) <= 0) ret = ASN_PARSE_E; @@ -3469,7 +3484,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, localIdx++; /* Get length of all OCTET_STRINGs. */ - if (GetLength(pkiMsg, &localIdx, &contentLen, totalSz) < 0) + if (GetLength_ex(pkiMsg, &localIdx, &contentLen, pkiMsgSz, + NO_USER_CHECK) < 0) ret = ASN_PARSE_E; /* Check whether there is one OCTET_STRING inside. */ @@ -3477,7 +3493,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING) ret = ASN_PARSE_E; - if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) + if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) ret = ASN_PARSE_E; if (ret == 0) { @@ -3493,7 +3510,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if (pkiMsg[localIdx++] != ASN_OCTET_STRING) ret = ASN_PARSE_E; - if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) + if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) ret = ASN_PARSE_E; } @@ -3545,8 +3563,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, case WC_PKCS7_VERIFY_STAGE3: #ifndef NO_PKCS7_STREAM - if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, pkcs7->stream->expected, - &pkiMsg, &idx)) != 0) { + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { break; } @@ -3727,6 +3745,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } XMEMCPY(pkcs7->stream->tmpCert, pkiMsg2 + idx, length); pkiMsg2 = pkcs7->stream->tmpCert; + pkiMsg2Sz = length; idx = 0; } #endif @@ -3740,18 +3759,26 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, word32 certIdx = idx; + if (length < MAX_LENGTH_SZ + ASN_TAG_SZ) + ret = BUFFER_E; + if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { if (GetLength(pkiMsg2, &certIdx, &certSz, pkiMsg2Sz) < 0) ret = ASN_PARSE_E; cert = &pkiMsg2[idx]; certSz += (certIdx - idx); + if (certSz > length) { + ret = BUFFER_E; + break; + } } #ifdef ASN_BER_TO_DER der = pkcs7->der; #endif contentDynamic = pkcs7->contentDynamic; + if (ret == 0) { #ifndef NO_PKCS7_STREAM PKCS7State* stream = pkcs7->stream; @@ -3814,6 +3841,11 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, * used then don't advance idx. */ if (pkcs7->stream->flagOne && pkcs7->stream->length == 0) { idx = stateIdx + idx; + if (idx > inSz) { + /* index is more than input size */ + ret = BUFFER_E; + break; + } } else { stateIdx = idx; /* didn't read any from internal buffer */ @@ -3834,6 +3866,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkcs7->stream->expected = (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + pkcs7->stream->length; + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, 0); wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); #endif wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE5); @@ -4011,6 +4044,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, WOLFSSL_MSG("Failed to set public key OID from signature"); } + if (idx >= pkiMsg2Sz) + ret = BUFFER_E; + /* Get the signature */ if (ret == 0 && pkiMsg2[idx] == ASN_OCTET_STRING) { idx++; @@ -8469,7 +8505,15 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + { + long rc; + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif /* read past ContentInfo, verify type is envelopedData */ if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -8532,7 +8576,7 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz; #endif if (ret == 0 && wc_GetContentType(pkiMsg, idx, &contentType, pkiMsgSz) < 0) ret = ASN_PARSE_E; @@ -8552,7 +8596,8 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ret = ASN_PARSE_E; - if (ret == 0 && GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + if (ret == 0 && GetLength_ex(pkiMsg, idx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) ret = ASN_PARSE_E; if (ret < 0) @@ -8785,7 +8830,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif /* remove EncryptedContentInfo */ @@ -8849,7 +8894,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length); tmpIv = pkcs7->stream->tmpIv; #endif @@ -9612,7 +9657,7 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, break; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); #endif if (ret == 0 && GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) { ret = ASN_PARSE_E; @@ -10313,7 +10358,15 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + { + long rc; + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif /* read past ContentInfo, verify type is encrypted-data */ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 19ee854e6..ad0400ad6 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1017,8 +1017,12 @@ WOLFSSL_LOCAL int GetShortInt(const byte* input, word32* inOutIdx, int* number, WOLFSSL_LOCAL char* GetSigName(int oid); WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, word32 maxIdx); +WOLFSSL_LOCAL int GetLength_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check); WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, word32 maxIdx); +WOLFSSL_LOCAL int GetSequence_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check); WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, word32 maxIdx); WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, From 773a81ef6aaf0acee7d67e14eeb4e8dc941bd86d Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Fri, 26 Oct 2018 10:12:30 -0600 Subject: [PATCH 50/56] CMS fixes for building with NO_ASN_TIME --- wolfcrypt/src/pkcs7.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 8c5130380..6da73e2e3 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -1416,12 +1416,12 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, const byte* signingTimeOid, word32 signingTimeOidSz, byte* signingTime, word32 signingTimeSz) { - int hashSz, timeSz; - time_t tm; - + int hashSz; #ifdef NO_ASN_TIME PKCS7Attrib cannedAttribs[2]; #else + time_t tm; + int timeSz; PKCS7Attrib cannedAttribs[3]; #endif word32 cannedAttribsCount; @@ -1476,6 +1476,12 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, pkcs7->signedAttribs, pkcs7->signedAttribsSz); #endif +#ifdef NO_ASN_TIME + (void)signingTimeOidSz; + (void)signingTime; + (void)signingTimeSz; +#endif + return 0; } @@ -6472,7 +6478,9 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, word32 encryptedKeySz; int timeSz = 0; +#ifndef NO_ASN_TIME time_t* tm = NULL; +#endif if (pkcs7 == NULL || kek == NULL || keyId == NULL) return BAD_FUNC_ARG; @@ -6539,6 +6547,7 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, totalSz += (kekIdOctetStrSz + keyIdSz); /* KEKIdentifier: GeneralizedTime (OPTIONAL) */ +#ifndef NO_ASN_TIME if (timePtr != NULL) { tm = (time_t*)timePtr; timeSz = GetAsnTimeString(tm, genTime, sizeof(genTime)); @@ -6551,6 +6560,7 @@ int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, } totalSz += timeSz; } +#endif /* KEKIdentifier: OtherKeyAttribute SEQ (OPTIONAL) */ if (other != NULL && otherSz > 0) { From afbf09b970d618fe4c6e3e2be4a26765fbeac4bd Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Fri, 26 Oct 2018 11:34:26 -0600 Subject: [PATCH 51/56] fix for building with clang --- wolfcrypt/src/pkcs7.c | 236 ++++++++++++++++++++++++++++++++------ wolfssl/wolfcrypt/pkcs7.h | 4 +- 2 files changed, 204 insertions(+), 36 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 6da73e2e3..255824745 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -63,7 +63,7 @@ typedef enum { #ifndef NO_PKCS7_STREAM #define MAX_PKCS7_STREAM_BUFFER 256 -typedef struct PKCS7State { +struct PKCS7State { byte* tmpCert; byte* bufferPt; byte* key; @@ -97,7 +97,7 @@ typedef struct PKCS7State { #endif byte multi:1; /* flag for if content is in multiple parts */ byte flagOne:1; -} PKCS7State; +}; enum PKCS7_MaxLen { @@ -754,21 +754,21 @@ int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId) /* Certificate structure holding der pointer, size, and pointer to next * Pkcs7Cert struct. Used when creating SignedData types with multiple * certificates. */ -typedef struct Pkcs7Cert { +struct Pkcs7Cert { byte* der; word32 derSz; Pkcs7Cert* next; -} Pkcs7Cert; +}; /* Linked list of ASN.1 encoded RecipientInfos */ -typedef struct Pkcs7EncodedRecip { +struct Pkcs7EncodedRecip { byte recip[MAX_RECIP_SZ]; word32 recipSz; int recipType; int recipVersion; Pkcs7EncodedRecip* next; -} Pkcs7EncodedRecip; +}; /* free all members of Pkcs7Cert linked list */ @@ -3574,7 +3574,15 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, break; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, (int*)&localIdx, &length); if (pkcs7->stream->length > 0) { @@ -6979,7 +6987,15 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) @@ -7015,7 +7031,15 @@ static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } wc_PKCS7_StreamGetVar(pkcs7, NULL, &sidType, &version); /* @TODO get expected size for next part, does not account for @@ -7659,8 +7683,15 @@ static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif /* get OtherRecipientInfo sequence length */ if (GetLength(pkiMsg, idx, &seqSz, pkiMsgSz) < 0) @@ -7745,7 +7776,15 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif /* remove KeyDerivationAlgorithmIdentifier */ if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) @@ -7944,16 +7983,23 @@ static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, switch (pkcs7->state) { case WC_PKCS7_DECRYPT_KEKRI: - //@TODO for now just get full buffer, needs divided up - #ifndef NO_PKCS7_STREAM + /* @TODO for now just get full buffer, needs divided up */ if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + pkcs7->stream->length, &pkiMsg, idx)) != 0) { return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif /* remove KEKIdentifier */ if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -8073,16 +8119,23 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, switch (pkcs7->state) { case WC_PKCS7_DECRYPT_KARI: { - //@TODO for now just get full buffer, needs divided up - #ifndef NO_PKCS7_STREAM + /* @TODO for now just get full buffer, needs divided up */ if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + pkcs7->stream->length, &pkiMsg, idx)) != 0) { return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif WC_PKCS7_KARI* kari; @@ -8310,7 +8363,13 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, savedIdx = *idx; #ifndef NO_PKCS7_STREAM - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + if (rc < 0) { + return (int)rc; + } + pkiMsgSz = (word32)rc; + } if (pkcs7->stream->length > 0) pkiMsg = pkcs7->stream->buffer; #endif @@ -8547,7 +8606,15 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif len = 0; @@ -8628,7 +8695,15 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif /* remove EnvelopedData and version */ if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) @@ -8657,7 +8732,15 @@ static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } version = pkcs7->stream->varOne; #endif @@ -8840,7 +8923,15 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif /* remove EncryptedContentInfo */ @@ -8904,7 +8995,15 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length); tmpIv = pkcs7->stream->tmpIv; #endif @@ -9218,7 +9317,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, /* otherwise, try to set from custom content type */ } else if (ret <= 0) { - if (pkcs7->contentType == NULL || pkcs7->contentTypeSz == 0) { + if (pkcs7->contentTypeSz == 0) { WOLFSSL_MSG("CMS pkcs7->contentType must be set if " "contentOID is not"); return BAD_FUNC_ARG; @@ -9612,8 +9711,15 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, break; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif /* remove EncryptedContentInfo */ @@ -9667,7 +9773,15 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, break; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif if (ret == 0 && GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) { ret = ASN_PARSE_E; @@ -9754,7 +9868,15 @@ WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, break; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } encryptedContentSz = pkcs7->stream->expected; #endif @@ -9864,8 +9986,15 @@ authenv_atrbend: return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } if (pkcs7->stream->aadSz > 0) { encodedAttribSz = pkcs7->stream->aadSz; encodedAttribs = pkcs7->stream->aad; @@ -10410,7 +10539,15 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif if (ret == 0 && pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) @@ -10441,7 +10578,15 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } #endif /* get version, check later */ haveAttribs = 0; @@ -10487,7 +10632,15 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } /* restore saved variables */ expBlockSz = pkcs7->stream->varOne; @@ -10524,7 +10677,15 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } /* use IV buffer from stream structure */ tmpIv = pkcs7->stream->tmpIv; @@ -10563,13 +10724,20 @@ int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, case WC_PKCS7_STAGE6: #ifndef NO_PKCS7_STREAM - //@TODO if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { return ret; } - pkiMsgSz = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + { + long rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + } /* restore saved variables */ expBlockSz = pkcs7->stream->varOne; diff --git a/wolfssl/wolfcrypt/pkcs7.h b/wolfssl/wolfcrypt/pkcs7.h index b381542ff..1636aafa2 100644 --- a/wolfssl/wolfcrypt/pkcs7.h +++ b/wolfssl/wolfcrypt/pkcs7.h @@ -203,7 +203,7 @@ typedef int (*CallbackOriEncrypt)(PKCS7* pkcs7, byte* cek, word32 cekSz, /* Public Structure Warning: * Existing members must not be changed to maintain backwards compatibility! */ -typedef struct PKCS7 { +struct PKCS7 { WC_RNG* rng; PKCS7Attrib* signedAttribs; byte* content; /* inner content, not owner */ @@ -283,7 +283,7 @@ typedef struct PKCS7 { word32 state; /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ -} PKCS7; +}; WOLFSSL_API PKCS7* wc_PKCS7_New(void* heap, int devId); From a2b2ce124e7056cccf8ca94b09178335ce6f8548 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Fri, 26 Oct 2018 13:53:41 -0600 Subject: [PATCH 52/56] add a check to help out static analysis tool --- wolfcrypt/src/pkcs7.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 255824745..c159d63ee 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -9006,6 +9006,11 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, } wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length); tmpIv = pkcs7->stream->tmpIv; + if (tmpIv == NULL) { + /* check added to help out static analysis tool */ + ret = MEMORY_E; + break; + } #endif XMEMCPY(tmpIv, &pkiMsg[idx], length); From 9fa4f754abbebdb43fa9c1b500d98a5685a0811c Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Mon, 29 Oct 2018 17:09:00 -0600 Subject: [PATCH 53/56] fix PKCS7/CMS conditional build errors --- wolfcrypt/src/pkcs7.c | 103 ++++++++++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 24 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index c159d63ee..50ee01444 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -502,7 +502,7 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) 0x01, 0x09, 0x10, 0x01, 0x09 }; #endif -#ifndef NO_PWDBASED +#if !defined(NO_PWDBASED) && !defined(NO_SHA) const byte pwriKek[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x03, 0x09 }; const byte pbkdf2[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, @@ -567,7 +567,7 @@ static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) typeName = firmwarePkgData; break; -#ifndef NO_PWDBASED +#if !defined(NO_PWDBASED) && !defined(NO_SHA) case PWRI_KEK_WRAP: typeSz = sizeof(pwriKek); typeName = pwriKek; @@ -5938,7 +5938,7 @@ int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb, return idx; } -#ifndef NO_PWDBASED +#if !defined(NO_PWDBASED) && !defined(NO_SHA) static int wc_PKCS7_GenerateKEK_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, @@ -7743,7 +7743,7 @@ static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } -#ifndef NO_PWDBASED +#if !defined(NO_PWDBASED) && !defined(NO_SHA) /* decode ASN.1 PasswordRecipientInfo (pwri), return 0 on success, * < 0 on error */ @@ -7960,7 +7960,7 @@ static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, return ret; } -#endif /* NO_PWDBASED */ +#endif /* NO_PWDBASED | NO_SHA */ /* decode ASN.1 KEKRecipientInfo (kekri), return 0 on success, * < 0 on error */ @@ -8339,7 +8339,7 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, break; case WC_PKCS7_DECRYPT_PWRI: - #ifndef NO_PWDBASED + #if !defined(NO_PWDBASED) && !defined(NO_SHA) ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx, decryptedKey, decryptedKeySz, recipFound); #else @@ -8461,7 +8461,7 @@ static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, /* pwri is IMPLICIT[3] */ } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 3)) { - #ifndef NO_PWDBASED + #if !defined(NO_PWDBASED) && !defined(NO_SHA) (*idx)++; if (GetLength(pkiMsg, idx, &version, pkiMsgSz) < 0) @@ -9174,7 +9174,7 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, byte authTag[AES_BLOCK_SIZE]; byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */ byte macInt[MAX_VERSION_SZ]; - word32 nonceSz, macIntSz; + word32 nonceSz = 0, macIntSz = 0; /* authAttribs */ byte* flatAuthAttribs = NULL; @@ -9209,14 +9209,38 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, if (output == NULL || outputSz == 0) return BAD_FUNC_ARG; - if (pkcs7->encryptOID != AES128GCMb && - pkcs7->encryptOID != AES192GCMb && - pkcs7->encryptOID != AES256GCMb && - pkcs7->encryptOID != AES128CCMb && - pkcs7->encryptOID != AES192CCMb && - pkcs7->encryptOID != AES256CCMb) { - WOLFSSL_MSG("CMS AuthEnvelopedData must use AES-GCM or AES-CCM"); - return BAD_FUNC_ARG; + switch (pkcs7->encryptOID) { +#ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + break; + #endif +#endif +#ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + break; + #endif +#endif + default: + WOLFSSL_MSG("CMS AuthEnvelopedData must use AES-GCM or AES-CCM"); + return BAD_FUNC_ARG; } blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); @@ -9285,14 +9309,45 @@ int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, recipSetSz = SetSet(recipSz, recipSet); /* generate random nonce and IV for encryption */ - if (pkcs7->encryptOID == AES128GCMb || - pkcs7->encryptOID == AES192GCMb || - pkcs7->encryptOID == AES256GCMb) { - /* GCM nonce is GCM_NONCE_MID_SZ (12) */ - nonceSz = GCM_NONCE_MID_SZ; - } else { - /* CCM nonce is CCM_NONCE_MIN_SZ (7) */ - nonceSz = CCM_NONCE_MIN_SZ; + switch (pkcs7->encryptOID) { +#ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + FALL_THROUGH; + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + FALL_THROUGH; + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + /* GCM nonce is GCM_NONCE_MID_SZ (12) */ + nonceSz = GCM_NONCE_MID_SZ; + break; + #endif +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + FALL_THROUGH; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + FALL_THROUGH; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + /* CCM nonce is CCM_NONCE_MIN_SZ (7) */ + nonceSz = CCM_NONCE_MIN_SZ; + break; + #endif +#endif /* HAVE_AESCCM */ } ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); From 820ee0439a856b68f0bbf9b485b5c13a124c4734 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Mon, 5 Nov 2018 15:42:31 -0700 Subject: [PATCH 54/56] handle degenerate case after rebase --- wolfcrypt/src/pkcs7.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 50ee01444..1b6f32f76 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -3356,7 +3356,8 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } /* Get the contentInfo sequence */ - if (ret == 0 && GetSequence(pkiMsg, &idx, &length, totalSz) < 0) + if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, totalSz, + NO_USER_CHECK) < 0) ret = ASN_PARSE_E; if (ret == 0 && length == 0 && pkiMsg[idx-1] == 0x80) { @@ -3389,6 +3390,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkiMsgSz) < 0) ret = ASN_PARSE_E; + if (ret == 0 && outerContentType != SIGNED_DATA) { WOLFSSL_MSG("PKCS#7 input not of type SignedData"); ret = PKCS7_OID_E; @@ -3399,11 +3401,13 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ret = ASN_PARSE_E; - if (ret == 0 && GetLength(pkiMsg, &idx, &length, totalSz) < 0) + if (ret == 0 && GetLength_ex(pkiMsg, &idx, &length, totalSz, + NO_USER_CHECK) < 0) ret = ASN_PARSE_E; /* Get the signedData sequence */ - if (ret == 0 && GetSequence(pkiMsg, &idx, &length, totalSz) < 0) + if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, totalSz, + NO_USER_CHECK) < 0) ret = ASN_PARSE_E; /* Get the version */ @@ -3433,7 +3437,9 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { break; } - pkcs7->stream->maxLen = totalSz; + if (pkiMsg2 && pkiMsg2Sz > 0) { + pkcs7->stream->maxLen += pkiMsg2Sz + pkcs7->contentSz; + } wc_PKCS7_StreamStoreVar(pkcs7, totalSz, 0, 0); #endif @@ -3529,6 +3535,13 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } idx = localIdx; } + else { + if (!degenerate && ret != 0) + break; + length = 0; /* no content to read */ + pkiMsg2 = pkiMsg; + pkiMsg2Sz = pkiMsgSz; + } #ifndef NO_PKCS7_STREAM /* save contentType */ @@ -3543,11 +3556,6 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, XMEMCPY(pkcs7->stream->nonce, contentType, contentTypeSz); } - if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { - break; - } - wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, localIdx, length); - /* content expected? */ if ((ret == 0 && length > 0) && !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0)) { @@ -3557,6 +3565,11 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, pkcs7->stream->expected = 0; } + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, localIdx, length); + /* content length is in multiple parts */ if (multiPart) { pkcs7->stream->expected = contentLen; @@ -3713,7 +3726,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } } - if (pkcs7->stream->flagOne) { + if (content != NULL && pkcs7->stream->flagOne) { stateIdx = idx; /* case where all data was read from in2 */ } From 27db083733c252206d09222e46532a5822422a89 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 6 Nov 2018 09:36:31 -0700 Subject: [PATCH 55/56] make degenerate test structure dynamic to set the uninitialized dynamic flag --- tests/api.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/tests/api.c b/tests/api.c index d62e18232..e670ae884 100644 --- a/tests/api.c +++ b/tests/api.c @@ -15960,7 +15960,7 @@ static void test_wc_PKCS7_EncodeEncryptedData (void) static void test_wc_PKCS7_Degenerate(void) { #if defined(HAVE_PKCS7) && !defined(NO_FILESYSTEM) - PKCS7 pkcs7; + PKCS7* pkcs7; char fName[] = "./certs/test-degenerate.p7b"; XFILE f; byte der[4096]; @@ -15975,17 +15975,19 @@ static void test_wc_PKCS7_Degenerate(void) XFCLOSE(f); /* test degenerate success */ - AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, INVALID_DEVID), 0); - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, NULL, 0), 0); - AssertIntEQ(wc_PKCS7_VerifySignedData(&pkcs7, der, derSz), 0); - wc_PKCS7_Free(&pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, der, derSz), 0); + wc_PKCS7_Free(pkcs7); /* test with turning off degenerate cases */ - AssertIntEQ(wc_PKCS7_Init(&pkcs7, HEAP_HINT, INVALID_DEVID), 0); - AssertIntEQ(wc_PKCS7_InitWithCert(&pkcs7, NULL, 0), 0); - wc_PKCS7_AllowDegenerate(&pkcs7, 0); /* override allowing degenerate case */ - AssertIntEQ(wc_PKCS7_VerifySignedData(&pkcs7, der, derSz), PKCS7_NO_SIGNER_E); - wc_PKCS7_Free(&pkcs7); + AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId)); + AssertIntEQ(wc_PKCS7_Init(pkcs7, HEAP_HINT, INVALID_DEVID), 0); + AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, NULL, 0), 0); + wc_PKCS7_AllowDegenerate(pkcs7, 0); /* override allowing degenerate case */ + AssertIntEQ(wc_PKCS7_VerifySignedData(pkcs7, der, derSz), PKCS7_NO_SIGNER_E); + wc_PKCS7_Free(pkcs7); printf(resultFmt, passed); #endif From 100bf767480a34e505c8926f161a6b5cefc88137 Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Tue, 6 Nov 2018 14:00:10 -0700 Subject: [PATCH 56/56] sanity check on length befor checking ASN.1 tag --- wolfcrypt/src/pkcs7.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index 1b6f32f76..8ecf1d6b4 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -3559,10 +3559,10 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, /* content expected? */ if ((ret == 0 && length > 0) && !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0)) { - pkcs7->stream->expected = length; + pkcs7->stream->expected = length + ASN_TAG_SZ; } else { - pkcs7->stream->expected = 0; + pkcs7->stream->expected = ASN_TAG_SZ; } if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { @@ -3572,7 +3572,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, /* content length is in multiple parts */ if (multiPart) { - pkcs7->stream->expected = contentLen; + pkcs7->stream->expected = contentLen + ASN_TAG_SZ; } pkcs7->stream->multi = multiPart; @@ -3686,6 +3686,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } else { pkiMsg2 = pkiMsg; + pkiMsg2Sz = pkiMsgSz; #ifndef NO_PKCS7_STREAM pkcs7->stream->flagOne = 1; #endif @@ -3702,14 +3703,18 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, } /* Get the implicit[0] set of certificates */ - if (pkiMsg2[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + if (ret == 0 && idx >= pkiMsg2Sz) + ret = BUFFER_E; + + if (ret == 0 && pkiMsg2[idx] == + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { idx++; if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) ret = ASN_PARSE_E; - if (ret != 0) { - break; - } + if (ret != 0) { + break; + } #ifndef NO_PKCS7_STREAM /* save content */ if (content != NULL) { @@ -3921,7 +3926,7 @@ static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, ret = ASN_PARSE_E; /* Get the implicit[1] set of crls */ - if (ret == 0 && idx > pkiMsg2Sz) + if (ret == 0 && idx >= pkiMsg2Sz) ret = BUFFER_E; if (ret == 0 && pkiMsg2[idx] ==