diff --git a/.gitignore b/.gitignore index fd5def3b6..50703a8aa 100644 --- a/.gitignore +++ b/.gitignore @@ -91,7 +91,18 @@ ecc-key.pem certreq.der certreq.pem pkcs7cert.der -pkcs7signedData.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 pkcs7envelopedDataAES128CBC.der pkcs7envelopedDataAES192CBC.der diff --git a/Makefile.am b/Makefile.am index 1f042dc3d..c81d7eca0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,7 +54,18 @@ CLEANFILES+= cert.der \ pkcs7envelopedDataAES128CBC.der \ pkcs7envelopedDataAES192CBC.der \ pkcs7envelopedDataAES256CBC.der \ - pkcs7signedData.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 exampledir = $(docdir)/example dist_example_DATA= diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index b65cfdb10..fb4aab9ea 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -31,6 +31,7 @@ #include #include #include +#include #ifndef NO_RSA #include #endif @@ -346,9 +347,10 @@ typedef struct EncodedAttrib { typedef struct ESD { - Sha sha; - byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ - byte contentAttribsDigest[SHA_DIGEST_SIZE]; + wc_HashAlg hash; + enum wc_HashType hashType; + byte contentDigest[WC_MAX_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ + byte contentAttribsDigest[WC_MAX_DIGEST_SIZE]; byte encContentDigest[512]; byte outerSeq[MAX_SEQ_SZ]; @@ -434,6 +436,443 @@ static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz) } +#ifndef NO_RSA + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +{ + int ret; + word32 idx; +#ifdef WOLFSSL_SMALL_STACK + RsaKey* privKey; +#else + RsaKey stack_privKey; + RsaKey* privKey = &stack_privKey; +#endif + + if (pkcs7 == NULL || pkcs7->privateKey == NULL || pkcs7->rng == NULL || + in == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_InitRsaKey(privKey, pkcs7->heap); + + if (ret == 0) { + idx = 0; + ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + + if (ret == 0) { + ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest, + sizeof(esd->encContentDigest), + privKey, pkcs7->rng); + } + + wc_FreeRsaKey(privKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* NO_RSA */ + + +#ifdef HAVE_ECC + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +{ + int ret; + word32 outSz, idx; +#ifdef WOLFSSL_SMALL_STACK + ecc_key* privKey; +#else + ecc_key stack_privKey; + ecc_key* privKey = &stack_privKey; +#endif + + if (pkcs7 == NULL || pkcs7->privateKey == NULL || pkcs7->rng == NULL || + in == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_ecc_init_ex(privKey, pkcs7->heap, INVALID_DEVID); + + if (ret == 0) { + idx = 0; + ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + + if (ret == 0) { + outSz = sizeof(esd->encContentDigest); + ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest, + &outSz, pkcs7->rng, privKey); + if (ret == 0) + ret = (int)outSz; + } + + wc_ecc_free(privKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_ECC */ + + +/* builds up SignedData signed attributes, including default ones. + * + * pkcs7 - pointer to initialized PKCS7 structure + * esd - pointer to initialized ESD structure, used for output + * + * return 0 on success, negative on error */ +static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd) +{ + int hashSz; + + byte contentTypeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, + 0x09, 0x03 }; + byte contentType[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x07, 0x01 }; + byte messageDigestOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x04 }; + + PKCS7Attrib cannedAttribs[2]; + word32 cannedAttribsCount; + + if (pkcs7 == NULL || esd == NULL) + return BAD_FUNC_ARG; + + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) + return hashSz; + + cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); + + cannedAttribs[0].oid = contentTypeOid; + cannedAttribs[0].oidSz = sizeof(contentTypeOid); + cannedAttribs[0].value = contentType; + cannedAttribs[0].valueSz = sizeof(contentType); + cannedAttribs[1].oid = messageDigestOid; + cannedAttribs[1].oidSz = sizeof(messageDigestOid); + cannedAttribs[1].value = esd->contentDigest; + cannedAttribs[1].valueSz = hashSz + 2; /* ASN.1 heading */ + + esd->signedAttribsCount += cannedAttribsCount; + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2, + cannedAttribs, cannedAttribsCount); + + esd->signedAttribsCount += pkcs7->signedAttribsSz; + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, + pkcs7->signedAttribs, pkcs7->signedAttribsSz); + + return 0; +} + + +/* gets correct encryption algo ID for SignedData, either RSAk or + * CTC_wECDSA, from pkcs7->publicKeyOID. + * + * pkcs7 - pointer to PKCS7 structure + * digEncAlgoId - [OUT] output int to store correct algo ID in + * digEncAlgoType - [OUT] output for algo ID type + * + * return 0 on success, negative on error */ +static int wc_PKCS7_SignedDataGetEncAlgoId(PKCS7* pkcs7, int* digEncAlgoId, + int* digEncAlgoType) +{ + int algoId = 0; + int algoType = 0; + + if (pkcs7 == NULL || digEncAlgoId == NULL || digEncAlgoType == NULL) + return BAD_FUNC_ARG; + + if (pkcs7->publicKeyOID == RSAk) { + + algoId = pkcs7->encryptOID; + algoType = oidKeyType; + + } else if (pkcs7->publicKeyOID == ECDSAk) { + + algoType = oidSigType; + + switch (pkcs7->hashOID) { + case SHAh: + algoId = CTC_SHAwECDSA; + break; + + case SHA224h: + algoId = CTC_SHA224wECDSA; + break; + + case SHA256h: + algoId = CTC_SHA256wECDSA; + break; + + case SHA384h: + algoId = CTC_SHA384wECDSA; + break; + + case SHA512h: + algoId = CTC_SHA512wECDSA; + break; + } + } + + if (algoId == 0) { + WOLFSSL_MSG("Invalid signature algorithm type"); + return BAD_FUNC_ARG; + } + + *digEncAlgoId = algoId; + *digEncAlgoType = algoType; + + return 0; +} + + +/* build SignedData DigestInfo for use with PKCS#7/RSA + * + * pkcs7 - pointer to initialized PKCS7 struct + * flatSignedAttribs - flattened, signed attributes + * flatSignedAttrbsSz - size of flatSignedAttribs, octets + * esd - pointer to initialized ESD struct + * digestInfo - [OUT] output array for DigestInfo + * digestInfoSz - [IN/OUT] - input size of array, size of digestInfo + * + * return 0 on success, negative on error */ +static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs, + word32 flatSignedAttribsSz, ESD* esd, + byte* digestInfo, word32* digestInfoSz) +{ + int ret, hashSz, digIdx = 0; + byte digestInfoSeq[MAX_SEQ_SZ]; + byte digestStr[MAX_OCTET_STR_SZ]; + byte attribSet[MAX_SET_SZ]; + byte algoId[MAX_ALGO_SZ]; + word32 digestInfoSeqSz, digestStrSz, algoIdSz; + word32 attribSetSz; + + if (pkcs7 == NULL || esd == NULL || digestInfo == NULL || + digestInfoSz == NULL) { + return BAD_FUNC_ARG; + } + + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) + return hashSz; + + if (pkcs7->signedAttribsSz != 0) { + + if (flatSignedAttribs == NULL) + return BAD_FUNC_ARG; + + attribSetSz = SetSet(flatSignedAttribsSz, attribSet); + + ret = wc_HashInit(&esd->hash, esd->hashType); + if (ret < 0) + return ret; + + ret = wc_HashUpdate(&esd->hash, esd->hashType, + attribSet, attribSetSz); + if (ret < 0) + return ret; + + ret = wc_HashUpdate(&esd->hash, esd->hashType, + flatSignedAttribs, flatSignedAttribsSz); + if (ret < 0) + return ret; + + ret = wc_HashFinal(&esd->hash, esd->hashType, + esd->contentAttribsDigest); + if (ret < 0) + return ret; + + } else { + /* when no attrs, digest is contentDigest without tag and length */ + XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, hashSz); + } + + /* set algoID, with NULL attributes */ + algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); + + digestStrSz = SetOctetString(hashSz, digestStr); + digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, + digestInfoSeq); + + if (*digestInfoSz < (digestInfoSeqSz + algoIdSz + digestStrSz + hashSz)) { + return BUFFER_E; + } + + XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); + digIdx += digestInfoSeqSz; + XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); + digIdx += algoIdSz; + XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); + digIdx += digestStrSz; + XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz); + digIdx += hashSz; + + *digestInfoSz = digIdx; + + return 0; +} + + +/* build SignedData signature over DigestInfo or content digest + * + * pkcs7 - pointer to initizlied PKCS7 struct + * flatSignedAttribs - flattened, signed attributes + * flatSignedAttribsSz - size of flatSignedAttribs, octets + * esd - pointer to initialized ESD struct + * + * returns length of signature on success, negative on error */ +static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, + byte* flatSignedAttribs, + word32 flatSignedAttribsSz, + ESD* esd) +{ + int ret; +#ifdef HAVE_ECC + int hashSz; +#endif + word32 digestInfoSz = MAX_SEQ_SZ + MAX_ALGO_SZ + + MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE; +#ifdef WOLFSSL_SMALL_STACK + byte* digestInfo; +#else + byte digestInfo[digestInfoSz]; +#endif + + if (pkcs7 == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + digestInfo = (byte*)XMALLOC(digestInfoSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (digestInfo == NULL) { + return MEMORY_E; + } +#endif + + ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd, digestInfo, + &digestInfoSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* sign digestInfo */ + switch (pkcs7->publicKeyOID) { + +#ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_RsaSign(pkcs7, digestInfo, digestInfoSz, esd); + break; +#endif + +#ifdef HAVE_ECC + case ECDSAk: + /* CMS with ECDSA does not sign DigestInfo structure + * like PKCS#7 with RSA does */ + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return hashSz; + } + + ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest, + hashSz, esd); + break; +#endif + + default: + WOLFSSL_MSG("Unsupported public key type"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret >= 0) { + esd->encContentDigestSz = (word32)ret; + } + + return ret; +} + + +/* sets the wc_HashType in ESD struct based on pkcs7->hashOID + * + * pkcs7 - pointer to initialized PKCS7 struct + * type - [OUT] pointer to wc_HashType for output + * + * returns hash digest size on success, negative on error */ +static enum wc_HashType wc_PKCS7_SetHashType(PKCS7* pkcs7, + enum wc_HashType* type) +{ + if (pkcs7 == NULL || type == NULL) + return BAD_FUNC_ARG; + + switch (pkcs7->hashOID) { + +#ifndef NO_SHA + case SHAh: + *type = WC_HASH_TYPE_SHA; + break; +#endif +#ifdef WOLFSSL_SHA224 + case SHA224h: + *type = WC_HASH_TYPE_SHA224; + break; +#endif +#ifndef NO_SHA256 + case SHA256h: + *type = WC_HASH_TYPE_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384h: + *type = WC_HASH_TYPE_SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512h: + *type = WC_HASH_TYPE_SHA512; + break; +#endif + default: + return BAD_FUNC_ARG; + } + + return wc_HashGetDigestSize(*type); +} + + /* build PKCS#7 signedData content type */ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) { @@ -454,6 +893,7 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) word32 signerInfoSz = 0; word32 totalSz = 0; int idx = 0, ret = 0; + int digEncAlgoId, digEncAlgoType, hashSz; byte* flatSignedAttribs = NULL; word32 flatSignedAttribsSz = 0; word32 innerOidSz = sizeof(innerOid); @@ -473,7 +913,16 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) #endif XMEMSET(esd, 0, sizeof(ESD)); - ret = wc_InitSha(&esd->sha); + + hashSz = wc_PKCS7_SetHashType(pkcs7, &esd->hashType); + if (hashSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return hashSz; + } + + ret = wc_HashInit(&esd->hash, esd->hashType); if (ret != 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); @@ -483,10 +932,24 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) if (pkcs7->contentSz != 0) { - wc_ShaUpdate(&esd->sha, pkcs7->content, pkcs7->contentSz); + ret = wc_HashUpdate(&esd->hash, esd->hashType, + pkcs7->content, pkcs7->contentSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } esd->contentDigest[0] = ASN_OCTET_STRING; - esd->contentDigest[1] = SHA_DIGEST_SIZE; - wc_ShaFinal(&esd->sha, &esd->contentDigest[2]); + esd->contentDigest[1] = hashSz; + ret = wc_HashFinal(&esd->hash, esd->hashType, + &esd->contentDigest[2]); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } } esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets); @@ -508,40 +971,30 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId, oidHashType, 0); signerInfoSz += esd->signerDigAlgoIdSz; - esd->digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd->digEncAlgoId, - oidKeyType, 0); + + /* set signatureAlgorithm */ + ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId, + &digEncAlgoType); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + esd->digEncAlgoIdSz = SetAlgoID(digEncAlgoId, esd->digEncAlgoId, + digEncAlgoType, 0); signerInfoSz += esd->digEncAlgoIdSz; if (pkcs7->signedAttribsSz != 0) { - byte contentTypeOid[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, - 0x09, 0x03 }; - byte contentType[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x07, 0x01 }; - byte messageDigestOid[] = - { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, - 0x09, 0x04 }; - PKCS7Attrib cannedAttribs[2] ; - - word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); - cannedAttribs[0].oid = contentTypeOid ; - cannedAttribs[0].oidSz = sizeof(contentTypeOid) ; - cannedAttribs[0].value = contentType ; - cannedAttribs[0].valueSz = sizeof(contentType) ; - cannedAttribs[1].oid = messageDigestOid ; - cannedAttribs[1].oidSz = sizeof(messageDigestOid) ; - cannedAttribs[1].value = esd->contentDigest ; - cannedAttribs[1].valueSz = sizeof(esd->contentDigest) ; - - esd->signedAttribsCount += cannedAttribsCount; - esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2, - cannedAttribs, cannedAttribsCount); - - esd->signedAttribsCount += pkcs7->signedAttribsSz; - esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, - pkcs7->signedAttribs, pkcs7->signedAttribsSz); + /* build up signed attributes */ + ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS); @@ -552,130 +1005,25 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) #endif return MEMORY_E; } + FlattenAttributes(flatSignedAttribs, esd->signedAttribs, esd->signedAttribsCount); esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz, esd->signedAttribSet); } + /* Calculate the final hash and encrypt it. */ - { - int result; - word32 scratch = 0; - + ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd); + if (ret < 0) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, 0, NULL); #ifdef WOLFSSL_SMALL_STACK - byte* digestInfo; - RsaKey* privKey; -#else - RsaKey stack_privKey; - RsaKey* privKey = &stack_privKey; - byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ + - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE]; + XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - byte digestInfoSeq[MAX_SEQ_SZ]; - byte digestStr[MAX_OCTET_STR_SZ]; - word32 digestInfoSeqSz, digestStrSz; - int digIdx = 0; - - if (pkcs7->signedAttribsSz != 0) { - byte attribSet[MAX_SET_SZ]; - word32 attribSetSz; - - attribSetSz = SetSet(flatSignedAttribsSz, attribSet); - - ret = wc_InitSha(&esd->sha); - if (ret < 0) { - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - wc_ShaUpdate(&esd->sha, attribSet, attribSetSz); - wc_ShaUpdate(&esd->sha, flatSignedAttribs, flatSignedAttribsSz); - wc_ShaFinal(&esd->sha, esd->contentAttribsDigest); - } else { - /* when no attrs, digest is contentDigest without tag and length */ - XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, - SHA_DIGEST_SIZE); - } - - digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr); - digestInfoSeqSz = SetSequence(esd->signerDigAlgoIdSz + - digestStrSz + SHA_DIGEST_SIZE, - digestInfoSeq); - -#ifdef WOLFSSL_SMALL_STACK - digestInfo = (byte*)XMALLOC(MAX_SEQ_SZ + MAX_ALGO_SZ + - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE, - NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (digestInfo == NULL) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, 0, NULL); - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); - digIdx += digestInfoSeqSz; - XMEMCPY(digestInfo + digIdx, - esd->signerDigAlgoId, esd->signerDigAlgoIdSz); - digIdx += esd->signerDigAlgoIdSz; - XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); - digIdx += digestStrSz; - XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, - SHA_DIGEST_SIZE); - digIdx += SHA_DIGEST_SIZE; - -#ifdef WOLFSSL_SMALL_STACK - privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (privKey == NULL) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, 0, NULL); - XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#endif - - result = wc_InitRsaKey(privKey, pkcs7->heap); - if (result == 0) - result = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, privKey, - pkcs7->privateKeySz); - if (result < 0) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); -#ifdef WOLFSSL_SMALL_STACK - XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return PUBLIC_KEY_E; - } - - result = wc_RsaSSL_Sign(digestInfo, digIdx, - esd->encContentDigest, - sizeof(esd->encContentDigest), - privKey, pkcs7->rng); - - wc_FreeRsaKey(privKey); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(privKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - if (result < 0) { - if (pkcs7->signedAttribsSz != 0) - XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS); -#ifdef WOLFSSL_SMALL_STACK - XFREE(esd, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return result; - } - esd->encContentDigestSz = (word32)result; + return ret; } + signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz; esd->signerDigestSz = SetOctetString(esd->encContentDigestSz, @@ -765,7 +1113,7 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) idx += esd->signerDigAlgoIdSz; /* SignerInfo:Attributes */ - if (pkcs7->signedAttribsSz != 0) { + if (flatSignedAttribsSz > 0) { XMEMCPY(output + idx, esd->signedAttribSet, esd->signedAttribSetSz); idx += esd->signedAttribSetSz; XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz); @@ -788,15 +1136,407 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) } +#ifndef NO_RSA + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, + byte* hash, word32 hashSz) +{ + #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ +\ + MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE) + int ret = 0; + word32 scratch = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + RsaKey* key; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + RsaKey stack_key; + RsaKey* key = &stack_key; +#endif + + if (pkcs7 == NULL || sig == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (digest == NULL) + return MEMORY_E; + + key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + ret = wc_InitRsaKey(key, pkcs7->heap); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key, + pkcs7->publicKeySz) < 0) { + WOLFSSL_MSG("ASN RSA key decode error"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PUBLIC_KEY_E; + } + + ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, key); + + wc_FreeRsaKey(key); + + if (((int)hashSz != ret) || (XMEMCMP(digest, hash, ret) != 0)) { + ret = SIG_VERIFY_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* NO_RSA */ + + +#ifdef HAVE_ECC + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, + byte* hash, word32 hashSz) +{ + #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ +\ + MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE) + int ret = 0; + int stat = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + ecc_key* key; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + ecc_key stack_key; + ecc_key* key = &stack_key; +#endif + + if (pkcs7 == NULL || sig == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (digest == NULL) + return MEMORY_E; + + key = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + ret = wc_ecc_init_ex(key, pkcs7->heap, INVALID_DEVID); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (wc_ecc_import_x963(pkcs7->publicKey, pkcs7->publicKeySz, key) < 0) { + WOLFSSL_MSG("ASN ECDSA key decode error"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PUBLIC_KEY_E; + } + + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &stat, key); + + wc_ecc_free(key); + + if (ret == 0 && stat != 1) { + ret = SIG_VERIFY_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_ECC */ + + +/* build SignedData digest, both in PKCS#7 DigestInfo format and + * as plain digest for CMS. + * + * pkcs7 - pointer to initialized PKCS7 struct + * signedAttrib - signed attributes + * signedAttribSz - size of signedAttrib, octets + * pkcs7Digest - [OUT] PKCS#7 DigestInfo + * pkcs7DigestSz - [IN/OUT] size of pkcs7Digest + * plainDigest - [OUT] pointer to plain digest, offset into pkcs7Digest + * plainDigestSz - [OUT] size of digest at plainDigest + * + * returns 0 on success, negative on error */ +static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib, + word32 signedAttribSz, byte* pkcs7Digest, + word32* pkcs7DigestSz, byte** plainDigest, + word32* plainDigestSz) +{ + int ret = 0, digIdx = 0, hashSz; + word32 attribSetSz; + byte attribSet[MAX_SET_SZ]; + byte digest[WC_MAX_DIGEST_SIZE]; + byte digestInfoSeq[MAX_SEQ_SZ]; + byte digestStr[MAX_OCTET_STR_SZ]; + byte algoId[MAX_ALGO_SZ]; + word32 digestInfoSeqSz, digestStrSz, algoIdSz; + word32 digestInfoSz = MAX_SEQ_SZ + MAX_ALGO_SZ + MAX_OCTET_STR_SZ + + WC_MAX_DIGEST_SIZE; +#ifdef WOLFSSL_SMALL_STACK + byte* digestInfo; +#else + byte digestInfo[digestInfoSz]; +#endif + + wc_HashAlg hash; + enum wc_HashType hashType; + + if (pkcs7 == NULL || pkcs7Digest == NULL || + pkcs7DigestSz == NULL || plainDigest == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + digestInfo = (byte*)XMALLOC(digestInfoSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (digestInfo == NULL) + return MEMORY_E; +#endif + + XMEMSET(pkcs7Digest, 0, *pkcs7DigestSz); + XMEMSET(digest, 0, WC_MAX_DIGEST_SIZE); + XMEMSET(digestInfo, 0, digestInfoSz); + + hashSz = wc_PKCS7_SetHashType(pkcs7, &hashType); + if (hashSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return hashSz; + } + + /* calculate digest */ + ret = wc_HashInit(&hash, hashType); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (signedAttribSz > 0) { + + if (signedAttrib == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + + attribSetSz = SetSet(signedAttribSz, attribSet); + ret = wc_HashUpdate(&hash, hashType, attribSet, attribSetSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + ret = wc_HashUpdate(&hash, hashType, signedAttrib, signedAttribSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + ret = wc_HashFinal(&hash, hashType, digest); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + } else { + + if (pkcs7->content == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + + ret = wc_HashUpdate(&hash, hashType, pkcs7->content, pkcs7->contentSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + ret = wc_HashFinal(&hash, hashType, digest); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + } + + /* Set algoID, with NULL attributes */ + algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); + + digestStrSz = SetOctetString(hashSz, digestStr); + digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, + digestInfoSeq); + + XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); + digIdx += digestInfoSeqSz; + XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); + digIdx += algoIdSz; + XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); + digIdx += digestStrSz; + XMEMCPY(digestInfo + digIdx, digest, hashSz); + digIdx += hashSz; + + XMEMCPY(pkcs7Digest, digestInfo, digIdx); + *pkcs7DigestSz = digIdx; + + /* set plain digest pointer */ + *plainDigest = pkcs7Digest + digIdx - hashSz; + *plainDigestSz = hashSz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return 0; +} + + +/* verifies SignedData signature, over either PKCS#7 DigestInfo or + * content digest. + * + * pkcs7 - pointer to initialized PKCS7 struct + * sig - signature to verify + * sigSz - size of sig + * signedAttrib - signed attributes, or null if empty + * signedAttribSz - size of signedAttributes + * + * return 0 on success, negative on error */ +static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig, + word32 sigSz, byte* signedAttrib, + word32 signedAttribSz) +{ + int ret = 0; + word32 plainDigestSz, pkcs7DigestSz; + word32 maxDigestSz = MAX_SEQ_SZ + MAX_ALGO_SZ + MAX_OCTET_STR_SZ + + WC_MAX_DIGEST_SIZE; + + byte* plainDigest; /* offset into pkcs7Digest */ +#ifdef WOLFSSL_SMALL_STACK + byte* pkcs7Digest; +#else + byte pkcs7Digest[maxDigestSz]; +#endif + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + pkcs7Digest = (byte*)XMALLOC(maxDigestSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pkcs7Digest == NULL) + return MEMORY_E; +#endif + + /* build hash to verify against */ + pkcs7DigestSz = maxDigestSz; + ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib, + signedAttribSz, pkcs7Digest, + &pkcs7DigestSz, &plainDigest, + &plainDigestSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + switch (pkcs7->publicKeyOID) { + +#ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, pkcs7Digest, + pkcs7DigestSz); + if (ret < 0) { + WOLFSSL_MSG("PKCS#7 verification failed, trying CMS"); + ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, plainDigest, + plainDigestSz); + } + break; +#endif + +#ifdef HAVE_ECC + case ECDSAk: + ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, sigSz, plainDigest, + plainDigestSz); + break; +#endif + + default: + WOLFSSL_MSG("Unsupported public key type"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} + + /* Finds the certificates in the message and saves it. */ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) { - word32 idx, contentType; + word32 idx, contentType, hashOID; int length, version, ret; byte* content = NULL; byte* sig = NULL; byte* cert = NULL; - int contentSz = 0, sigSz = 0, certSz = 0; + byte* signedAttrib = NULL; + int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0; if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0) return BAD_FUNC_ARG; @@ -939,11 +1679,10 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) idx += length; /* Get the sequence of digestAlgorithm */ - if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + if (GetAlgoId(pkiMsg, &idx, &hashOID, oidHashType, pkiMsgSz) < 0) { return ASN_PARSE_E; - - /* Skip it */ - idx += length; + } + pkcs7->hashOID = (int)hashOID; /* Get the IMPLICIT[0] SET OF signedAttributes */ if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { @@ -952,6 +1691,10 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; + /* save pointer and length */ + signedAttrib = &pkiMsg[idx]; + signedAttribSz = length; + idx += length; } @@ -979,72 +1722,18 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) pkcs7->content = content; pkcs7->contentSz = contentSz; - { - word32 scratch = 0; - int plainSz = 0; - #define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ +\ - MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE) - -#ifdef WOLFSSL_SMALL_STACK - byte* digest; - RsaKey* key; - - digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (digest == NULL) - return MEMORY_E; - - key = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (key == NULL) { - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#else - byte digest[MAX_PKCS7_DIGEST_SZ]; - RsaKey stack_key; - RsaKey* key = &stack_key; -#endif - - XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); - - ret = wc_InitRsaKey(key, pkcs7->heap); - if (ret != 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return ret; - } - if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key, - pkcs7->publicKeySz) < 0) { - WOLFSSL_MSG("ASN RSA key decode error"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return PUBLIC_KEY_E; - } - - plainSz = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, - key); - wc_FreeRsaKey(key); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - if (plainSz < 0) - return plainSz; - } + ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, + signedAttrib, signedAttribSz); + if (ret < 0) + return ret; } return 0; } +#ifdef HAVE_ECC + /* KARI == KeyAgreeRecipientInfo (key agreement) */ typedef struct WC_PKCS7_KARI { DecodedCert* decoded; /* decoded recip cert */ @@ -1770,6 +2459,8 @@ static int wc_CreateKeyAgreeRecipientInfo(PKCS7* pkcs7, const byte* cert, return idx; } +#endif /* HAVE_ECC */ + /* create ASN.1 formatted RecipientInfo structure, returns sequence size */ static int wc_CreateRecipientInfo(const byte* cert, word32 certSz, @@ -2300,6 +2991,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) MAX_RECIP_SZ, pkcs7->heap); break; +#ifdef HAVE_ECC case ECDSAk: recipSz = wc_CreateKeyAgreeRecipientInfo(pkcs7, pkcs7->singleCert, pkcs7->singleCertSz, @@ -2309,6 +3001,7 @@ int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) contentKeyPlain, contentKeyEnc, &contentKeyEncSz, recip, MAX_RECIP_SZ); break; +#endif default: WOLFSSL_MSG("Unsupported RecipientInfo public key type"); @@ -2652,6 +3345,8 @@ static int wc_PKCS7_DecodeKtri(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, } +#ifdef HAVE_ECC + /* remove ASN.1 OriginatorIdentifierOrKey, return 0 on success, <0 on error */ static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, byte* pkiMsg, word32 pkiMsgSz, word32* idx) @@ -2861,6 +3556,8 @@ static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, return 0; } +#endif /* HAVE_ECC */ + /* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success, * < 0 on error */ @@ -2868,6 +3565,7 @@ static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, word32* idx, byte* decryptedKey, word32* decryptedKeySz, int* recipFound) { +#ifdef HAVE_ECC int ret, keySz; int encryptedKeySz; int direction = 0; @@ -3001,6 +3699,17 @@ static int wc_PKCS7_DecodeKari(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, #endif return 0; +#else + (void)pkcs7; + (void)pkiMsg; + (void)pkiMsgSz; + (void)idx; + (void)decryptedKey; + (void)decryptedKeySz; + (void)recipFound; + + return NOT_COMPILED_IN; +#endif /* HAVE_ECC */ } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index ce24a6511..50b03f5de 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -549,7 +549,7 @@ int wolfcrypt_test(void* args) #endif #endif -#ifdef HAVE_X963_KDF +#if defined(HAVE_X963_KDF) && defined(HAVE_ECC) if ( (ret = x963kdf_test()) != 0) return err_sys("X963-KDF test failed!\n", ret); else @@ -5266,7 +5266,7 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) #ifndef NO_RSA static const char* clientKey = CERT_ROOT "client-key.der"; static const char* clientCert = CERT_ROOT "client-cert.der"; - #ifdef HAVE_PKCS7 + #if defined(HAVE_PKCS7) && defined(HAVE_ECC) static const char* eccClientKey = CERT_ROOT "ecc-client-key.der"; static const char* eccClientCert = CERT_ROOT "client-ecc-cert.der"; #endif @@ -9384,7 +9384,7 @@ int hkdf_test(void) #endif /* HAVE_HKDF */ -#if defined(HAVE_X963_KDF) +#if defined(HAVE_ECC) && defined(HAVE_X963_KDF) int x963kdf_test(void) { @@ -12148,6 +12148,132 @@ int compress_test(void) * #define PKCS7_OUTPUT_TEST_BUNDLES */ + +/* 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 + * + * 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) +{ +#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) + FILE* certFile; + FILE* keyFile; +#endif + +#ifndef NO_RSA + if (rsaCert == NULL || rsaCertSz == NULL || + rsaPrivKey == NULL || rsaPrivKeySz == NULL) + return BAD_FUNC_ARG; +#endif + +#ifdef HAVE_ECC + if (eccCert == NULL || eccCertSz == NULL || + eccPrivKey == NULL || eccPrivKeySz == NULL) + return BAD_FUNC_ARG; +#endif + +/* RSA */ +#ifndef NO_RSA + +#ifdef USE_CERT_BUFFERS_1024 + if (*rsaCertSz < sizeof_client_cert_der_1024) + return -201; + + 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 < sizeof_client_cert_der_2048) + return -202; + + XMEMCPY(rsaCert, client_cert_der_2048, sizeof_client_cert_der_2048); + rsaCertSz = sizeof_client_cert_der_2048; +#else + certFile = fopen(clientCert, "rb"); + if (!certFile) + return -203; + + *rsaCertSz = (word32)fread(rsaCert, 1, *rsaCertSz, certFile); + fclose(certFile); +#endif + +#ifdef USE_CERT_BUFFERS_1024 + if (*rsaKeySz < sizeof_client_key_der_1024) + return -204; + + XMEMCPY(rsaPrivKey, client_key_der_1024, sizeof_client_key_der_1024); + *rsaPrivKeySz = sizeof_client_key_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + if (*rsaKeySz < sizeof_client_key_der_2048) + return -205; + + XMEMCPY(rsaPrivKey, client_key_der_2048, sizeof_client_key_der_2048); + *rsaPrivKeySz = sizeof_client_key_der_2048; +#else + keyFile = fopen(clientKey, "rb"); + if (!keyFile) + return -204; + + *rsaPrivKeySz = (word32)fread(rsaPrivKey, 1, *rsaPrivKeySz, keyFile); + fclose(keyFile); +#endif /* USE_CERT_BUFFERS */ + +#endif /* NO_RSA */ + +/* ECC */ +#ifdef HAVE_ECC + +#ifdef USE_CERT_BUFFERS_256 + if (*eccCertSz < sizeof_cliecc_cert_der_256) + return -206; + + XMEMCPY(eccCert, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); + *eccCertSz = sizeof_cliecc_cert_der_256; +#else + certFile = fopen(eccClientCert, "rb"); + if (!certFile) + return -207; + + *eccCertSz = (word32)fread(eccCert, 1, *eccCertSz, certFile); + fclose(certFile); +#endif /* USE_CERT_BUFFERS_256 */ + +#ifdef USE_CERT_BUFFERS_256 + if (*eccPrivKeySz < sizeof_ecc_clikey_der_256) + return -208; + + XMEMCPY(eccPrivKey, ecc_clikey_der_256, sizeof_ecc_clikey_der_256); + *eccPrivKeySz = sizeof_ecc_clikey_der_256; +#else + keyFile = fopen(eccClientKey, "rb"); + if (!keyFile) + return -208; + + *eccPrivKeySz = (word32)fread(eccPrivKey, 1, *eccPrivKeySz, keyFile); + fclose(keyFile); +#endif /* USE_CERT_BUFFERS_256 */ +#endif /* HAVE_ECC */ + + (void)eccCert; + (void)eccCertSz; + (void)eccPrivKey; + (void)eccPrivKeySz; + return 0; +} + + typedef struct { const byte* content; word32 contentSz; @@ -12185,7 +12311,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, 0x72,0x6c,0x64 }; -#ifndef NO_AES +#if !defined(NO_AES) && defined(HAVE_ECC) byte optionalUkm[] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 }; @@ -12287,8 +12413,11 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz, if (!pkcs7File) return -213; - ret = (int)fwrite(enveloped, envelopedSz, 1, pkcs7File); + ret = (int)fwrite(enveloped, 1, envelopedSz, pkcs7File); fclose(pkcs7File); + if (ret != envelopedSz) { + return -214; + } #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ wc_PKCS7_Free(&pkcs7); @@ -12311,15 +12440,10 @@ int pkcs7enveloped_test(void) byte* rsaPrivKey = NULL; byte* eccPrivKey = NULL; - size_t rsaCertSz = 0; - size_t eccCertSz = 0; - size_t rsaPrivKeySz = 0; - size_t eccPrivKeySz = 0; - -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) - FILE* certFile; - FILE* keyFile; -#endif + word32 rsaCertSz = 0; + word32 eccCertSz = 0; + word32 rsaPrivKeySz = 0; + word32 eccPrivKeySz = 0; #ifndef NO_RSA /* read client RSA cert and key in DER format */ @@ -12333,46 +12457,8 @@ int pkcs7enveloped_test(void) return -202; } -#ifdef USE_CERT_BUFFERS_1024 - XMEMCPY(rsaCert, client_cert_der_1024, sizeof_client_cert_der_1024); - rsaCertSz = sizeof_client_cert_der_1024; -#elif defined(USE_CERT_BUFFERS_2048) - XMEMCPY(rsaCert, client_cert_der_2048, sizeof_client_cert_der_2048); - rsaCertSz = sizeof_client_cert_der_2048; -#else - certFile = fopen(clientCert, "rb"); - if (!certFile) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-cert.der, " - "Please run from wolfSSL home dir", -42); - return -203; - } - - rsaCertSz = fread(rsaCert, 1, FOURK_BUF, certFile); - fclose(certFile); -#endif - -#ifdef USE_CERT_BUFFERS_1024 - XMEMCPY(rsaPrivKey, client_key_der_1024, sizeof_client_key_der_1024); - rsaPrivKeySz = sizeof_client_key_der_1024; -#elif defined(USE_CERT_BUFFERS_2048) - XMEMCPY(rsaPrivKey, client_key_der_2048, sizeof_client_key_der_2048); - rsaPrivKeySz = sizeof_client_key_der_2048; -#else - keyFile = fopen(clientKey, "rb"); - if (!keyFile) { - XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-key.der, " - "Please run from wolfSSL home dir", -43); - return -204; - } - - rsaPrivKeySz = fread(rsaPrivKey, 1, FOURK_BUF, keyFile); - fclose(keyFile); -#endif /* USE_CERT_BUFFERS */ - + rsaCertSz = FOURK_BUF; + rsaPrivKeySz = FOURK_BUF; #endif /* NO_RSA */ #ifdef HAVE_ECC @@ -12381,7 +12467,7 @@ int pkcs7enveloped_test(void) if (eccCert == NULL) { XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -205; + return -203; } eccPrivKey =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); @@ -12389,51 +12475,17 @@ int pkcs7enveloped_test(void) 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 -206; + return -204; } -#ifdef USE_CERT_BUFFERS_256 - XMEMCPY(eccCert, cliecc_cert_der_256, sizeof_cliecc_cert_der_256); - eccCertSz = sizeof_cliecc_cert_der_256; -#else - certFile = fopen(eccClientCert, "rb"); - if (!certFile) { - 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); - err_sys("can't open ./certs/client-ecc-cert.der, " - "Please run from wolfSSL home dir", -42); - return -207; - } - eccCertSz = fread(eccCert, 1, FOURK_BUF, certFile); - fclose(certFile); -#endif /* USE_CERT_BUFFERS_256 */ - -#ifdef USE_CERT_BUFFERS_256 - XMEMCPY(eccPrivKey, ecc_clikey_der_256, sizeof_ecc_clikey_der_256); - eccPrivKeySz = sizeof_ecc_clikey_der_256; -#else - keyFile = fopen(eccClientKey, "rb"); - if (!keyFile) { - 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); - err_sys("can't open ./certs/ecc-client-key.der, " - "Please run from wolfSSL home dir", -43); - return -208; - } - eccPrivKeySz = fread(eccPrivKey, 1, FOURK_BUF, keyFile); - fclose(keyFile); -#endif /* USE_CERT_BUFFERS_256 */ + eccCertSz = FOURK_BUF; + eccPrivKeySz = FOURK_BUF; #endif /* HAVE_ECC */ - ret = pkcs7enveloped_run_vectors(rsaCert, (word32)rsaCertSz, - rsaPrivKey, (word32)rsaPrivKeySz, - eccCert, (word32)eccCertSz, - eccPrivKey, (word32)eccPrivKeySz); - if (ret != 0) { + ret = pkcs7_load_certs_keys(rsaCert, &rsaCertSz, rsaPrivKey, + &rsaPrivKeySz, eccCert, &eccCertSz, + eccPrivKey, &eccPrivKeySz); + 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); @@ -12441,12 +12493,17 @@ int pkcs7enveloped_test(void) return ret; } + ret = pkcs7enveloped_run_vectors(rsaCert, (word32)rsaCertSz, + rsaPrivKey, (word32)rsaPrivKeySz, + eccCert, (word32)eccCertSz, + eccPrivKey, (word32)eccPrivKeySz); + 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); - return 0; + return ret; } @@ -12650,19 +12707,41 @@ int pkcs7encrypted_test(void) return ret; } -int pkcs7signed_test(void) + +typedef struct { + const byte* content; + word32 contentSz; + int hashOID; + int encryptOID; + byte* privateKey; + word32 privateKeySz; + byte* cert; + size_t certSz; + PKCS7Attrib* signedAttribs; + word32 signedAttribsSz; + const char* outFileName; +} pkcs7SignedVector; + + +static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz, + byte* rsaPrivKey, word32 rsaPrivKeySz, + byte* eccCert, word32 eccCertSz, + byte* eccPrivKey, word32 eccPrivKeySz) { - int ret = 0; -#if !defined(USE_CERT_BUFFERS_1024) && !defined(USE_CERT_BUFFERS_2048) - FILE* file; -#endif - byte* certDer; - byte* keyDer; - byte* out; - char data[] = "Hello World"; - word32 dataSz, outSz, certDerSz, keyDerSz; - PKCS7 msg; + 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 + }; static byte transIdOid[] = { 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01, @@ -12687,64 +12766,91 @@ int pkcs7signed_test(void) senderNonce, sizeof(senderNonce) } }; - dataSz = (word32) XSTRLEN(data); + const pkcs7SignedVector testVectors[] = + { +#ifndef NO_RSA + #ifndef NO_SHA + /* RSA with SHA */ + {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_RSA_SHA.der"}, + + /* RSA with SHA, no signed attributes */ + {data, (word32)sizeof(data), SHAh, RSAk, rsaPrivKey, rsaPrivKeySz, + rsaCert, rsaCertSz, NULL, 0, + "pkcs7signedData_RSA_SHA_noattr.der"}, + #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"}, + #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"}, + #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"}, + #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"}, + #endif +#endif /* NO_RSA */ + +#ifdef HAVE_ECC + #ifndef NO_SHA + /* ECDSA with SHA */ + {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, attribs, (sizeof(attribs)/sizeof(PKCS7Attrib)), + "pkcs7signedData_ECDSA_SHA.der"}, + + /* ECDSA with SHA, no signed attributes */ + {data, (word32)sizeof(data), SHAh, ECDSAk, eccPrivKey, eccPrivKeySz, + eccCert, eccCertSz, NULL, 0, + "pkcs7signedData_ECDSA_SHA_noattr.der"}, + #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"}, + #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"}, + #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"}, + #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"}, + #endif +#endif /* HAVE_ECC */ + }; + + testSz = sizeof(testVectors) / sizeof(pkcs7SignedVector); + outSz = FOURK_BUF; - - certDer =(byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (certDer == NULL) - return -207; - keyDer = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (keyDer == NULL) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -208; - } - out = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - if (out == NULL) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + out = (byte*)XMALLOC(outSz, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (out == NULL) return -209; - } - - /* read in DER cert of recipient, into cert of size certSz */ -#ifdef USE_CERT_BUFFERS_1024 - XMEMCPY(certDer, client_cert_der_1024, sizeof_client_cert_der_1024); - certDerSz = sizeof_client_cert_der_1024; -#elif defined(USE_CERT_BUFFERS_2048) - XMEMCPY(certDer, client_cert_der_2048, sizeof_client_cert_der_2048); - certDerSz = sizeof_client_cert_der_2048; -#else - file = fopen(clientCert, "rb"); - if (!file) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-cert.der, " - "Please run from wolfSSL home dir", -44); - return -44; - } - certDerSz = (word32)fread(certDer, 1, FOURK_BUF, file); - fclose(file); -#endif /* USE_CERT_BUFFER_ */ - -#ifdef USE_CERT_BUFFERS_1024 - XMEMCPY(keyDer, client_key_der_1024, sizeof_client_key_der_1024); - keyDerSz = sizeof_client_key_der_1024; -#elif defined(USE_CERT_BUFFERS_2048) - XMEMCPY(keyDer, client_key_der_2048, sizeof_client_key_der_2048); - keyDerSz = sizeof_client_key_der_2048; -#else - file = fopen(clientKey, "rb"); - if (!file) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - err_sys("can't open ./certs/client-key.der, " - "Please run from wolfSSL home dir", -45); - return -45; - } - keyDerSz = (word32)fread(keyDer, 1, FOURK_BUF, file); - fclose(file); -#endif /* USE_CERT_BUFFER_ */ #ifndef HAVE_FIPS ret = wc_InitRng_ex(&rng, HEAP_HINT, devId); @@ -12752,131 +12858,205 @@ int pkcs7signed_test(void) ret = wc_InitRng(&rng); #endif if (ret != 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); return -210; } - senderNonce[0] = 0x04; - senderNonce[1] = PKCS7_NONCE_SZ; + for (i = 0; i < testSz; i++) { - ret = wc_RNG_GenerateBlock(&rng, &senderNonce[2], PKCS7_NONCE_SZ); - if (ret != 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -211; - } + ret = wc_PKCS7_InitWithCert(&pkcs7, testVectors[i].cert, + (word32)testVectors[i].certSz); - wc_PKCS7_InitWithCert(&msg, certDer, certDerSz); - msg.privateKey = keyDer; - msg.privateKeySz = keyDerSz; - msg.content = (byte*)data; - msg.contentSz = dataSz; - msg.hashOID = SHAh; - msg.encryptOID = RSAk; - msg.signedAttribs = attribs; - msg.signedAttribsSz = sizeof(attribs)/sizeof(PKCS7Attrib); - msg.rng = &rng; - { - Sha sha; - byte digest[SHA_DIGEST_SIZE]; - int i,j; + if (ret != 0) + return -211; - transId[0] = 0x13; - transId[1] = SHA_DIGEST_SIZE * 2; + pkcs7.rng = &rng; + pkcs7.content = (byte*)testVectors[i].content; + pkcs7.contentSz = testVectors[i].contentSz; + pkcs7.hashOID = testVectors[i].hashOID; + pkcs7.encryptOID = testVectors[i].encryptOID; + pkcs7.privateKey = testVectors[i].privateKey; + pkcs7.privateKeySz = testVectors[i].privateKeySz; + pkcs7.signedAttribs = testVectors[i].signedAttribs; + pkcs7.signedAttribsSz = testVectors[i].signedAttribsSz; - ret = wc_InitSha_ex(&sha, HEAP_HINT, devId); - if (ret != 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + /* generate senderNonce */ + { + senderNonce[0] = 0x04; + senderNonce[1] = PKCS7_NONCE_SZ; + + ret = wc_RNG_GenerateBlock(&rng, &senderNonce[2], PKCS7_NONCE_SZ); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -212; + } + } + + /* generate trans ID */ + { + Sha sha; + byte digest[SHA_DIGEST_SIZE]; + int j,k; + + transId[0] = 0x13; + transId[1] = SHA_DIGEST_SIZE * 2; + + ret = wc_InitSha_ex(&sha, HEAP_HINT, devId); + if (ret != 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -213; + } + wc_ShaUpdate(&sha, pkcs7.publicKey, pkcs7.publicKeySz); + wc_ShaFinal(&sha, digest); + wc_ShaFree(&sha); + + for (j = 0, k = 2; j < SHA_DIGEST_SIZE; j++, k += 2) { + snprintf((char*)&transId[k], 3, "%02x", digest[j]); + } + } + + encodedSz = wc_PKCS7_EncodeSignedData(&pkcs7, out, outSz); + if (encodedSz < 0) { XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - return -4003; + wc_PKCS7_Free(&pkcs7); + return -214; } - wc_ShaUpdate(&sha, msg.publicKey, msg.publicKeySz); - wc_ShaFinal(&sha, digest); - wc_ShaFree(&sha); - for (i = 0, j = 2; i < SHA_DIGEST_SIZE; i++, j += 2) { - snprintf((char*)&transId[j], 3, "%02x", digest[i]); + #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 -215; } - } - ret = wc_PKCS7_EncodeSignedData(&msg, out, outSz); - if (ret < 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -212; - } - else - outSz = ret; + 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 -216; + } + #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ -#ifdef PKCS7_OUTPUT_TEST_BUNDLES - /* write PKCS#7 to output file for more testing */ - file = fopen("./pkcs7signedData.der", "wb"); - if (!file) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -213; - } - ret = (int)fwrite(out, 1, outSz, file); - fclose(file); - if (ret != (int)outSz) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -218; - } -#endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + wc_PKCS7_Free(&pkcs7); + wc_PKCS7_InitWithCert(&pkcs7, NULL, 0); - wc_PKCS7_Free(&msg); - wc_PKCS7_InitWithCert(&msg, 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 -217; + } - ret = wc_PKCS7_VerifySignedData(&msg, out, outSz); - if (ret < 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -214; + if (pkcs7.singleCert == NULL || pkcs7.singleCertSz == 0) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -218; + } + + #ifdef PKCS7_OUTPUT_TEST_BUNDLES + file = fopen("./pkcs7cert.der", "wb"); + if (!file) { + XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS7_Free(&pkcs7); + return -219; + } + ret = (int)fwrite(pkcs7.singleCert, 1, pkcs7.singleCertSz, file); + fclose(file); + #endif /* PKCS7_OUTPUT_TEST_BUNDLES */ + + wc_PKCS7_Free(&pkcs7); } - if (msg.singleCert == NULL || msg.singleCertSz == 0) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -215; - } - -#ifdef PKCS7_OUTPUT_TEST_BUNDLES - file = fopen("./pkcs7cert.der", "wb"); - if (!file) { - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - return -216; - } - ret = (int)fwrite(msg.singleCert, 1, msg.singleCertSz, file); - fclose(file); -#endif /* PKCS7_OUTPUT_TEST_BUNDLES */ - - XFREE(certDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyDer, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS7_Free(&msg); - wc_FreeRng(&rng); if (ret > 0) return 0; + (void)eccCert; + (void)eccCertSz; + (void)eccPrivKey; + (void)eccPrivKeySz; + return ret; +} + + +int pkcs7signed_test(void) +{ + int ret = 0; + + byte* rsaCert = NULL; + byte* eccCert = NULL; + byte* rsaPrivKey = NULL; + byte* eccPrivKey = NULL; + + word32 rsaCertSz = 0; + word32 eccCertSz = 0; + word32 rsaPrivKeySz = 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 -201; + + rsaPrivKey = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (rsaPrivKey == NULL) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -202; + } + + 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) { + XFREE(rsaCert, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(rsaPrivKey, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + return -203; + } + + 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 -204; + } + + eccCertSz = FOURK_BUF; + eccPrivKeySz = FOURK_BUF; +#endif /* HAVE_ECC */ + + ret = pkcs7_load_certs_keys(rsaCert, &rsaCertSz, rsaPrivKey, + &rsaPrivKeySz, eccCert, &eccCertSz, + eccPrivKey, &eccPrivKeySz); + 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); + return ret; + } + + ret = pkcs7signed_run_vectors(rsaCert, (word32)rsaCertSz, + rsaPrivKey, (word32)rsaPrivKeySz, + eccCert, (word32)eccCertSz, + eccPrivKey, (word32)eccPrivKeySz); + + 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); + return ret; }