PKCS12 : Add PKCS12 parsing

pull/604/head
Jacob Barthelmeh 2016-10-29 13:12:26 -06:00
parent 7ef037af0f
commit b686deecbe
19 changed files with 2027 additions and 22 deletions

1
.gitignore vendored
View File

@ -146,6 +146,7 @@ mplabx/wolfcrypt_test.X/nbproject/Makefile-*
mplabx/wolfcrypt_test.X/nbproject/Package-default.bash
mplabx/wolfssl.X/nbproject/Makefile-*
mplabx/wolfssl.X/nbproject/Package-default.bash
*.dSYM
# Vagrant folder
.vagrant/

View File

@ -28,7 +28,8 @@ EXTRA_DIST += \
certs/server-keyPkcs8.pem \
certs/server-revoked-cert.pem \
certs/server-revoked-key.pem \
certs/wolfssl-website-ca.pem
certs/wolfssl-website-ca.pem \
certs/test-servercert.p12
EXTRA_DIST += \
certs/ca-key.der \
certs/ca-cert.der \

Binary file not shown.

View File

@ -210,6 +210,7 @@ mkdir -p $RPM_BUILD_ROOT/
%{_includedir}/wolfssl/wolfcrypt/mpi_class.h
%{_includedir}/wolfssl/wolfcrypt/mpi_superclass.h
%{_includedir}/wolfssl/wolfcrypt/pkcs7.h
%{_includedir}/wolfssl/wolfcrypt/pkcs12.h
%{_includedir}/wolfssl/wolfcrypt/wc_port.h
%{_includedir}/wolfssl/wolfcrypt/poly1305.h
%{_includedir}/wolfssl/wolfcrypt/pwdbased.h
@ -274,6 +275,8 @@ mkdir -p $RPM_BUILD_ROOT/
%{_libdir}/pkgconfig/wolfssl.pc
%changelog
* Fri Oct 28 2016 Jacob Barthelmeh <jacob@wolfssl.com>
- Added header for pkcs12
* Fri Sep 23 2016 John Safranek <john@wolfssl.com>
- Add the dtls-sctp example sources
* Mon Jun 14 2016 Jacob Barthelmeh <jacob@wolfssl.com>

View File

@ -153,6 +153,7 @@ endif
if BUILD_PWDBASED
src_libwolfssl_la_SOURCES += wolfcrypt/src/pwdbased.c
src_libwolfssl_la_SOURCES += wolfcrypt/src/pkcs12.c
endif
if BUILD_DSA

407
src/ssl.c
View File

