allow different hashes with PKCS7 SignedData, cleanup conditional builds

This commit is contained in:
Chris Conlon
2017-04-14 13:33:54 -06:00
parent 74aafb1679
commit 4f26e0341b
4 changed files with 526 additions and 151 deletions

13
.gitignore vendored
View File

@@ -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

View File

@@ -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=

View File

@@ -31,6 +31,7 @@
#include <wolfssl/wolfcrypt/pkcs7.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
#include <wolfssl/wolfcrypt/hash.h>
#ifndef NO_RSA
#include <wolfssl/wolfcrypt/rsa.h>
#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,8 @@ 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)
{
@@ -459,6 +463,7 @@ static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd)
ret = wc_InitRsaKey(privKey, pkcs7->heap);
if (ret == 0) {
idx = 0;
ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey,
pkcs7->privateKeySz);
}
@@ -477,6 +482,10 @@ static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd)
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)
@@ -524,6 +533,8 @@ static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd)
return ret;
}
#endif /* HAVE_ECC */
/* builds up SignedData signed attributes, including default ones.
*
@@ -533,6 +544,7 @@ 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)
{
int hashSz;
byte contentTypeOid[] =
{ ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
@@ -547,9 +559,13 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd)
PKCS7Attrib cannedAttribs[2];
word32 cannedAttribsCount;
if (pkcs7 == NULL || esd == NULL)
if (pkcs7 == NULL || esd == NULL || &esd->hash == NULL)
return BAD_FUNC_ARG;
hashSz = wc_HashGetDigestSize(esd->hashType);
if (hashSz < 0)
return hashSz;
cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib);
cannedAttribs[0].oid = contentTypeOid;
@@ -559,7 +575,7 @@ static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd)
cannedAttribs[1].oid = messageDigestOid;
cannedAttribs[1].oidSz = sizeof(messageDigestOid);
cannedAttribs[1].value = esd->contentDigest;
cannedAttribs[1].valueSz = sizeof(esd->contentDigest);
cannedAttribs[1].valueSz = hashSz + 2; /* ASN.1 heading */
esd->signedAttribsCount += cannedAttribsCount;
esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 2,
@@ -648,19 +664,24 @@ static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs,
word32 flatSignedAttribsSz, ESD* esd,
byte* digestInfo, word32* digestInfoSz)
{
int ret, digIdx = 0;
int ret, hashSz, digIdx = 0;
byte digestInfoSeq[MAX_SEQ_SZ];
byte digestStr[MAX_OCTET_STR_SZ];
byte attribSet[MAX_SET_SZ];
word32 digestInfoSeqSz, digestStrSz;
byte algoId[MAX_ALGO_SZ];
word32 digestInfoSeqSz, digestStrSz, algoIdSz;
word32 attribSetSz;
if (pkcs7 == NULL || esd == NULL || &esd->sha == NULL ||
if (pkcs7 == NULL || esd == NULL || &esd->hash == NULL ||
esd->contentDigest == NULL || esd->signerDigAlgoId == 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)
@@ -668,38 +689,49 @@ static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs,
attribSetSz = SetSet(flatSignedAttribsSz, attribSet);
ret = wc_InitSha(&esd->sha);
ret = wc_HashInit(&esd->hash, esd->hashType);
if (ret < 0)
return ret;
wc_ShaUpdate(&esd->sha, attribSet, attribSetSz);
wc_ShaUpdate(&esd->sha, flatSignedAttribs, flatSignedAttribsSz);
wc_ShaFinal(&esd->sha, esd->contentAttribsDigest);
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,
SHA_DIGEST_SIZE);
XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, hashSz);
}
digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr);
digestInfoSeqSz = SetSequence(esd->signerDigAlgoIdSz +
digestStrSz + SHA_DIGEST_SIZE,
/* 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 + esd->signerDigAlgoIdSz +
digestStrSz + SHA_DIGEST_SIZE)) {
if (*digestInfoSz < (digestInfoSeqSz + algoIdSz + digestStrSz + hashSz)) {
return BUFFER_E;
}
XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
digIdx += digestInfoSeqSz;
XMEMCPY(digestInfo + digIdx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz);
digIdx += esd->signerDigAlgoIdSz;
XMEMCPY(digestInfo + digIdx, algoId, algoIdSz);
digIdx += algoIdSz;
XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
digIdx += digestStrSz;
XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, SHA_DIGEST_SIZE);
digIdx += SHA_DIGEST_SIZE;
XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz);
digIdx += hashSz;
*digestInfoSz = digIdx;
@@ -721,8 +753,11 @@ static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7,
ESD* esd)
{
int ret;
#ifdef HAVE_ECC
int hashSz;
#endif
word32 digestInfoSz = MAX_SEQ_SZ + MAX_ALGO_SZ +
MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE;
MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE;
#ifdef WOLFSSL_SMALL_STACK
byte* digestInfo;
#else
@@ -752,16 +787,28 @@ static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7,
/* 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,
SHA_DIGEST_SIZE, esd);
hashSz, esd);
break;
#endif
default:
WOLFSSL_MSG("Unsupported public key type");
@@ -780,6 +827,53 @@ static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7,
}
/* 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)
{
@@ -800,7 +894,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;
int digEncAlgoId, digEncAlgoType, hashSz;
byte* flatSignedAttribs = NULL;
word32 flatSignedAttribsSz = 0;
word32 innerOidSz = sizeof(innerOid);
@@ -820,7 +914,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);
@@ -830,10 +933,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);
@@ -873,6 +990,12 @@ int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
/* 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);
@@ -1014,26 +1137,31 @@ 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)
{
(void)hash;
(void)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;
#define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ +\
MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE)
if (pkcs7 == NULL || pkcs7->publicKey == NULL || sig == NULL ||
hash == NULL)
return BAD_FUNC_ARG;
#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 || pkcs7->publicKey == 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);
@@ -1045,10 +1173,6 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
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);
@@ -1061,6 +1185,7 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
#endif
return ret;
}
if (wc_RsaPublicKeyDecode(pkcs7->publicKey, &scratch, key,
pkcs7->publicKeySz) < 0) {
WOLFSSL_MSG("ASN RSA key decode error");
@@ -1075,8 +1200,9 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
wc_FreeRsaKey(key);
if (XMEMCMP(digest, hash, ret) != 0)
if (((int)hashSz != ret) || (XMEMCMP(digest, hash, ret) != 0)) {
ret = SIG_VERIFY_E;
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
@@ -1086,23 +1212,32 @@ static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
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;
#define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ +\
MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE)
#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 || pkcs7->publicKey == NULL || sig == NULL)
return BAD_FUNC_ARG;
#ifdef WOLFSSL_SMALL_STACK
byte* digest;
ecc_key* key;
digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
@@ -1114,10 +1249,6 @@ static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#else
byte digest[MAX_PKCS7_DIGEST_SZ];
ecc_key stack_key;
ecc_key* key = &stack_key;
#endif
XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ);
@@ -1130,6 +1261,7 @@ static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
#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
@@ -1155,97 +1287,258 @@ static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
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* digAlgId,
word32 digAlgIdSz, byte* out,
word32 outSz)
word32 signedAttribSz, byte* pkcs7Digest,
word32* pkcs7DigestSz, byte** plainDigest,
word32* plainDigestSz)
{
int ret = 0;
int ret = 0, digIdx = 0, hashSz;
word32 attribSetSz;
byte attribSet[MAX_SET_SZ];
byte digest[SHA_DIGEST_SIZE];
byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ + MAX_OCTET_STR_SZ +
SHA_DIGEST_SIZE];
byte digest[WC_MAX_DIGEST_SIZE];
byte digestInfoSeq[MAX_SEQ_SZ];
byte digestStr[MAX_OCTET_STR_SZ];
word32 digestInfoSeqSz, digestStrSz;
int digIdx = 0;
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
Sha sha;
wc_HashAlg hash;
enum wc_HashType hashType;
if (pkcs7 == NULL || digAlgId == NULL || out == NULL)
if (pkcs7 == NULL || pkcs7Digest == NULL ||
pkcs7DigestSz == NULL || plainDigest == NULL) {
return BAD_FUNC_ARG;
}
XMEMSET(out, 0, outSz);
XMEMSET(digest, 0, SHA_DIGEST_SIZE);
#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_InitSha(&sha);
if (ret < 0)
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)
if (signedAttrib == NULL) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return BAD_FUNC_ARG;
}
attribSetSz = SetSet(signedAttribSz, attribSet);
wc_ShaUpdate(&sha, attribSet, attribSetSz);
wc_ShaUpdate(&sha, signedAttrib, signedAttribSz);
wc_ShaFinal(&sha, digest);
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)
if (pkcs7->content == NULL) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(digestInfo, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return BAD_FUNC_ARG;
}
wc_ShaUpdate(&sha, pkcs7->content, pkcs7->contentSz);
wc_ShaFinal(&sha, digest);
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;
}
}
/* form input to verify operation */
if (pkcs7->publicKeyOID == RSAk) {
/* Set algoID, with NULL attributes */
algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0);
digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr);
digestInfoSeqSz = SetSequence(digAlgIdSz + digestStrSz +
SHA_DIGEST_SIZE, digestInfoSeq);
digestStrSz = SetOctetString(hashSz, digestStr);
digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz,
digestInfoSeq);
XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
digIdx += digestInfoSeqSz;
XMEMCPY(digestInfo + digIdx, digAlgId, digAlgIdSz);
digIdx += digAlgIdSz;
XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
digIdx += digestStrSz;
XMEMCPY(digestInfo + digIdx, digest, SHA_DIGEST_SIZE);
digIdx += SHA_DIGEST_SIZE;
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(out, digestInfo, digIdx);
XMEMCPY(pkcs7Digest, digestInfo, digIdx);
*pkcs7DigestSz = digIdx;
} else if (pkcs7->publicKeyOID == ECDSAk) {
/* set plain digest pointer */
*plainDigest = pkcs7Digest + digIdx - hashSz;
*plainDigestSz = hashSz;
XMEMCPY(out, digest, SHA_DIGEST_SIZE);
digIdx = SHA_DIGEST_SIZE;
#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;
}
return digIdx;
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;
byte* signedAttrib = NULL;
byte* digAlgId = NULL;
int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0;
int digAlgIdSz = 0;
if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
return BAD_FUNC_ARG;
@@ -1387,18 +1680,11 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
/* Skip it */
idx += length;
/* Get the sequence of digestAlgorithm, saving pointer */
digAlgId = &pkiMsg[idx];
digAlgIdSz = idx;
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
/* Get the sequence of digestAlgorithm */
if (GetAlgoId(pkiMsg, &idx, &hashOID, oidHashType, pkiMsgSz) < 0) {
return ASN_PARSE_E;
/* update digAlgIdSz with sequence and length */
digAlgIdSz = length + (idx - digAlgIdSz);
/* Skip it */
idx += length;
}
pkcs7->hashOID = (int)hashOID;
/* Get the IMPLICIT[0] SET OF signedAttributes */
if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
@@ -1438,34 +1724,8 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
pkcs7->content = content;
pkcs7->contentSz = contentSz;
#define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ +\
MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE)
/* build hash to verify against */
byte finalDigest[MAX_PKCS7_DIGEST_SZ];
ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib,
signedAttribSz, digAlgId,
digAlgIdSz, finalDigest,
SHA_DIGEST_SIZE);
if (ret < 0)
return ret;
switch (pkcs7->publicKeyOID) {
case RSAk:
ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, finalDigest, ret);
break;
case ECDSAk:
ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, sigSz, finalDigest, ret);
break;
default:
WOLFSSL_MSG("Unsupported public key type");
ret = BAD_FUNC_ARG;
}
ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz,
signedAttrib, signedAttribSz);
if (ret < 0)
return ret;
}
@@ -1474,6 +1734,8 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
}
#ifdef HAVE_ECC
/* KARI == KeyAgreeRecipientInfo (key agreement) */
typedef struct WC_PKCS7_KARI {
DecodedCert* decoded; /* decoded recip cert */
@@ -2199,6 +2461,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,
@@ -2729,6 +2993,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,
@@ -2738,6 +3003,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");
@@ -3081,6 +3347,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)
@@ -3290,6 +3558,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 */
@@ -3297,6 +3567,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;
@@ -3430,6 +3701,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 */
}

