From 6764e7c15ff1313183a2e4684f2b52afff765807 Mon Sep 17 00:00:00 2001 From: Hayden Roche Date: Thu, 9 Dec 2021 15:45:03 -0800 Subject: [PATCH] Make wolfCrypt ASN cert parsing functionality public. Currently, the `ParseCert` function is only available if `WOLFSSL_ASN_API` is defined to `WOLFSSL_API`. The only way to achieve this without enabling the compatibility layer is to define `WOLFSSL_TEST_CERT`. There are users defining this so that they can parse certs with wolfCrypt, even though this doesn't seem to be the original intent of the define. This commit adds the function `wc_ParseCert` to the public wolfCrypt API. It's simply a wrapper around `ParseCert`. Similarly, this commit adds `wc_InitDecodedCert` and `wc_FreeDecodedCert` to the public API, which are wrappers around `InitDecodedCert` and `FreeDecodedCert`, respectively. --- doc/dox_comments/header_files/asn_public.h | 94 ++++++++++++++++++++++ tests/api.c | 18 +++++ wolfcrypt/src/asn.c | 16 ++++ wolfssl/wolfcrypt/asn_public.h | 6 ++ 4 files changed, 134 insertions(+) diff --git a/doc/dox_comments/header_files/asn_public.h b/doc/dox_comments/header_files/asn_public.h index fcdc7fcea..fe6903ba9 100644 --- a/doc/dox_comments/header_files/asn_public.h +++ b/doc/dox_comments/header_files/asn_public.h @@ -1767,3 +1767,97 @@ WOLFSSL_API int wc_CreateEncryptedPKCS8Key(byte* key, word32 keySz, byte* out, word32* outSz, const char* password, int passwordSz, int vPKCS, int pbeOid, int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap); + +/*! + \ingroup ASN + + \brief This function initializes the DecodedCert pointed to by the "cert" + parameter. It saves the "source" pointer to a DER-encoded certificate of + length "inSz." This certificate can be parsed by a subsequent call to + wc_ParseCert. + + \param cert Pointer to an allocated DecodedCert object. + \param source Pointer to a DER-encoded certificate. + \param inSz Length of the DER-encoded certificate in bytes. + \param heap A pointer to the heap used for dynamic allocation. Can be NULL. + + _Example_ + \code + DecodedCert decodedCert; // Decoded certificate object. + byte* certBuf; // DER-encoded certificate buffer. + word32 certBufSz; // Size of certBuf in bytes. + + wc_InitDecodedCert(&decodedCert, certBuf, certBufSz, NULL); + \endcode + + \sa wc_ParseCert + \sa wc_FreeDecodedCert +*/ +WOLFSSL_API void wc_InitDecodedCert(struct DecodedCert* cert, + const byte* source, word32 inSz, void* heap); + +/*! + \ingroup ASN + + \brief This function parses the DER-encoded certificate saved in the + DecodedCert object and populates the fields of that object. The DecodedCert + must have been initialized with a prior call to wc_InitDecodedCert. This + function takes an optional pointer to a CertificateManager object, which + is used to populate the certificate authority information of the + DecodedCert, if the CA is found in the CertificateManager. + + \return 0 on success. + \return Other negative values on failure. + + \param cert Pointer to an initialized DecodedCert object. + \param type Type of certificate. See the CertType enum in asn_public.h. + \param verify Flag that, if set, indicates the user wants to verify the + validity of the certificate. + \param cm An optional pointer to a CertificateManager. Can be NULL. + + _Example_ + \code + int ret; + DecodedCert decodedCert; // Decoded certificate object. + byte* certBuf; // DER-encoded certificate buffer. + word32 certBufSz; // Size of certBuf in bytes. + + wc_InitDecodedCert(&decodedCert, certBuf, certBufSz, NULL); + ret = wc_ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + fprintf(stderr, "wc_ParseCert failed.\n"); + } + \endcode + + \sa wc_InitDecodedCert + \sa wc_FreeDecodedCert +*/ +WOLFSSL_API int wc_ParseCert(DecodedCert* cert, int type, int verify, void* cm); + +/*! + \ingroup ASN + + \brief This function frees a DecodedCert that was previously initialized + with wc_InitDecodedCert. + + \param cert Pointer to an initialized DecodedCert object. + + _Example_ + \code + int ret; + DecodedCert decodedCert; // Decoded certificate object. + byte* certBuf; // DER-encoded certificate buffer. + word32 certBufSz; // Size of certBuf in bytes. + + wc_InitDecodedCert(&decodedCert, certBuf, certBufSz, NULL); + ret = wc_ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL); + if (ret != 0) { + fprintf(stderr, "wc_ParseCert failed.\n"); + } + wc_FreeDecodedCert(&decodedCert); + \endcode + + \sa wc_InitDecodedCert + \sa wc_ParseCert +*/ +WOLFSSL_API void wc_FreeDecodedCert(struct DecodedCert* cert); diff --git a/tests/api.c b/tests/api.c index 83ed95772..b2d327ce5 100644 --- a/tests/api.c +++ b/tests/api.c @@ -45710,6 +45710,23 @@ static void test_CheckCertSignature(void) #endif } +static void test_wc_ParseCert(void) +{ +#if !defined(NO_CERTS) && !defined(NO_RSA) + DecodedCert decodedCert; + const byte* rawCert = client_cert_der_2048; + const int rawCertSize = sizeof_client_cert_der_2048; + + printf(testingFmt, "wc_ParseCert"); + + wc_InitDecodedCert(&decodedCert, rawCert, rawCertSize, NULL); + AssertIntEQ(wc_ParseCert(&decodedCert, CERT_TYPE, NO_VERIFY, NULL), 0); + wc_FreeDecodedCert(&decodedCert); + + printf(resultFmt, passed); +#endif +} + /*----------------------------------------------------------------------------* | wolfCrypt ECC *----------------------------------------------------------------------------*/ @@ -52280,6 +52297,7 @@ void ApiTest(void) test_wc_SetSubjectKeyId(); test_wc_SetSubject(); test_CheckCertSignature(); + test_wc_ParseCert(); /* wolfCrypt ECC tests */ test_wc_ecc_get_curve_size_from_name(); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index c7d8581c5..6a9080eec 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -9513,6 +9513,12 @@ void InitDecodedCert(DecodedCert* cert, } } +void wc_InitDecodedCert(DecodedCert* cert, const byte* source, word32 inSz, + void* heap) +{ + InitDecodedCert(cert, source, inSz, heap); +} + /* Free the alternative names object. * * Frees each linked list items and its name. @@ -9617,6 +9623,11 @@ void FreeDecodedCert(DecodedCert* cert) #endif } +void wc_FreeDecodedCert(DecodedCert* cert) +{ + FreeDecodedCert(cert); +} + #ifndef WOLFSSL_ASN_TEMPLATE static int GetCertHeader(DecodedCert* cert) { @@ -17267,6 +17278,11 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) return ret; } +int wc_ParseCert(DecodedCert* cert, int type, int verify, void* cm) +{ + return ParseCert(cert, type, verify, cm); +} + #if !defined(OPENSSL_EXTRA) && !defined(OPENSSL_EXTRA_X509_SMALL) && \ !defined(GetCA) /* from SSL proper, for locking can't do find here anymore. diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index e56453de8..00c58dcd2 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -759,6 +759,12 @@ typedef struct _wc_CertPIV { WOLFSSL_API int wc_ParseCertPIV(wc_CertPIV* cert, const byte* buf, word32 totalSz); #endif /* WOLFSSL_CERT_PIV */ +/* Forward declaration needed, as DecodedCert is defined in asn.h.*/ +struct DecodedCert; + +WOLFSSL_API void wc_InitDecodedCert(struct DecodedCert*, const byte*, word32, void*); +WOLFSSL_API void wc_FreeDecodedCert(struct DecodedCert*); +WOLFSSL_API int wc_ParseCert(struct DecodedCert*, int, int, void*); #ifdef __cplusplus } /* extern "C" */