@ -11371,6 +11371,99 @@ byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in,
#endif /* WOLFSSL_SEP */
/* require OPENSSL_EXTRA since wolfSSL_X509_free is wrapped by OPENSSL_EXTRA */
#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
/* return 1 on success 0 on fail */
int wolfSSL_sk_X509_push(STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509)
{
WOLFSSL_STACK* node;
if (sk == NULL || x509 == NULL) {
return 0;
}
/* no previous values in stack */
if (sk->data.x509 == NULL) {
sk->data.x509 = x509;
sk->num += 1;
return 1;
}
/* stack already has value(s) create a new node and add more */
node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL,
DYNAMIC_TYPE_X509);
if (node == NULL) {
WOLFSSL_MSG("Memory error");
return 0;
}
XMEMSET(node, 0, sizeof(WOLFSSL_STACK));
/* push new x509 onto head of stack */
node->data.x509 = sk->data.x509;
node->next = sk->next;
sk->next = node;
sk->data.x509 = x509;
sk->num += 1;
return 1;
}
WOLFSSL_X509* wolfSSL_sk_X509_pop(STACK_OF(WOLFSSL_X509_NAME)* sk) {
WOLFSSL_STACK* node;
WOLFSSL_X509* x509;
if (sk == NULL) {
return NULL;
}
node = sk->next;
x509 = sk->data.x509;
if (node != NULL) { /* update sk and remove node from stack */
sk->data.x509 = node->data.x509;
sk->next = node->next;
XFREE(node, NULL, DYNAMIC_TYPE_X509);
}
else { /* last x509 in stack */
sk->data.x509 = NULL;
}
if (sk->num > 0) {
sk->num -= 1;
}
return x509;
}
/* free structure for x509 stack */
void wolfSSL_sk_X509_free(STACK_OF(WOLFSSL_X509_NAME)* sk) {
WOLFSSL_STACK* node;
if (sk == NULL) {
return;
}
/* parse through stack freeing each node */
node = sk->next;
while (sk->num > 1) {
WOLFSSL_STACK* tmp = node;
node = node->next;
wolfSSL_X509_free(tmp->data.x509);
XFREE(tmp, NULL, DYNAMIC_TYPE_X509);
sk->num -= 1;
}
/* free head of stack */
if (sk->num == 1) {
wolfSSL_X509_free(sk->data.x509);
}
XFREE(sk, NULL, DYNAMIC_TYPE_X509);
}
#endif /* NO_CERTS && OPENSSL_EXTRA */
WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len)
{
@ -12411,6 +12504,320 @@ WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store,
#ifndef NO_CERTS
#if !defined(NO_ASN) && !defined(NO_PWDBASED)
WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12)
{
WC_PKCS12* localPkcs12 = NULL;
const unsigned char* mem = NULL;
int ret;
word32 size;
WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio");
if (bio == NULL) {
WOLFSSL_MSG("Bad Function Argument bio is NULL");
return NULL;
}
localPkcs12 = wc_PKCS12_new();
if (localPkcs12 == NULL) {
WOLFSSL_MSG("Memory error");
return NULL;
}
if (pkcs12 != NULL) {
*pkcs12 = localPkcs12;
}
ret = wolfSSL_BIO_get_mem_data(bio, &mem);
if (mem == NULL || ret <= 0) {
WOLFSSL_MSG("Failed to get data from bio struct");
wc_PKCS12_free(localPkcs12);
if (pkcs12 != NULL) {
*pkcs12 = NULL;
}
return NULL;
}
size = ret;
ret = wc_d2i_PKCS12(mem, size, localPkcs12);
if (ret <= 0) {
WOLFSSL_MSG("Failed to get PKCS12 sequence");
wc_PKCS12_free(localPkcs12);
if (pkcs12 != NULL) {
*pkcs12 = NULL;
}
return NULL;
}
return localPkcs12;
}
/* return 1 on success, 0 on failure */
int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, STACK_OF(WOLFSSL_X509)** ca)
{
DecodedCert DeCert;
int ret;
byte* certData = NULL;
word32 certDataSz;
byte* pk = NULL;
word32 pkSz;
DerCertList* certList = NULL;
WOLFSSL_ENTER("wolfSSL_PKCS12_parse");
if (pkcs12 == NULL || psw == NULL || pkey == NULL || cert == NULL) {
WOLFSSL_MSG("Bad argument value");
return 0;
}
*pkey = NULL;
*cert = NULL;
if (ca == NULL) {
ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
NULL);
}
else {
*ca = NULL;
ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz,
&certList);
}
if (ret < 0) {
WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret);
return 0;
}
/* Decode cert and place in X509 stack struct */
if (certList != NULL) {
DerCertList* current = certList;
*ca = (STACK_OF(WOLFSSL_X509)*)XMALLOC(sizeof(STACK_OF(WOLFSSL_X509)),
pkcs12->heap, DYNAMIC_TYPE_PKCS);
if (*ca == NULL) {
if (pk != NULL) {
XFREE(pk, pkcs12->heap, DYNAMIC_TYPE_PKCS);
}
if (certData != NULL) {
XFREE(*cert, pkcs12->heap, DYNAMIC_TYPE_PKCS); *cert = NULL;
}
/* Free up DerCertList and move on */
while (current != NULL) {
DerCertList* next = current->next;
XFREE(current->buffer, pkcs12->heap, DYNAMIC_TYPE_PKCS);
XFREE(current, pkcs12->heap, DYNAMIC_TYPE_PKCS);
current = next;
}
return 0;
}
XMEMSET(*ca, 0, sizeof(STACK_OF(WOLFSSL_X509)));
/* add list of DER certs as X509's to stack */
while (current != NULL) {
DerCertList* toFree = current;
WOLFSSL_X509* x509;
x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), pkcs12->heap,
DYNAMIC_TYPE_PKCS);
InitX509(x509, 1, pkcs12->heap);
InitDecodedCert(&DeCert, current->buffer, current->bufferSz,
pkcs12->heap);
if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
WOLFSSL_MSG("Issue with parsing certificate");
FreeDecodedCert(&DeCert);
wolfSSL_X509_free(x509);
}
else {
if ((ret = CopyDecodedToX509(x509, &DeCert)) != 0) {
WOLFSSL_MSG("Failed to copy decoded cert");
FreeDecodedCert(&DeCert);
wolfSSL_X509_free(x509);
wolfSSL_sk_X509_free(*ca); *ca = NULL;
if (pk != NULL) {
XFREE(pk, pkcs12->heap, DYNAMIC_TYPE_PKCS);
}
if (certData != NULL) {
XFREE(certData, pkcs12->heap, DYNAMIC_TYPE_PKCS);
}
/* Free up DerCertList */
while (current != NULL) {
DerCertList* next = current->next;
XFREE(current->buffer, pkcs12->heap, DYNAMIC_TYPE_PKCS);
XFREE(current, pkcs12->heap, DYNAMIC_TYPE_PKCS);
current = next;
}
return 0;
}
FreeDecodedCert(&DeCert);
if (wolfSSL_sk_X509_push(*ca, x509) != 1) {
WOLFSSL_MSG("Failed to push x509 onto stack");
wolfSSL_X509_free(x509);
wolfSSL_sk_X509_free(*ca); *ca = NULL;
if (pk != NULL) {
XFREE(pk, pkcs12->heap, DYNAMIC_TYPE_PKCS);
}
if (certData != NULL) {
XFREE(certData, pkcs12->heap, DYNAMIC_TYPE_PKCS);
}
/* Free up DerCertList */
while (current != NULL) {
DerCertList* next = current->next;
XFREE(current->buffer, pkcs12->heap, DYNAMIC_TYPE_PKCS);
XFREE(current, pkcs12->heap, DYNAMIC_TYPE_PKCS);
current = next;
}
return 0;
}
}
current = current->next;
XFREE(toFree->buffer, pkcs12->heap, DYNAMIC_TYPE_PKCS);
XFREE(toFree, pkcs12->heap, DYNAMIC_TYPE_PKCS);
}
}
/* Decode cert and place in X509 struct */
if (certData != NULL) {
*cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), pkcs12->heap,
DYNAMIC_TYPE_PKCS);
if (*cert == NULL) {
if (pk != NULL) {
XFREE(pk, pkcs12->heap, DYNAMIC_TYPE_PKCS);
}
if (ca != NULL) {
wolfSSL_sk_X509_free(*ca); *ca = NULL;
}
XFREE(certData, pkcs12->heap, DYNAMIC_TYPE_PKCS);
return 0;
}
InitX509(*cert, 1, pkcs12->heap);
InitDecodedCert(&DeCert, certData, certDataSz, pkcs12->heap);
if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) {
WOLFSSL_MSG("Issue with parsing certificate");
}
if ((ret = CopyDecodedToX509(*cert, &DeCert)) != 0) {
WOLFSSL_MSG("Failed to copy decoded cert");
FreeDecodedCert(&DeCert);
if (pk != NULL) {
XFREE(pk, pkcs12->heap, DYNAMIC_TYPE_PKCS);
}
if (ca != NULL) {
wolfSSL_sk_X509_free(*ca); *ca = NULL;
}
wolfSSL_X509_free(*cert); *cert = NULL;
return 0;
}
FreeDecodedCert(&DeCert);
XFREE(certData, pkcs12->heap, DYNAMIC_TYPE_PKCS);
}
/* get key type */
ret = BAD_STATE_E;
if (pk != NULL) { /* decode key if present */
*pkey = (WOLFSSL_EVP_PKEY*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY),
pkcs12->heap, DYNAMIC_TYPE_PKCS);
if (*pkey == NULL) {
wolfSSL_X509_free(*cert); *cert = NULL;
if (ca != NULL) {
wolfSSL_sk_X509_free(*ca); *ca = NULL;
}
XFREE(pk, pkcs12->heap, DYNAMIC_TYPE_PKCS);
return 0;
}
#ifndef NO_RSA
{
word32 keyIdx = 0;
RsaKey key;
if (wc_InitRsaKey(&key, pkcs12->heap) != 0) {
ret = BAD_STATE_E;
}
else {
if ((ret = wc_RsaPrivateKeyDecode(pk, &keyIdx, &key, pkSz))
== 0) {
(*pkey)->type = RSAk;
WOLFSSL_MSG("Found PKCS12 RSA key");
}
wc_FreeRsaKey(&key);
}
}
#endif /* NO_RSA */
#ifdef HAVE_ECC
{
word32 keyIdx = 0;
ecc_key key;
if (ret != 0) { /* if is in fail state check if ECC key */
if (wc_ecc_init(&key) != 0) {
wolfSSL_X509_free(*cert); *cert = NULL;
if (ca != NULL) {
wolfSSL_sk_X509_free(*ca); *ca = NULL;
}
XFREE(*pkey, pkcs12->heap, DYNAMIC_TYPE_PKCS); *pkey = NULL;
XFREE(pk, pkcs12->heap, DYNAMIC_TYPE_PKCS);
return 0;
}
if ((ret = wc_EccPrivateKeyDecode(pk, &keyIdx, &key, pkSz))
!= 0) {
wolfSSL_X509_free(*cert); *cert = NULL;
if (ca != NULL) {
wolfSSL_sk_X509_free(*ca); *ca = NULL;
}
XFREE(*pkey, pkcs12->heap, DYNAMIC_TYPE_PKCS); *pkey = NULL;
XFREE(pk, pkcs12->heap, DYNAMIC_TYPE_PKCS);
WOLFSSL_MSG("Bad PKCS12 key format");
return 0;
}
(*pkey)->type = ECDSAk;
(*pkey)->pkey_curve = key.dp->oidSum;
wc_ecc_free(&key);
WOLFSSL_MSG("Found PKCS12 ECC key");
}
}
#else
if (ret != 0) { /* if is in fail state and no ECC then fail */
wolfSSL_X509_free(*cert); *cert = NULL;
if (ca != NULL) {
wolfSSL_sk_X509_free(*ca); *ca = NULL;
}
XFREE(*pkey, pkcs12->heap, DYNAMIC_TYPE_PKCS); *pkey = NULL;
XFREE(pk, pkcs12->heap, DYNAMIC_TYPE_PKCS);
WOLFSSL_MSG("Bad PKCS12 key format");
return 0;
}
#endif /* HAVE_ECC */
(*pkey)->save_type = 0;
(*pkey)->pkey_sz = pkSz;
(*pkey)->pkey.ptr = (char*)pk;
}
(void)ret;
(void)ca;
return 1;
}
#endif /* !defined(NO_ASN) && !defined(NO_PWDBASED) */
/* no-op function. Was initially used for adding encryption algorithms available
* for PKCS12 */
void wolfSSL_PKCS12_PBE_add(void)
{
WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add");
}
int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509)
{
int result = SSL_FATAL_ERROR;

View File

@ -45,6 +45,7 @@
#ifdef OPENSSL_EXTRA
#include <wolfssl/openssl/ssl.h>
#include <wolfssl/openssl/pkcs12.h>
#endif
/* enable testing buffer load functions */
@ -1996,6 +1997,83 @@ static void test_wolfSSL_X509_NAME_get_entry(void)
#endif /* !NO_CERTS */
}
/* Testing functions dealing with PKCS12 parsing out X509 certs */
static void test_wolfSSL_PKCS12(void)
{
/* .p12 file is encrypted with DES3 */
#if defined(OPENSSL_EXTRA) && !defined(NO_DES3) && !defined(NO_FILESYSTEM) && \
!defined(NO_ASN) && !defined(NO_PWDBASED)
byte buffer[5300];
char file[] = "./certs/test-servercert.p12";
FILE *f;
int bytes, ret;
WOLFSSL_BIO *bio;
WOLFSSL_EVP_PKEY *pkey;
WC_PKCS12 *pkcs12;
WOLFSSL_X509 *cert;
WOLFSSL_X509 *tmp;
STACK_OF(WOLFSSL_X509) *ca;
printf(testingFmt, "wolfSSL_PKCS12()");
f = fopen(file, "rb");
AssertNotNull(f);
bytes = (int)fread(buffer, 1, sizeof(buffer), f);
fclose(f);
bio = BIO_new_mem_buf((void*)buffer, bytes);
AssertNotNull(bio);
pkcs12 = d2i_PKCS12_bio(bio, NULL);
AssertNotNull(pkcs12);
PKCS12_free(pkcs12);
d2i_PKCS12_bio(bio, &pkcs12);
AssertNotNull(pkcs12);
/* check verify MAC fail case */
ret = PKCS12_parse(pkcs12, "bad", &pkey, &cert, NULL);
AssertIntEQ(ret, 0);
AssertNull(pkey);
AssertNull(cert);
/* check parse with no extra certs kept */
ret = PKCS12_parse(pkcs12, "wolfSSL test", &pkey, &cert, NULL);
AssertIntEQ(ret, 1);
AssertNotNull(pkey);
AssertNotNull(cert);
wolfSSL_EVP_PKEY_free(pkey);
wolfSSL_X509_free(cert);
/* check parse with extra certs kept */
ret = PKCS12_parse(pkcs12, "wolfSSL test", &pkey, &cert, &ca);
AssertIntEQ(ret, 1);
AssertNotNull(pkey);
AssertNotNull(cert);
AssertNotNull(ca);
/* should be 2 other certs on stack */
tmp = sk_X509_pop(ca);
AssertNotNull(tmp);
X509_free(tmp);
tmp = sk_X509_pop(ca);
AssertNotNull(tmp);
X509_free(tmp);
AssertNull(sk_X509_pop(ca));
EVP_PKEY_free(pkey);
X509_free(cert);
BIO_free(bio);
PKCS12_free(pkcs12);
sk_X509_free(ca);
printf(resultFmt, passed);
#endif /* OPENSSL_EXTRA */
}
/* Testing function wolfSSL_CTX_SetMinVersion; sets the minimum downgrade
* version allowed.
* POST: 1 on success.
@ -2155,6 +2233,7 @@ void ApiTest(void)
/* X509 tests */
test_wolfSSL_X509_NAME_get_entry();
test_wolfSSL_PKCS12();
/*OCSP Stapling. */
AssertIntEQ(test_wolfSSL_UseOCSPStapling(), SSL_SUCCESS);

