diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 58a726fe3..ef7d43b98 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -3426,7 +3426,8 @@ int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, /* check key type and get OID if ECC */ if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap))< 0) { - return ret; + WOLFSSL_MSG("Error getting key OID"); + return ret; } /* PKCS#8 wrapping around key */ @@ -3937,6 +3938,9 @@ exit_tte: * heap possible heap hint for mallocs/frees * * returns the total size of encrypted content on success. + * + * data returned is : + * [ seq - obj [ seq -salt,itt]] , construct with encrypted data */ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, const char* password, int passwordSz, int vPKCS, int vAlgo, @@ -3947,6 +3951,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, word32 tmpIdx = 0; word32 totalSz = 0; word32 seqSz; + word32 innerSz; int ret; int version, id, blockSz = 0; #ifdef WOLFSSL_SMALL_STACK @@ -3956,6 +3961,11 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, byte saltTmp[MAX_SALT_SIZE]; byte cbcIv[MAX_IV_SIZE]; #endif + byte seq[MAX_SEQ_SZ]; + byte shr[MAX_SHORT_SZ]; + word32 maxShr = MAX_SHORT_SZ; + word32 algoSz; + const byte* algoName; (void)heap; @@ -3976,58 +3986,51 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, return BAD_FUNC_ARG; } + /* calculate size */ + /* size of constructed string at end */ + sz = Pkcs8Pad(NULL, inputSz, blockSz); + totalSz = ASN_TAG_SZ; + totalSz += SetLength(sz, seq); + totalSz += sz; + + /* size of sequence holding object id and sub sequence of salt and itt */ + algoName = OidFromId(id, oidPBEType, &algoSz); + if (algoName == NULL) { + WOLFSSL_MSG("Unknown Algorithm"); + return 0; + } + innerSz = SetObjectId(algoSz, seq); + innerSz += algoSz; + + /* get subsequence of salt and itt */ + if (salt == NULL || saltSz == 0) { + sz = 8; + } + else { + sz = saltSz; + } + seqSz = SetOctetString(sz, seq); + seqSz += sz; + + tmpIdx = 0; + seqSz += SetShortInt(shr, &tmpIdx, itt, maxShr); + innerSz += seqSz + SetSequence(seqSz, seq); + totalSz += innerSz + SetSequence(innerSz, seq); + if (out == NULL) { - sz = inputSz; - switch (id) { - #if !defined(NO_DES3) && (!defined(NO_MD5) || !defined(NO_SHA)) - case PBE_MD5_DES: - case PBE_SHA1_DES: - case PBE_SHA1_DES3: - /* set to block size of 8 for DES operations. This rounds up - * to the nearest multiple of 8 */ - sz &= 0xfffffff8; - sz += 8; - break; - #endif /* !NO_DES3 && (!NO_MD5 || !NO_SHA) */ - #if !defined(NO_RC4) && !defined(NO_SHA) - case PBE_SHA1_RC4_128: - break; - #endif - case -1: - break; - - default: - return ALGO_ID_E; - } - - if (saltSz == 0) { - sz += MAX_SALT_SIZE; - } - else { - sz += saltSz; - } - - /* add 2 for tags */ - totalSz = sz + MAX_ALGO_SZ + MAX_SEQ_SZ + MAX_LENGTH_SZ + - MAX_LENGTH_SZ + MAX_LENGTH_SZ + MAX_SHORT_SZ + 2; - - /* adjust size to pad */ - totalSz = Pkcs8Pad(NULL, totalSz, blockSz); - - /* return result */ *outSz = totalSz; - return LENGTH_ONLY_E; } - if (inOutIdx + MAX_ALGO_SZ + MAX_SEQ_SZ + 1 > *outSz) + inOutIdx = 0; + if (totalSz > *outSz) return BUFFER_E; - sz = SetAlgoID(id, out + inOutIdx, oidPBEType, 0); - inOutIdx += sz; totalSz += sz; - tmpIdx = inOutIdx; - tmpIdx += MAX_SEQ_SZ; /* save room for salt and itter sequence */ - out[tmpIdx++] = ASN_OCTET_STRING; + inOutIdx += SetSequence(innerSz, out + inOutIdx); + inOutIdx += SetObjectId(algoSz, out + inOutIdx); + XMEMCPY(out + inOutIdx, algoName, algoSz); + inOutIdx += algoSz; + inOutIdx += SetSequence(seqSz, out + inOutIdx); /* create random salt if one not provided */ if (salt == NULL || saltSz == 0) { @@ -4047,22 +4050,18 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, return ret; } } - - if (tmpIdx + MAX_LENGTH_SZ + saltSz + MAX_SHORT_SZ > *outSz) { + inOutIdx += SetOctetString(saltSz, out + inOutIdx); + if (saltSz + inOutIdx > *outSz) { #ifdef WOLFSSL_SMALL_STACK XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); #endif return BUFFER_E; } - - sz = SetLength(saltSz, out + tmpIdx); - tmpIdx += sz; - - XMEMCPY(out + tmpIdx, salt, saltSz); - tmpIdx += saltSz; + XMEMCPY(out + inOutIdx, salt, saltSz); + inOutIdx += saltSz; /* place iteration setting in buffer */ - ret = SetShortInt(out, &tmpIdx, itt, *outSz); + ret = SetShortInt(out, &inOutIdx, itt, *outSz); if (ret < 0) { #ifdef WOLFSSL_SMALL_STACK XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -4070,13 +4069,27 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, return ret; } - /* rewind and place sequence */ - sz = tmpIdx - inOutIdx - MAX_SEQ_SZ; - seqSz = SetSequence(sz, out + inOutIdx); - XMEMMOVE(out + inOutIdx + seqSz, out + inOutIdx + MAX_SEQ_SZ, sz); - inOutIdx += seqSz; totalSz += seqSz; - inOutIdx += sz; totalSz += sz; + if (inOutIdx + 1 > *outSz) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + out[inOutIdx++] = ASN_CONTEXT_SPECIFIC | 0; + /* get pad size and verify buffer room */ + sz = Pkcs8Pad(NULL, inputSz, blockSz); + if (sz + inOutIdx > *outSz) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + inOutIdx += SetLength(sz, out + inOutIdx); + + /* copy input to output buffer and pad end */ + XMEMCPY(out + inOutIdx, input, inputSz); + sz = Pkcs8Pad(out + inOutIdx, inputSz, blockSz); #ifdef WOLFSSL_SMALL_STACK cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); if (cbcIv == NULL) { @@ -4085,23 +4098,6 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, } #endif - if (inOutIdx + 1 + MAX_LENGTH_SZ + inputSz > *outSz) - return BUFFER_E; - - out[inOutIdx++] = ASN_CONTEXT_SPECIFIC | 0; totalSz++; - sz = SetLength(inputSz, out + inOutIdx); - inOutIdx += sz; totalSz += sz; - - /* get pad size and verify buffer room */ - sz = Pkcs8Pad(NULL, inputSz, blockSz); - if (sz + inOutIdx > *outSz) - return BUFFER_E; - - /* copy input to output buffer and pad end */ - XMEMCPY(out + inOutIdx, input, inputSz); - sz = Pkcs8Pad(out + inOutIdx, inputSz, blockSz); - totalSz += sz; - /* encrypt */ if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id, out + inOutIdx, sz, version, cbcIv, 1, 0)) < 0) { @@ -4120,7 +4116,7 @@ int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, (void)rng; - return totalSz; + return inOutIdx + sz; } diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index 99860fe28..12efd7bcb 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -60,8 +60,8 @@ enum { WC_PKCS12_DATA_OBJ_SZ = 11, }; -/* static const byte WC_PKCS12_ENCRYPTED_OID[] = - {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06}; */ +static const byte WC_PKCS12_ENCRYPTED_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06}; static const byte WC_PKCS12_DATA_OID[] = {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01}; static const byte WC_PKCS12_CertBag_Type1_OID[] = @@ -717,14 +717,37 @@ int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz) /* Create the MAC portion */ if ((ret == 0) && (pkcs12->signData != NULL)) { MacData *mac = (MacData*)pkcs12->signData; - word32 aSz = (2 + (2 + 5) + (2)); - word32 bSz = (2 + mac->digestSz); - word32 cSz = (2 + mac->saltSz); - word32 dSz = (2 + sizeof(short int)); - word32 innerSz = aSz + bSz; - word32 outerSz = 2 + innerSz + cSz + dSz; + word32 innerSz = 0; + word32 outerSz = 0; - sdBufSz = 2 + outerSz; + /* get exact size */ + { + byte ASNLENGTH[MAX_LENGTH_SZ]; + byte ASNSHORT[MAX_SHORT_SZ]; + byte ASNALGO[MAX_ALGO_SZ]; + word32 tmpIdx = 0; + + /* algo id */ + innerSz += SetAlgoID(mac->oid, ASNALGO, oidHashType, 0); + + /* Octet string holding digest */ + innerSz += ASN_TAG_SZ; + innerSz += SetLength(mac->digestSz, ASNLENGTH); + innerSz += mac->digestSz; + + /* salt */ + outerSz += ASN_TAG_SZ; + outerSz += SetLength(mac->saltSz, ASNLENGTH); + outerSz += mac->saltSz; + + /* MAC iterations */ + outerSz += SetShortInt(ASNSHORT, &tmpIdx, mac->itt, MAX_SHORT_SZ); + + /* sequence of inner data */ + outerSz += SetSequence(innerSz, seq); + outerSz += innerSz; + } + sdBufSz = outerSz + SetSequence(outerSz, seq); sdBuf = (byte*)XMALLOC(sdBufSz, pkcs12->heap, DYNAMIC_TYPE_PKCS); if (sdBuf == NULL) { ret = MEMORY_E; @@ -749,15 +772,15 @@ int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz) } if (ret == 0) { + + /* Octet string holding digest */ - sdBuf[idx++] = ASN_OCTET_STRING; - idx += SetLength(mac->digestSz, &sdBuf[idx]); + idx += SetOctetString(mac->digestSz, &sdBuf[idx]); XMEMCPY(&sdBuf[idx], mac->digest, mac->digestSz); idx += mac->digestSz; /* Set salt */ - sdBuf[idx++] = ASN_OCTET_STRING; - idx += SetLength(mac->saltSz, &sdBuf[idx]); + idx += SetOctetString(mac->saltSz, &sdBuf[idx]); XMEMCPY(&sdBuf[idx], mac->salt, mac->saltSz); idx += mac->saltSz; @@ -765,16 +788,16 @@ int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz) { int tmpSz; word32 tmpIdx = 0; - byte ar[MAX_LENGTH_SZ + 2]; - tmpSz = SetShortInt(ar, &tmpIdx, mac->itt, MAX_LENGTH_SZ + 2); + byte ar[MAX_SHORT_SZ]; + tmpSz = SetShortInt(ar, &tmpIdx, mac->itt, MAX_SHORT_SZ); if (tmpSz < 0) { ret = tmpSz; } else { XMEMCPY(&sdBuf[idx], ar, tmpSz); + idx += tmpSz; } } - totalSz += sdBufSz; } } @@ -882,6 +905,7 @@ int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz) return ret; } + /* helper function to free WC_DerCertList */ void wc_FreeCertList(WC_DerCertList* list, void* heap) { @@ -1687,7 +1711,8 @@ static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, word32 length = 0; word32 tmpSz; word32 encSz; - word32 i; + + byte seq[MAX_SEQ_SZ]; WOLFSSL_MSG("encrypting PKCS12 content"); @@ -1701,30 +1726,7 @@ static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, * sequence * get object id */ if (type == WC_PKCS12_ENCRYPTED_DATA) { - if (out == NULL) { - *outSz = 1 + MAX_LENGTH_SZ + MAX_SEQ_SZ + MAX_VERSION_SZ + - MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ; - ret = EncryptContent(NULL, contentSz + MAX_SEQ_SZ, NULL, &encSz, - pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap); - if (ret != LENGTH_ONLY_E) { - return ret; - } - - *outSz += encSz; - return LENGTH_ONLY_E; - } - - if (*outSz < (1 + MAX_LENGTH_SZ + MAX_SEQ_SZ + MAX_VERSION_SZ)) { - return BUFFER_E; - } - out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); totalSz++; - - /* save room for length and sequence */ - idx += MAX_LENGTH_SZ; - idx += MAX_SEQ_SZ; - - tmpSz = SetMyVersion(0, out + idx, 0); - idx += tmpSz; length += tmpSz; + word32 outerSz = 0; encSz = contentSz; if ((ret = EncryptContent(NULL, contentSz, NULL, &encSz, @@ -1734,9 +1736,46 @@ static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, } } - if (*outSz < (idx + MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ + encSz)) { + /* calculate size */ + totalSz = SetObjectId(sizeof(WC_PKCS12_ENCRYPTED_OID), seq); + totalSz += sizeof(WC_PKCS12_ENCRYPTED_OID); + totalSz += ASN_TAG_SZ; + + length = SetMyVersion(0, seq, 0); + tmpSz = SetObjectId(sizeof(WC_PKCS12_DATA_OID), seq); + tmpSz += sizeof(WC_PKCS12_DATA_OID); + tmpSz += encSz; + length += SetSequence(tmpSz, seq) + tmpSz; + outerSz = SetSequence(length, seq) + length; + + totalSz += SetLength(outerSz, seq) + outerSz; + if (out == NULL) { + *outSz = totalSz + SetSequence(totalSz, seq); + return LENGTH_ONLY_E; + } + + if (*outSz < totalSz + SetSequence(totalSz, seq)) { return BUFFER_E; } + + idx = 0; + idx += SetSequence(totalSz, out + idx); + idx += SetObjectId(sizeof(WC_PKCS12_ENCRYPTED_OID), out + idx); + if (idx + sizeof(WC_PKCS12_ENCRYPTED_OID) > *outSz){ + return BUFFER_E; + } + XMEMCPY(out + idx, WC_PKCS12_ENCRYPTED_OID, + sizeof(WC_PKCS12_ENCRYPTED_OID)); + idx += sizeof(WC_PKCS12_ENCRYPTED_OID); + + if (idx + 1 > *outSz){ + return BUFFER_E; + } + out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); + idx += SetLength(outerSz, out + idx); + + idx += SetSequence(length, out + idx); + idx += SetMyVersion(0, out + idx, 0); tmp = (byte*)XMALLOC(encSz, heap, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) { return MEMORY_E; @@ -1760,34 +1799,23 @@ static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, } #endif - tmpSz = SetSequence(WC_PKCS12_DATA_OBJ_SZ + encSz, out + idx); - idx += tmpSz; length += tmpSz; - - out[idx++] = ASN_OBJECT_ID; length++; - tmpSz = SetLength(sizeof(WC_PKCS12_DATA_OID), out + idx); - idx += tmpSz; length += tmpSz; - for (i = 0; i < sizeof(WC_PKCS12_DATA_OID); i++) { - out[idx++] = WC_PKCS12_DATA_OID[i]; length++; + idx += SetSequence(WC_PKCS12_DATA_OBJ_SZ + encSz, out + idx); + idx += SetObjectId(sizeof(WC_PKCS12_DATA_OID), out + idx); + if (idx + sizeof(WC_PKCS12_DATA_OID) > *outSz){ + WOLFSSL_MSG("Buffer not large enough for DATA OID"); + return BUFFER_E; } + XMEMCPY(out + idx, WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID)); + idx += sizeof(WC_PKCS12_DATA_OID); /* copy over encrypted data */ + if (idx + encSz > *outSz){ + return BUFFER_E; + } XMEMCPY(out + idx, tmp, encSz); XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); - idx += encSz; length += encSz; - - /* rewind and place sequence */ - idx -= (length + MAX_SEQ_SZ); - tmpSz = SetSequence(length, out + idx); - XMEMMOVE(out + idx + tmpSz, out + idx + MAX_SEQ_SZ, length); - length += tmpSz; - - /* now place length */ - idx -= MAX_LENGTH_SZ; - tmpSz = SetLength(length, out + idx); - XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length); - totalSz += length + tmpSz; - - return totalSz; + idx += encSz; + return idx; } /* DATA @@ -1797,35 +1825,50 @@ static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, * length * sequence containing all bags */ if (type == WC_PKCS12_DATA) { + /* calculate size */ + totalSz = SetObjectId(sizeof(WC_PKCS12_DATA_OID), seq); + totalSz += sizeof(WC_PKCS12_DATA_OID); + totalSz += ASN_TAG_SZ; + + length = SetOctetString(contentSz, seq); + length += contentSz; + totalSz += SetLength(length, seq); + totalSz += length; + if (out == NULL) { - *outSz = 1 + MAX_LENGTH_SZ + 1 + MAX_LENGTH_SZ + contentSz; + *outSz = totalSz + SetSequence(totalSz, seq); return LENGTH_ONLY_E; } - if (*outSz < (1 + MAX_LENGTH_SZ + 1 + MAX_LENGTH_SZ + contentSz)) { + if (*outSz < (totalSz + SetSequence(totalSz, seq))) { return BUFFER_E; } + /* place data in output buffer */ + idx = 0; + idx += SetSequence(totalSz, out); + idx += SetObjectId(sizeof(WC_PKCS12_DATA_OID), out + idx); + if (idx + sizeof(WC_PKCS12_DATA_OID) > *outSz){ + WOLFSSL_MSG("Buffer not large enough for DATA OID"); + return BUFFER_E; + } + XMEMCPY(out + idx, WC_PKCS12_DATA_OID, sizeof(WC_PKCS12_DATA_OID)); + idx += sizeof(WC_PKCS12_DATA_OID); + + if (idx + 1 > *outSz){ + return BUFFER_E; + } out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); - totalSz++; + idx += SetLength(length, out + idx); + idx += SetOctetString(contentSz, out + idx); - /* save room for length */ - idx += MAX_LENGTH_SZ; - - out[idx++] = ASN_OCTET_STRING; length++; - tmpSz = SetLength(contentSz, out + idx); - idx += tmpSz; length += tmpSz; - - /* sequence containing all bags */ + if (idx + contentSz > *outSz){ + return BUFFER_E; + } XMEMCPY(out + idx, content, contentSz); - idx += contentSz; length += contentSz; + idx += contentSz; - idx -= (MAX_LENGTH_SZ + length); - tmpSz = SetLength(length, out + idx); - XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length); - totalSz += length + tmpSz; - - return totalSz; + return idx; } WOLFSSL_MSG("Unknown/Unsupported content type"); @@ -1833,6 +1876,335 @@ static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, } +/* helper function to create the PKCS12 key content + * keyCiSz is output buffer size + * returns a pointer to be free'd by caller on success and NULL on failure */ +static byte* PKCS12_create_key_content(WC_PKCS12* pkcs12, int nidKey, + word32* keyCiSz, WC_RNG* rng, char* pass, word32 passSz, + byte* key, word32 keySz, int iter) +{ + byte* keyBuf; + word32 keyBufSz = 0; + byte* keyCi = NULL; + word32 tmpSz; + int ret; + int algo; + + void* heap = wc_PKCS12_GetHeap(pkcs12); + + *keyCiSz = 0; + switch (nidKey) { + case PBE_SHA1_RC4_128: + algo = 1; + break; + + case PBE_SHA1_DES: + algo = 2; + break; + + case PBE_SHA1_DES3: + algo = 3; + break; + + /* no encryption */ + case -1: + algo = -1; + break; + + default: + WOLFSSL_MSG("Unknown/Unsupported key encryption"); + return NULL; + } + + /* get max size for key bag */ + ret = wc_PKCS12_create_key_bag(pkcs12, rng, NULL, &keyBufSz, key, keySz, + algo, iter, pass, passSz); + if (ret != LENGTH_ONLY_E && ret < 0) { + WOLFSSL_MSG("Error getting key bag size"); + return NULL; + } + + /* account for sequence around bag */ + keyBufSz += MAX_SEQ_SZ; + keyBuf = (byte*)XMALLOC(keyBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + WOLFSSL_MSG("Memory error creating keyBuf buffer"); + return NULL; + } + + ret = wc_PKCS12_create_key_bag(pkcs12, rng, keyBuf + MAX_SEQ_SZ, &keyBufSz, + key, keySz, algo, iter, pass, passSz); + if (ret < 0) { + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Error creating key bag"); + return NULL; + } + keyBufSz = ret; + + tmpSz = SetSequence(keyBufSz, keyBuf); + XMEMMOVE(keyBuf + tmpSz, keyBuf + MAX_SEQ_SZ, keyBufSz); + keyBufSz += tmpSz; + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + word32 i; + printf("(size %u) Key Bag = ", keyBufSz); + for (i = 0; i < keyBufSz; i++) + printf("%02X", keyBuf[i]); + printf("\n"); + } + #endif + ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, keyCiSz, + NULL, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA); + if (ret != LENGTH_ONLY_E) { + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Error getting key encrypt content size"); + return NULL; + } + keyCi = (byte*)XMALLOC(*keyCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (keyCi == NULL) { + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + ret = wc_PKCS12_encrypt_content(pkcs12, rng, keyCi, keyCiSz, + keyBuf, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA); + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0 ) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Error creating key encrypt content"); + return NULL; + } + *keyCiSz = ret; + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + word32 i; + printf("(size %u) Key Content Info = ", *keyCiSz); + for (i = 0; i < *keyCiSz; i++) + printf("%02X", keyCi[i]); + printf("\n"); + } + #endif + + return keyCi; +} + + +/* helper function to create the PKCS12 certificate content + * certCiSz is output buffer size + * returns a pointer to be free'd by caller on success and NULL on failure */ +static byte* PKCS12_create_cert_content(WC_PKCS12* pkcs12, int nidCert, + WC_DerCertList* ca, byte* cert, word32 certSz, word32* certCiSz, + WC_RNG* rng, char* pass, word32 passSz, int iter) +{ + int algo; + int ret; + int type; + + byte* certBuf = NULL; + word32 certBufSz; + word32 idx; + word32 sz; + word32 tmpSz; + + byte* certCi; + void* heap = wc_PKCS12_GetHeap(pkcs12); + + switch (nidCert) { + case PBE_SHA1_RC4_128: + type = WC_PKCS12_ENCRYPTED_DATA; + algo = 1; + break; + + case PBE_SHA1_DES: + type = WC_PKCS12_ENCRYPTED_DATA; + algo = 2; + break; + + case PBE_SHA1_DES3: + type = WC_PKCS12_ENCRYPTED_DATA; + algo = 3; + break; + + case -1: + type = WC_PKCS12_DATA; + algo = -1; + break; + + default: + WOLFSSL_MSG("Unknown/Unsupported certificate encryption"); + return NULL; + } + + /* get max size of buffer needed */ + ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &certBufSz, cert, certSz); + if (ret != LENGTH_ONLY_E) { + return NULL; + } + + if (ca != NULL) { + WC_DerCertList* current = ca; + word32 curBufSz = 0; + + /* get max buffer size */ + while (current != NULL) { + ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &curBufSz, + current->buffer, current->bufferSz); + if (ret != LENGTH_ONLY_E) { + return NULL; + } + certBufSz += curBufSz; + current = current->next; + } + } + + /* account for Sequence that holds all certificate bags */ + certBufSz += MAX_SEQ_SZ; + + /* completed getting max size, now create buffer and start adding bags */ + certBuf = (byte*)XMALLOC(certBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (certBuf == NULL) { + WOLFSSL_MSG("Memory error creating certificate bags"); + return NULL; + } + + idx = 0; + idx += MAX_SEQ_SZ; + + sz = certBufSz - idx; + if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz, + cert, certSz)) < 0) { + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + idx += ret; + + if (ca != NULL) { + WC_DerCertList* current = ca; + + while (current != NULL) { + sz = certBufSz - idx; + if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz, + current->buffer, current->bufferSz)) < 0) { + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + idx += ret; + current = current->next; + } + } + + /* set sequence and create encrypted content with all certificate bags */ + tmpSz = SetSequence(idx - MAX_SEQ_SZ, certBuf); + XMEMMOVE(certBuf + tmpSz, certBuf + MAX_SEQ_SZ, idx - MAX_SEQ_SZ); + certBufSz = tmpSz + (idx - MAX_SEQ_SZ); + + /* get buffer size needed for content info */ + ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, certCiSz, + NULL, certBufSz, algo, pass, passSz, iter, type); + if (ret != LENGTH_ONLY_E) { + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_LEAVE("wc_PKCS12_create()", ret); + return NULL; + } + certCi = (byte*)XMALLOC(*certCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (certCi == NULL) { + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + ret = wc_PKCS12_encrypt_content(pkcs12, rng, certCi, certCiSz, + certBuf, certBufSz, algo, pass, passSz, iter, type); + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0) { + WOLFSSL_LEAVE("wc_PKCS12_create()", ret); + return NULL; + } + *certCiSz = ret; + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + word32 i; + printf("(size %u) Encrypted Certificate Content Info = ", *certCiSz); + for (i = 0; i < *certCiSz; i++) + printf("%02X", certCi[i]); + printf("\n"); + } + #endif + + return certCi; +} + + +/* helper function to create the PKCS12 safe + * returns 0 on success */ +static int PKCS12_create_safe(WC_PKCS12* pkcs12, byte* certCi, word32 certCiSz, + byte* keyCi, word32 keyCiSz, WC_RNG* rng, char* pass, word32 passSz, + int iter) +{ + int length; + int ret; + byte seq[MAX_SEQ_SZ]; + word32 safeDataSz; + word32 innerDataSz; + byte *innerData = NULL; + byte *safeData = NULL; + word32 idx; + + innerDataSz = certCiSz + keyCiSz+SetSequence(certCiSz + keyCiSz, seq); + + /* add Content Info structs to safe, key first then cert */ + ret = wc_PKCS12_encrypt_content(pkcs12, rng, NULL, &safeDataSz, + NULL, innerDataSz, 0, NULL, 0, 0, WC_PKCS12_DATA); + if (ret != LENGTH_ONLY_E) { + return ret; + } + + safeData = (byte*)XMALLOC(safeDataSz, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (safeData == NULL) { + WOLFSSL_MSG("Error malloc'ing safe data buffer"); + return MEMORY_E; + } + + /* create sequence of inner data */ + innerData = (byte*)XMALLOC(innerDataSz, pkcs12->heap, DYNAMIC_TYPE_PKCS); + if (innerData == NULL) { + WOLFSSL_MSG("Error malloc'ing inner data buffer"); + return MEMORY_E; + } + idx = 0; + idx += SetSequence(certCiSz + keyCiSz, innerData); + XMEMCPY(innerData + idx, certCi, certCiSz); + XMEMCPY(innerData + idx + certCiSz, keyCi, keyCiSz); + + ret = wc_PKCS12_encrypt_content(pkcs12, rng, safeData, &safeDataSz, + innerData, innerDataSz, 0, pass, passSz, iter, WC_PKCS12_DATA); + XFREE(innerData, pkcs12->heap, DYNAMIC_TYPE_PKCS); + if (ret < 0 ) { + WOLFSSL_MSG("Error setting data type for safe contents"); + XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + idx = 0; + + ret = GetSequence(safeData, &idx, &length, safeDataSz); + if (ret < 0) { + WOLFSSL_MSG("Error getting first sequence of safe"); + XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + ret = GetSafeContent(pkcs12, safeData, &idx, safeDataSz); + XFREE(safeData, pkcs12->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0) { + WOLFSSL_MSG("Unable to create safe contents"); + return ret; + } + return 0; +} + + /* * pass : password to use with encryption * passSz : size of the password buffer @@ -1856,27 +2228,15 @@ WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name, byte* key, word32 keySz, byte* cert, word32 certSz, WC_DerCertList* ca, int nidKey, int nidCert, int iter, int macIter, int keyType, void* heap) { - WC_PKCS12* pkcs12; - AuthenticatedSafe* safe; - ContentInfo* ci; - WC_RNG rng; - int algo; + WC_PKCS12* pkcs12; + WC_RNG rng; int ret; - int type; - word32 idx; - word32 sz; - word32 tmpSz; byte* certCi = NULL; + byte* keyCi = NULL; word32 certCiSz; - byte* keyCi; word32 keyCiSz; - byte* certBuf = NULL; - word32 certBufSz; - byte* keyBuf; - word32 keyBufSz = 0; - WOLFSSL_ENTER("wc_PKCS12_create()"); if ((ret = wc_InitRng_ex(&rng, heap, INVALID_DEVID)) != 0) { @@ -1901,320 +2261,35 @@ WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name, } /**** add private key bag ****/ - switch (nidKey) { - case PBE_SHA1_RC4_128: - algo = 1; - break; - - case PBE_SHA1_DES: - algo = 2; - break; - - case PBE_SHA1_DES3: - algo = 3; - break; - - /* no encryption */ - case -1: - algo = -1; - break; - - default: - WOLFSSL_MSG("Unknown/Unsupported key encryption"); - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - return NULL; - } - - /* get max size for key bag */ - ret = wc_PKCS12_create_key_bag(pkcs12, &rng, NULL, &keyBufSz, key, keySz, - algo, iter, pass, passSz); - if (ret != LENGTH_ONLY_E && ret < 0) { - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - WOLFSSL_LEAVE("wc_PKCS12_create", ret); - return NULL; - } - - /* account for sequence around bag */ - keyBufSz += MAX_SEQ_SZ; - - keyBuf = (byte*)XMALLOC(keyBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER); - if (keyBuf == NULL) { - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - WOLFSSL_LEAVE("wc_PKCS12_create", MEMORY_E); - return NULL; - } - - ret = wc_PKCS12_create_key_bag(pkcs12, &rng, keyBuf + MAX_SEQ_SZ, &keyBufSz, - key, keySz, algo, iter, pass, passSz); - if (ret < 0) { - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); - WOLFSSL_LEAVE("wc_PKCS12_create", ret); - return NULL; - } - keyBufSz = ret; - - tmpSz = SetSequence(keyBufSz, keyBuf); - XMEMMOVE(keyBuf + tmpSz, keyBuf + MAX_SEQ_SZ, keyBufSz); - keyBufSz += tmpSz; - - ret = wc_PKCS12_encrypt_content(pkcs12, &rng, NULL, &keyCiSz, - NULL, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA); - if (ret != LENGTH_ONLY_E) { - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); - WOLFSSL_LEAVE("wc_PKCS12_create", ret); - return NULL; - } - keyCi = (byte*)XMALLOC(keyCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + keyCi = PKCS12_create_key_content(pkcs12, nidKey, &keyCiSz, &rng, + pass, passSz, key, keySz, iter); if (keyCi == NULL) { wc_PKCS12_free(pkcs12); wc_FreeRng(&rng); - XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); return NULL; } - ret = wc_PKCS12_encrypt_content(pkcs12, &rng, keyCi, &keyCiSz, - keyBuf, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA); - if (ret < 0 ) { - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - WOLFSSL_LEAVE("wc_PKCS12_create", ret); - return NULL; - } - keyCiSz = ret; - XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); - - #ifdef WOLFSSL_DEBUG_PKCS12 - { - byte* p; - for (printf("(size %u) Key Content Info = ", keyCiSz), p = (byte*)keyCi; - p < (byte*)keyCi + keyCiSz; - printf("%02X", *p), p++); - printf("\n"); - } - #endif - - /**** add main certificate bag and extras ****/ - switch (nidCert) { - case PBE_SHA1_RC4_128: - type = WC_PKCS12_ENCRYPTED_DATA; - algo = 1; - break; - - case PBE_SHA1_DES: - type = WC_PKCS12_ENCRYPTED_DATA; - algo = 2; - break; - - case PBE_SHA1_DES3: - type = WC_PKCS12_ENCRYPTED_DATA; - algo = 3; - break; - - case -1: - type = WC_PKCS12_DATA; - algo = -1; - break; - - default: - WOLFSSL_MSG("Unknown/Unsupported certificate encryption"); - XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - return NULL; - } - - /* get max size of buffer needed */ - ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &certBufSz, cert, certSz); - if (ret != LENGTH_ONLY_E) { - XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - return NULL; - } - - if (ca != NULL) { - WC_DerCertList* current = ca; - word32 curBufSz = 0; - - /* get max buffer size */ - while (current != NULL) { - ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &curBufSz, - current->buffer, current->bufferSz); - if (ret != LENGTH_ONLY_E) { - XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - return NULL; - } - certBufSz += curBufSz; - current = current->next; - } - } - - /* account for Sequence that holds all certificate bags */ - certBufSz += MAX_SEQ_SZ; - - /* completed getting max size, now create buffer and start adding bags */ - certBuf = (byte*)XMALLOC(certBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER); - if (certBuf == NULL) { - XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - WOLFSSL_MSG("Memory error creating certificate bags"); - return NULL; - } - - idx = 0; - idx += MAX_SEQ_SZ; - - sz = certBufSz - idx; - if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz, - cert, certSz)) < 0) { - XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - return NULL; - } - idx += ret; - - if (ca != NULL) { - WC_DerCertList* current = ca; - - while (current != NULL) { - sz = certBufSz - idx; - if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz, - current->buffer, current->bufferSz)) < 0) { - XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - return NULL; - } - idx += ret; - current = current->next; - } - } - - /* set sequence and create encrypted content with all certificate bags */ - tmpSz = SetSequence(idx - MAX_SEQ_SZ, certBuf); - XMEMMOVE(certBuf + tmpSz, certBuf + MAX_SEQ_SZ, idx - MAX_SEQ_SZ); - certBufSz = tmpSz + (idx - MAX_SEQ_SZ); - - /* get buffer size needed for content info */ - ret = wc_PKCS12_encrypt_content(pkcs12, &rng, NULL, &certCiSz, - NULL, certBufSz, algo, pass, passSz, iter, type); - if (ret != LENGTH_ONLY_E) { - XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - WOLFSSL_LEAVE("wc_PKCS12_create()", ret); - return NULL; - } - certCi = (byte*)XMALLOC(certCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + certCi = PKCS12_create_cert_content(pkcs12, nidCert, ca, cert, certSz, + &certCiSz, &rng, pass, passSz, iter); if (certCi == NULL) { XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); wc_PKCS12_free(pkcs12); wc_FreeRng(&rng); return NULL; } - ret = wc_PKCS12_encrypt_content(pkcs12, &rng, certCi, &certCiSz, - certBuf, certBufSz, algo, pass, passSz, iter, type); - if (ret < 0) { - XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - WOLFSSL_LEAVE("wc_PKCS12_create()", ret); - return NULL; - } - certCiSz = ret; - XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); - - #ifdef WOLFSSL_DEBUG_PKCS12 - { - byte* p; - for (printf("(size %u) Encrypted Certificate Content Info = ",certCiSz), - p = (byte*)certCi; - p < (byte*)certCi + certCiSz; - printf("%02X", *p), p++); - printf("\n"); - } - #endif - - /**** create safe and and Content Info ****/ - safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), heap, - DYNAMIC_TYPE_PKCS); - if (safe == NULL) { - XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - return NULL; - } - pkcs12->safe = safe; /* set so all of safe is free'd with wc_PKCS12_free */ - XMEMSET(safe, 0, sizeof(AuthenticatedSafe)); - - safe->dataSz = certCiSz + keyCiSz; - safe->data = (byte*)XMALLOC(safe->dataSz, heap, DYNAMIC_TYPE_PKCS); - if (safe->data == NULL) { - XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - return NULL; - } - XMEMCPY(safe->data, certCi, certCiSz); - XMEMCPY(safe->data + certCiSz, keyCi, keyCiSz); - XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + /**** create safe and Content Info ****/ + ret = PKCS12_create_safe(pkcs12, certCi, certCiSz, keyCi, keyCiSz, &rng, + pass, passSz, iter); XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); - - safe->numCI = 2; - - /* add Content Info structs to safe, key first then cert */ - ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), heap, DYNAMIC_TYPE_PKCS); - if (ci == NULL) { + XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret != 0) { + WOLFSSL_MSG("Unable to create PKCS12 safe"); wc_PKCS12_free(pkcs12); wc_FreeRng(&rng); return NULL; } - XMEMSET(ci, 0, sizeof(ContentInfo)); - safe->CI = ci; - ci->data = safe->data + certCiSz; - ci->dataSz = keyCiSz; - ci->type = WC_PKCS12_DATA; - - ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), heap, DYNAMIC_TYPE_PKCS); - if (ci == NULL) { - wc_PKCS12_free(pkcs12); - wc_FreeRng(&rng); - return NULL; - } - XMEMSET(ci, 0, sizeof(ContentInfo)); - ci->next = safe->CI; - safe->CI = ci; - ci->data = safe->data; - ci->dataSz = certCiSz; - if (nidCert < 0) { - ci->type = WC_PKCS12_DATA; - } - else { - ci->type = WC_PKCS12_ENCRYPTED_DATA; - } /* create MAC */ if (macIter > 0) { @@ -2225,6 +2300,7 @@ WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name, if (mac == NULL) { wc_PKCS12_free(pkcs12); wc_FreeRng(&rng); + WOLFSSL_MSG("Error malloc'ing mac data buffer"); return NULL; } XMEMSET(mac, 0, sizeof(MacData)); @@ -2254,6 +2330,7 @@ WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name, if (mac->salt == NULL) { wc_PKCS12_free(pkcs12); wc_FreeRng(&rng); + WOLFSSL_MSG("Error malloc'ing salt data buffer"); return NULL; } @@ -2263,17 +2340,21 @@ WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name, wc_FreeRng(&rng); return NULL; } - ret = wc_PKCS12_create_mac(pkcs12, safe->data, safe->dataSz, - (const byte*)pass, passSz, digest, WC_MAX_DIGEST_SIZE); + ret = wc_PKCS12_create_mac(pkcs12, pkcs12->safe->data, + pkcs12->safe->dataSz, (const byte*)pass, passSz, digest, + WC_MAX_DIGEST_SIZE); if (ret < 0) { wc_PKCS12_free(pkcs12); wc_FreeRng(&rng); + WOLFSSL_MSG("Error creating mac"); + WOLFSSL_LEAVE("wc_PKCS12_create", ret); return NULL; } mac->digestSz = ret; mac->digest = (byte*)XMALLOC(ret, heap, DYNAMIC_TYPE_PKCS); if (mac->digest == NULL) { + WOLFSSL_MSG("Error malloc'ing mac digest buffer"); wc_PKCS12_free(pkcs12); wc_FreeRng(&rng); return NULL;