diff --git a/tests/api.c b/tests/api.c index a9e9fcd84..df7227682 100644 --- a/tests/api.c +++ b/tests/api.c @@ -29162,6 +29162,20 @@ static void test_wc_i2d_PKCS12(void) XFREE(pt, NULL, DYNAMIC_TYPE_PKCS); wc_PKCS12_free(pkcs12); + /* Run the same test but use wc_d2i_PKCS12_fp. */ + AssertNotNull(pkcs12 = wc_PKCS12_new()); + AssertIntEQ(wc_d2i_PKCS12_fp("./certs/test-servercert.p12", &pkcs12), 0); + AssertIntEQ(wc_i2d_PKCS12(pkcs12, NULL, &outSz), LENGTH_ONLY_E); + AssertIntEQ(outSz, derSz); + wc_PKCS12_free(pkcs12); + + /* wc_d2i_PKCS12_fp can also allocate the PKCS12 object for the caller. */ + pkcs12 = NULL; + AssertIntEQ(wc_d2i_PKCS12_fp("./certs/test-servercert.p12", &pkcs12), 0); + AssertIntEQ(wc_i2d_PKCS12(pkcs12, NULL, &outSz), LENGTH_ONLY_E); + AssertIntEQ(outSz, derSz); + wc_PKCS12_free(pkcs12); + printf(resultFmt, passed); #endif diff --git a/wolfcrypt/src/pkcs12.c b/wolfcrypt/src/pkcs12.c index bb807f928..486e51137 100644 --- a/wolfcrypt/src/pkcs12.c +++ b/wolfcrypt/src/pkcs12.c @@ -707,6 +707,66 @@ int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12) return ret; } +#ifndef NO_FILESYSTEM +/* Parse the DER-encoded PKCS #12 object in the provided file. Populate the + * WC_PKCS12 object pointed to by the passed in pointer, allocating the object + * if necessary. + * + * file : path to PKCS #12 file. + * pkcs12: pointer to a pointer to a WC_PKCS12 object to populate. If *pkcs12 is + * NULL, this function will allocate a new WC_PKCS12. + * return 0 on success and negative on failure. + */ +int wc_d2i_PKCS12_fp(const char* file, WC_PKCS12** pkcs12) +{ + int ret = 0; + byte* buf; + size_t bufSz; + WC_PKCS12* tmpPkcs12 = NULL; + int callerAlloc = 1; + + WOLFSSL_ENTER("wc_d2i_PKCS12_fp"); + + if (pkcs12 == NULL) { + WOLFSSL_MSG("pkcs12 parameter NULL."); + ret = BAD_FUNC_ARG; + } + + ret = wc_FileLoad(file, &buf, &bufSz, NULL); + if (ret == 0) { + if (*pkcs12 == NULL) { + tmpPkcs12 = wc_PKCS12_new(); + if (tmpPkcs12 == NULL) { + WOLFSSL_MSG("Failed to allocate PKCS12 object."); + ret = MEMORY_E; + } + else { + *pkcs12 = tmpPkcs12; + callerAlloc = 0; + } + } + } + if (ret == 0) { + ret = wc_d2i_PKCS12(buf, (word32)bufSz, *pkcs12); + if (ret != 0) { + WOLFSSL_MSG("wc_d2i_PKCS12 failed."); + } + } + + if (ret != 0 && callerAlloc == 0 && *pkcs12 != NULL) { + wc_PKCS12_free(*pkcs12); + *pkcs12 = NULL; + } + if (buf != NULL) { + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + WOLFSSL_LEAVE("wc_d2i_PKCS12_fp", ret); + + return ret; +} +#endif /* NO_FILESYSTEM */ + /* Convert WC_PKCS12 struct to allocated DER buffer. * pkcs12 : non-null pkcs12 pointer * der : pointer-pointer to der buffer. If NULL space will be diff --git a/wolfssl/wolfcrypt/pkcs12.h b/wolfssl/wolfcrypt/pkcs12.h index fa8b331ec..f43124114 100644 --- a/wolfssl/wolfcrypt/pkcs12.h +++ b/wolfssl/wolfcrypt/pkcs12.h @@ -49,6 +49,9 @@ enum { 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); +#ifndef NO_FILESYSTEM +WOLFSSL_API int wc_d2i_PKCS12_fp(const char*, WC_PKCS12**); +#endif WOLFSSL_API int wc_i2d_PKCS12(WC_PKCS12* pkcs12, byte** der, int* derSz); WOLFSSL_API int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, byte** pkey, word32* pkeySz, byte** cert, word32* certSz,