View File

@ -582,12 +582,15 @@ WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
/* Windows header clash for WinCE using GetVersion */
WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx,
int* version)
int* version, word32 maxIdx)
{
word32 idx = *inOutIdx;
WOLFSSL_ENTER("GetMyVersion");
if (idx + MIN_VERSION_SZ > maxIdx)
return ASN_PARSE_E;
if (input[idx++] != ASN_INTEGER)
return ASN_PARSE_E;
@ -603,13 +606,16 @@ WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx,
#ifndef NO_PWDBASED
/* Get small count integer, 32 bits or less */
static int GetShortInt(const byte* input, word32* inOutIdx, int* number)
int GetShortInt(const byte* input, word32* inOutIdx, int* number, word32 maxIdx)
{
word32 idx = *inOutIdx;
word32 len;
*number = 0;
if (idx + 2 > maxIdx) /*one for type and one for length */
return ASN_PARSE_E;
if (input[idx++] != ASN_INTEGER)
return ASN_PARSE_E;
@ -617,6 +623,9 @@ static int GetShortInt(const byte* input, word32* inOutIdx, int* number)
if (len > 4)
return ASN_PARSE_E;
if (len + idx > maxIdx)
return ASN_PARSE_E;
while (len--) {
*number = *number << 8 | input[idx++];
}
@ -629,14 +638,15 @@ static int GetShortInt(const byte* input, word32* inOutIdx, int* number)
#ifndef NO_ASN_TIME
/* May not have one, not an error */
static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version)
static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version,
word32 maxIdx)
{
word32 idx = *inOutIdx;
WOLFSSL_ENTER("GetExplicitVersion");
if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) {
*inOutIdx = ++idx; /* eat header */
return GetMyVersion(input, inOutIdx, version);
return GetMyVersion(input, inOutIdx, version, maxIdx);
}
/* go back as is */
@ -1365,7 +1375,7 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
if (GetMyVersion(input, inOutIdx, &version) < 0)
if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
return ASN_PARSE_E;
key->type = RSA_PRIVATE;
@ -1393,7 +1403,7 @@ int ToTraditional(byte* input, word32 sz)
if (GetSequence(input, &inOutIdx, &length, sz) < 0)
return ASN_PARSE_E;
if (GetMyVersion(input, &inOutIdx, &version) < 0)
if (GetMyVersion(input, &inOutIdx, &version, sz) < 0)
return ASN_PARSE_E;
if (GetAlgoId(input, &inOutIdx, &oid, oidKeyType, sz) < 0)
@ -1419,6 +1429,108 @@ int ToTraditional(byte* input, word32 sz)
}
/* check that the private key is a pair for the public key in certificate
* return 1 (true) on match
* return 0 or negative value on failure/error
*
* key : buffer holding DER fromat key
* keySz : size of key buffer
* der : a initialized and parsed DecodedCert holding a certificate */
int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der)
{
if (key == NULL || der == NULL) {
return BAD_FUNC_ARG;
}
#if !defined(NO_RSA)
{
RsaKey a, b;
word32 keyIdx = 0;
int ret = 0;
/* test if RSA key */
if (wc_InitRsaKey(&a, NULL) == 0) {
if (wc_RsaPrivateKeyDecode(key, &keyIdx, &a, keySz) == 0 &&
der->keyOID == RSAk) {
WOLFSSL_MSG("Checking RSA key pair");
keyIdx = 0; /* reset to 0 for parsing public key */
if (wc_InitRsaKey(&b, NULL) == 0) {
if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx,
&b, der->pubKeySize)) == 0) {
/* limit for user RSA crypto because of RsaKey
* dereference. */
#if defined(HAVE_USER_RSA)
WOLFSSL_MSG("Cannot verify RSA pair with user RSA");
wc_FreeRsaKey(&b);
wc_FreeRsaKey(&a);
return 1; /* return first RSA cert as match */
#else
/* both keys extracted successfully now check n and e
* values are the same. This is dereferencing RsaKey */
if (mp_cmp(&(a.n), &(b.n)) != MP_EQ ||
mp_cmp(&(a.e), &(b.e)) != MP_EQ) {
ret = MP_CMP_E;
}
else {
/* match found, free keys and return success */
wc_FreeRsaKey(&b);
wc_FreeRsaKey(&a);
return 1;
}
#endif
}
wc_FreeRsaKey(&b);
}
}
wc_FreeRsaKey(&a);
}
/* if ret is not 0 then there was a failed comparision attempt */
if (ret != 0) {
return ret;
}
}
#endif /* NO_RSA */
#ifdef HAVE_ECC
{
int ret = 0;
word32 keyIdx = 0;
ecc_key key_pair;
if ((ret = wc_ecc_init(&key_pair)) == 0) {
if (wc_EccPrivateKeyDecode(key, &keyIdx, &key_pair, keySz) == 0 &&
der->keyOID == ECDSAk) {
WOLFSSL_MSG("Checking ECC key pair");
keyIdx = 0;
if ((ret = wc_ecc_import_x963(der->publicKey, der->pubKeySize,
&key_pair)) == 0) {
/* public and private extracted successfuly no check if is
* a pair and also do sanity checks on key. wc_ecc_check_key
* checks that private * base generator equals pubkey */
if ((ret = wc_ecc_check_key(&key_pair)) == 0) {
/* found a match */
wc_ecc_free(&key_pair);
return 1;
}
}
}
wc_ecc_free(&key_pair);
}
/* error on attempt to match */
if (ret != 0) {
return ret;
}
}
#endif /* HAVE_ECC */
/* no match found */
return 0;
}
#ifndef NO_PWDBASED
/* Check To see if PKCS version algo is supported, set id if it is return 0
@ -1715,7 +1827,7 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz)
XMEMCPY(salt, &input[inOutIdx], saltSz);
inOutIdx += saltSz;
if (GetShortInt(input, &inOutIdx, &iterations) < 0) {
if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
@ -1803,6 +1915,150 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz)
return ToTraditional(input, length);
}
/* decrypt PKCS */
int DecryptContent(byte* input, word32 sz,const char* password,int passwordSz)
{
word32 inOutIdx = 0, oid;
int ret;
int first, second, length, version, saltSz, id;
int iterations = 0;
#ifdef WOLFSSL_SMALL_STACK
byte* salt = NULL;
byte* cbcIv = NULL;
#else
byte salt[MAX_SALT_SIZE];
byte cbcIv[MAX_IV_SIZE];
#endif
if (GetAlgoId(input, &inOutIdx, &oid, oidSigType, sz) < 0)
return ASN_PARSE_E;
first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */
second = input[inOutIdx - 1]; /* version.algo, algo id last byte */
if (CheckAlgo(first, second, &id, &version) < 0)
return ASN_INPUT_E; /* Algo ID error */
if (version == PKCS5v2) {
if (GetSequence(input, &inOutIdx, &length, sz) < 0)
return ASN_PARSE_E;
if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0)
return ASN_PARSE_E;
if (oid != PBKDF2_OID)
return ASN_PARSE_E;
}
if (GetSequence(input, &inOutIdx, &length, sz) < 0)
return ASN_PARSE_E;
if (input[inOutIdx++] != ASN_OCTET_STRING)
return ASN_PARSE_E;
if (GetLength(input, &inOutIdx, &saltSz, sz) < 0)
return ASN_PARSE_E;
if (saltSz > MAX_SALT_SIZE)
return ASN_PARSE_E;
#ifdef WOLFSSL_SMALL_STACK
salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (salt == NULL)
return MEMORY_E;
#endif
XMEMCPY(salt, &input[inOutIdx], saltSz);
inOutIdx += saltSz;
if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ASN_PARSE_E;
}
#ifdef WOLFSSL_SMALL_STACK
cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (cbcIv == NULL) {
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return MEMORY_E;
}
#endif
if (version == PKCS5v2) {
/* get encryption algo */
/* JOHN: New type. Need a little more research. */
if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ASN_PARSE_E;
}
if (CheckAlgoV2(oid, &id) < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ASN_PARSE_E; /* PKCS v2 algo id error */
}
if (input[inOutIdx++] != ASN_OCTET_STRING) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ASN_PARSE_E;
}
if (GetLength(input, &inOutIdx, &length, sz) < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ASN_PARSE_E;
}
XMEMCPY(cbcIv, &input[inOutIdx], length);
inOutIdx += length;
}
if (input[inOutIdx++] != ASN_LONG_LENGTH) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ASN_PARSE_E;
}
if (GetLength(input, &inOutIdx, &length, sz) < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ASN_PARSE_E;
}
if ((ret = DecryptKey(password, passwordSz, salt, saltSz, iterations, id,
input + inOutIdx, length, version, cbcIv)) < 0) {
#ifdef WOLFSSL_SMALL_STACK
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
return ret; /* decrypt failure */
}
#ifdef WOLFSSL_SMALL_STACK
XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER);
#endif
XMEMMOVE(input, input + inOutIdx, length);
return length;
}
#endif /* NO_PWDBASED */
#ifndef NO_RSA
@ -1813,6 +2069,10 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key,
{
int length;
if (input == NULL || inOutIdx == NULL || key == NULL) {
return BAD_FUNC_ARG;
}
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
@ -1995,7 +2255,7 @@ int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key,
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
if (GetMyVersion(input, inOutIdx, &version) < 0)
if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
return ASN_PARSE_E;
if (GetInt(&key->p, input, inOutIdx, inSz) < 0 ||
@ -2320,7 +2580,8 @@ static int GetCertHeader(DecodedCert* cert)
return ASN_PARSE_E;
cert->sigIndex = len + cert->srcIdx;
if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version) < 0)
if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version,
cert->maxIdx) < 0)
return ASN_PARSE_E;
if (GetSerialNumber(cert->source, &cert->srcIdx, cert->serial,
@ -3188,6 +3449,7 @@ static int GetDate(DecodedCert* cert, int dateType)
byte b;
word32 startIdx = 0;
XMEMSET(date, 0, MAX_DATE_SIZE);
if (dateType == BEFORE)
cert->beforeDate = &cert->source[cert->srcIdx];
else
@ -8605,7 +8867,7 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
if (GetMyVersion(input, inOutIdx, &version) < 0)
if (GetMyVersion(input, inOutIdx, &version, inSz) < 0)
return ASN_PARSE_E;
b = input[*inOutIdx];
@ -9161,7 +9423,7 @@ static int DecodeResponseData(byte* source,
if (source[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED))
{
idx += 2; /* Eat the value and length */
if (GetMyVersion(source, &idx, &version) < 0)
if (GetMyVersion(source, &idx, &version, size) < 0)
return ASN_PARSE_E;
} else
version = 0;
@ -9821,7 +10083,7 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm)
/* may have version */
if (buff[idx] == ASN_INTEGER) {
if (GetMyVersion(buff, &idx, &version) < 0)
if (GetMyVersion(buff, &idx, &version, sz) < 0)
return ASN_PARSE_E;
}

File diff suppressed because it is too large Load Diff

View File

@ -735,7 +735,7 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
return ASN_PARSE_E;
/* Get the version */
if (GetMyVersion(pkiMsg, &idx, &version) < 0)
if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (version != 1) {
@ -830,7 +830,7 @@ int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
return ASN_PARSE_E;
/* Get the version */
if (GetMyVersion(pkiMsg, &idx, &version) < 0)
if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (version != 1) {
@ -1530,7 +1530,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (GetMyVersion(pkiMsg, &idx, &version) < 0)
if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (version != 0) {
@ -1563,7 +1563,7 @@ WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
break;
}
if (GetMyVersion(pkiMsg, &idx, &version) < 0) {
if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) {
idx = savedIdx;
break;
}

View File

@ -259,6 +259,10 @@
RelativePath=".\wolfcrypt\src\pkcs7.c"
>
</File>
<File
RelativePath=".\wolfcrypt\src\pkcs12.c"
>
</File>
<File
RelativePath=".\wolfcrypt\src\poly1305.c"
>

View File

@ -305,6 +305,7 @@
<ClCompile Include="wolfcrypt\src\md5.c" />
<ClCompile Include="wolfcrypt\src\memory.c" />
<ClCompile Include="wolfcrypt\src\pkcs7.c" />
<ClCompile Include="wolfcrypt\src\pkcs12.c" />
<ClCompile Include="wolfcrypt\src\poly1305.c" />
<ClCompile Include="wolfcrypt\src\pwdbased.c" />
<ClCompile Include="wolfcrypt\src\rabbit.c" />

View File

@ -45,6 +45,7 @@
#endif
#ifndef NO_ASN
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/pkcs12.h>
#endif
#ifndef NO_MD5
#include <wolfssl/wolfcrypt/md5.h>
@ -2485,6 +2486,17 @@ typedef struct Arrays {
#define MAX_DATE_SZ 32
#endif
typedef struct WOLFSSL_STACK {
unsigned long num; /* number of nodes in stack
* (saftey measure for freeing and shortcut for count) */
union {
WOLFSSL_X509* x509;
WOLFSSL_BIO* bio;
} data;
WOLFSSL_STACK* next;
} WOLFSSL_STACK;
struct WOLFSSL_X509_NAME {
char *name;
char staticName[ASN_NAME_MAX];

View File

@ -1,2 +1,14 @@
/* pkcs12.h for openssl */
#include <wolfssl/wolfcrypt/pkcs12.h>
/* wolfCrypt level does not make use of ssl.h */
#define PKCS12 WC_PKCS12
#define PKCS12_new wc_PKCS12_new
#define PKCS12_free wc_PKCS12_free
/* wolfSSL level using structs from ssl.h and calls down to wolfCrypt */
#define d2i_PKCS12_bio wolfSSL_d2i_PKCS12_bio
#define PKCS12_parse wolfSSL_PKCS12_parse
#define PKCS12_PBE_add wolfSSL_PKCS12_PBE_add

View File

@ -398,6 +398,8 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX;
#define sk_num wolfSSL_sk_num
#define sk_value wolfSSL_sk_value
#define sk_X509_pop wolfSSL_sk_X509_pop
#define sk_X509_free wolfSSL_sk_X509_free
#define SSL_CTX_get_ex_data wolfSSL_CTX_get_ex_data
#define SSL_CTX_set_ex_data wolfSSL_CTX_set_ex_data

View File

@ -70,6 +70,7 @@ typedef struct WOLFSSL_SESSION WOLFSSL_SESSION;
typedef struct WOLFSSL_METHOD WOLFSSL_METHOD;
typedef struct WOLFSSL_CTX WOLFSSL_CTX;
typedef struct WOLFSSL_STACK WOLFSSL_STACK;
typedef struct WOLFSSL_X509 WOLFSSL_X509;
typedef struct WOLFSSL_X509_NAME WOLFSSL_X509_NAME;
typedef struct WOLFSSL_X509_NAME_ENTRY WOLFSSL_X509_NAME_ENTRY;
@ -422,7 +423,11 @@ WOLFSSL_API const char* wolfSSL_ERR_reason_error_string(unsigned long);
/* extras */
#define STACK_OF(x) x
#define STACK_OF(x) WOLFSSL_STACK
WOLFSSL_API int wolfSSL_sk_X509_push(STACK_OF(WOLFSSL_X509_NAME)* sk,
WOLFSSL_X509* x509);
WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_pop(STACK_OF(WOLFSSL_X509_NAME)* sk);
WOLFSSL_API void wolfSSL_sk_X509_free(STACK_OF(WOLFSSL_X509_NAME)* sk);
WOLFSSL_API int wolfSSL_set_ex_data(WOLFSSL*, int, void*);
WOLFSSL_API int wolfSSL_get_shutdown(const WOLFSSL*);
@ -982,6 +987,18 @@ WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer(
/* connect enough to get peer cert */
WOLFSSL_API int wolfSSL_connect_cert(WOLFSSL* ssl);
/* PKCS12 compatibility */
typedef struct WC_PKCS12 WC_PKCS12;
WOLFSSL_API WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio,
WC_PKCS12** pkcs12);
WOLFSSL_API int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, STACK_OF(WOLFSSL_X509)** ca);
WOLFSSL_API void wolfSSL_PKCS12_PBE_add(void);
#ifndef NO_DH
/* server Diffie-Hellman parameters */
WOLFSSL_API int wolfSSL_SetTmpDH(WOLFSSL*, const unsigned char* p, int pSz,
@ -1778,8 +1795,9 @@ WOLFSSL_API char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* time,
char* buf, int len);
#endif /* WOLFSSL_MYSQL_COMPATIBLE */
#ifdef OPENSSL_EXTRA /*lighttp compatibility */
#ifdef OPENSSL_EXTRA
/*lighttp compatibility */
#include <wolfssl/openssl/asn1.h>
struct WOLFSSL_X509_NAME_ENTRY {
WOLFSSL_ASN1_OBJECT* object; /* not defined yet */

View File

@ -195,7 +195,8 @@ enum Misc_ASN {
MAX_PUBLIC_KEY_SZ = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2,
/* use bigger NTRU size */
HEADER_ENCRYPTED_KEY_SIZE = 88,/* Extra header size for encrypted key */
TRAILING_ZERO = 1 /* Used for size of zero pad */
TRAILING_ZERO = 1, /* Used for size of zero pad */
MIN_VERSION_SZ = 3 /* Min bytes needed for GetMyVersion */
};
@ -633,6 +634,7 @@ WOLFSSL_LOCAL void FreeTrustedPeerTable(TrustedPeerCert**, int, void*);
WOLFSSL_LOCAL int ToTraditional(byte* buffer, word32 length);
WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*,int);
WOLFSSL_LOCAL int DecryptContent(byte* input, word32 sz,const char* psw,int pswSz);
typedef struct tm wolfssl_tm;
#if defined(WOLFSSL_MYSQL_COMPATIBLE)
@ -646,6 +648,8 @@ WOLFSSL_LOCAL int ValidateDate(const byte* date, byte format, int dateType);
#ifdef WOLFSSL_CERT_GEN
WOLFSSL_TEST_API int SetName(byte* output, word32 outputSz, CertName* name);
#endif
WOLFSSL_LOCAL int GetShortInt(const byte* input, word32* inOutIdx, int* number,
word32 maxIdx);
WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx);
WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
@ -653,7 +657,7 @@ WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx);
WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx,
int* version);
int* version, word32 maxIdx);
WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx,
word32 maxIdx);
#ifdef HAVE_OID_ENCODING
@ -681,6 +685,7 @@ WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx,
byte* serial, int* serialSz, word32 maxIdx);
WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
int maxIdx);
WOLFSSL_LOCAL int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der);
#ifdef HAVE_ECC
/* ASN sig helpers */