View File

@@ -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)
{
@@ -12266,6 +12266,10 @@ static int pkcs7_load_certs_keys(byte* rsaCert, word32* rsaCertSz,
#endif /* USE_CERT_BUFFERS_256 */
#endif /* HAVE_ECC */
(void)eccCert;
(void)eccCertSz;
(void)eccPrivKey;
(void)eccPrivKeySz;
return 0;
}
@@ -12307,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
};
@@ -12409,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);
@@ -12722,6 +12729,7 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz,
byte* eccPrivKey, word32 eccPrivKeySz)
{
int ret, testSz, i;
int encodedSz;
byte* out;
word32 outSz;
WC_RNG rng;
@@ -12760,11 +12768,46 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz,
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)),
@@ -12774,6 +12817,32 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz,
{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);
@@ -12848,14 +12917,12 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz,
}
}
ret = wc_PKCS7_EncodeSignedData(&pkcs7, out, outSz);
if (ret < 0) {
encodedSz = wc_PKCS7_EncodeSignedData(&pkcs7, out, outSz);
if (encodedSz < 0) {
XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
wc_PKCS7_Free(&pkcs7);
return -214;
}
else
outSz = ret;
#ifdef PKCS7_OUTPUT_TEST_BUNDLES
/* write PKCS#7 to output file for more testing */
@@ -12865,9 +12932,9 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz,
wc_PKCS7_Free(&pkcs7);
return -215;
}
ret = (int)fwrite(out, 1, outSz, file);
ret = (int)fwrite(out, 1, encodedSz, file);
fclose(file);
if (ret != (int)outSz) {
if (ret != (int)encodedSz) {
XFREE(out, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
wc_PKCS7_Free(&pkcs7);
return -216;
@@ -12910,6 +12977,10 @@ static int pkcs7signed_run_vectors(byte* rsaCert, word32 rsaCertSz,
if (ret > 0)
return 0;
(void)eccCert;
(void)eccCertSz;
(void)eccPrivKey;
(void)eccPrivKeySz;
return ret;
}