View File

@ -57,7 +57,8 @@ nobase_include_HEADERS+= \
wolfssl/wolfcrypt/mpi_class.h \
wolfssl/wolfcrypt/mpi_superclass.h \
wolfssl/wolfcrypt/mem_track.h \
wolfssl/wolfcrypt/wolfevent.h
wolfssl/wolfcrypt/wolfevent.h \
wolfssl/wolfcrypt/pkcs12.h
noinst_HEADERS+= \
wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \

View File

@ -0,0 +1,114 @@
/* pkcs12.h
*
* Copyright (C) 2006-2016 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#ifndef WOLF_CRYPT_PKCS12_H
#define WOLF_CRYPT_PKCS12_H
#include <wolfssl/wolfcrypt/types.h>
#ifdef __cplusplus
extern "C" {
#endif
enum {
WC_PKCS12_KeyBag = 667,
WC_PKCS12_ShroudedKeyBag = 668,
WC_PKCS12_CertBag = 669,
WC_PKCS12_CertBag_Type1 = 675,
WC_PKCS12_CrlBag = 670,
WC_PKCS12_SecretBag = 671,
WC_PKCS12_SafeContentsBag = 672,
WC_PKCS12_DATA = 651,
WC_PKCS12_ENCRYPTED_DATA = 656,
};
typedef struct DerCertList DerCertList;
typedef struct DerCertList {
byte* buffer;
word32 bufferSz;
DerCertList* next;
} DerCertList;
typedef struct ContentInfo ContentInfo;
typedef struct ContentInfo {
byte* data;
ContentInfo* next;
word32 encC; /* encryptedContent */
word32 dataSz;
int type; /* DATA / encrypted / envelpoed */
} ContentInfo;
typedef struct AuthenticatedSafe {
ContentInfo* CI;
byte* data; /* T contents.... */
word32 oid; /* encrypted or not */
word32 numCI; /* number of Content Info structs */
word32 dataSz;
} AuthenticatedSafe;
typedef struct MacData {
byte* digest;
byte* salt;
word32 oid;
word32 digestSz;
word32 saltSz;
int itt; /* number of itterations when creating HMAC key */
} MacData;
/* for friendlyName, localKeyId .... */
typedef struct WC_PKCS12_ATTRIBUTE {
byte* data;
word32 oid;
word32 dataSz;
} WC_PKCS12_ATTRIBUTE;
typedef struct WC_PKCS12 {
void* heap;
AuthenticatedSafe* safe;
MacData* signData;
word32 oid; /* DATA / Enveloped DATA ... */
} WC_PKCS12;
WOLFSSL_API WC_PKCS12* wc_PKCS12_new(void);
WOLFSSL_API void wc_PKCS12_free(WC_PKCS12* pkcs12);
WOLFSSL_API int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12);
WOLFSSL_API int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw,
byte** pkey, word32* pkeySz, byte** cert, word32* certSz,
DerCertList** ca);
WOLFSSL_LOCAL int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* WOLF_CRYPT_PKCS12_H */