From e8c3e8dd63c844ff64da5fa464f2d2d1f9400605 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Thu, 28 Feb 2019 15:07:38 -0600 Subject: [PATCH 1/3] Decoded cert cache feature --- configure.ac | 14 + doc/dox_comments/header_files/asn_public.h | 32 + wolfcrypt/src/asn.c | 655 +++++++++++---------- wolfcrypt/test/test.c | 128 ++++ wolfssl/wolfcrypt/asn_public.h | 10 +- 5 files changed, 526 insertions(+), 313 deletions(-) diff --git a/configure.ac b/configure.ac index f09f20d9b..d59f73bea 100644 --- a/configure.ac +++ b/configure.ac @@ -1376,6 +1376,19 @@ then fi +# DECODED CERT CACHE +AC_ARG_ENABLE([certgencache], + [AS_HELP_STRING([--enable-certgencache],[Enable decoded cert caching (default: disabled)])], + [ ENABLED_certgencache=$enableval ], + [ ENABLED_certgencache=no ] + ) + +if test "$ENABLED_certgencache" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CERT_GEN_CACHE" +fi + + # SEP AC_ARG_ENABLE([sep], [AS_HELP_STRING([--enable-sep],[Enable sep extensions (default: disabled)])], @@ -4864,6 +4877,7 @@ echo " * keygen: $ENABLED_KEYGEN" echo " * certgen: $ENABLED_CERTGEN" echo " * certreq: $ENABLED_CERTREQ" echo " * certext: $ENABLED_CERTEXT" +echo " * certgencache: $ENABLED_certgencache" echo " * HC-128: $ENABLED_HC128" echo " * RABBIT: $ENABLED_RABBIT" echo " * CHACHA: $ENABLED_CHACHA" diff --git a/doc/dox_comments/header_files/asn_public.h b/doc/dox_comments/header_files/asn_public.h index b7943a849..d43180941 100644 --- a/doc/dox_comments/header_files/asn_public.h +++ b/doc/dox_comments/header_files/asn_public.h @@ -1597,3 +1597,35 @@ WOLFSSL_API word32 wc_EncodeSignature(byte* out, const byte* digest, \sa none */ WOLFSSL_API int wc_GetCTC_HashOID(int type); + +/*! + \ingroup ASN + + \brief This function cleans up memory and resources used by the certificate + structure's decoded cert cache. When WOLFSSL_CERT_GEN_CACHE is defined the + decoded cert structure is cached in the certificate structure. This allows + subsequent calls to certificate set functions to avoid parsing the decoded + cert on each call. + + \return 0 on success. + \return BAD_FUNC_ARG Returned if invalid pointer is passed in as argument. + + \param cert pointer to an uninitialized certificate information structure. + + _Example_ + \code + Cert cert; // Initialized certificate structure + + wc_SetCert_Free(&cert); + \endcode + + \sa wc_SetAuthKeyIdFromCert + \sa wc_SetIssuerBuffer + \sa wc_SetSubjectBuffer + \sa wc_SetSubjectRaw + \sa wc_SetIssuerRaw + \sa wc_SetAltNamesBuffer + \sa wc_SetDatesBuffer +*/ +WOLFSSL_API void wc_SetCert_Free(Cert* cert); + diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 82db202bd..ef76a0823 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -9924,6 +9924,62 @@ static word32 SetUTF8String(word32 len, byte* output) #endif /* WOLFSSL_CERT_REQ */ + +#ifndef WOLFSSL_CERT_GEN_CACHE +/* wc_SetCert_Free is only public when WOLFSSL_CERT_GEN_CACHE is not defined */ +static +#endif +void wc_SetCert_Free(Cert* cert) +{ + if (cert != NULL) { + + if (cert->der != NULL) { + cert->der = NULL; + } + + if (cert->decodedCert) { + FreeDecodedCert((DecodedCert*)cert->decodedCert); + + XFREE(cert->decodedCert, cert->heap, DYNAMIC_TYPE_DCERT); + cert->decodedCert = NULL; + } + } +} + +static int wc_SetCert_LoadDer(Cert* cert, const byte* der, word32 derSz) +{ + int ret; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Allocate DecodedCert struct and Zero */ + cert->decodedCert = (void*)XMALLOC(sizeof(DecodedCert), cert->heap, + DYNAMIC_TYPE_DCERT); + + if (cert->decodedCert == NULL) { + ret = MEMORY_E; + } + else { + XMEMSET(cert->decodedCert, 0, sizeof(DecodedCert)); + + InitDecodedCert((DecodedCert*)cert->decodedCert, der, derSz, + cert->heap); + ret = ParseCertRelative((DecodedCert*)cert->decodedCert, + CERT_TYPE, 0, NULL); + if (ret >= 0) { + cert->der = (byte*)der; + } + else { + wc_SetCert_Free(cert); + } + } + } + + return ret; +} + #endif /* WOLFSSL_CERT_GEN */ @@ -12453,66 +12509,53 @@ int wc_SetSubjectKeyId(Cert *cert, const char* file) #endif /* !NO_FILESYSTEM && !NO_ASN_CRYPT */ -/* Set AKID from certificate contains in buffer (DER encoded) */ -int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz) +static int SetAuthKeyIdFromDcert(Cert* cert, DecodedCert* decoded) { - int ret; - -#ifdef WOLFSSL_SMALL_STACK - DecodedCert* decoded; -#else - DecodedCert decoded[1]; -#endif - - if (cert == NULL || der == NULL || derSz <= 0) - return BAD_FUNC_ARG; - -#ifdef WOLFSSL_SMALL_STACK - decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), - cert->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (decoded == NULL) - return MEMORY_E; -#endif - - /* decode certificate and get SKID that will be AKID of current cert */ - InitDecodedCert(decoded, der, derSz, NULL); - ret = ParseCert(decoded, CERT_TYPE, NO_VERIFY, 0); - if (ret != 0) { - FreeDecodedCert(decoded); - #ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ret; - } + int ret = 0; /* Subject Key Id not found !! */ if (decoded->extSubjKeyIdSet == 0) { - FreeDecodedCert(decoded); - #ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return ASN_NO_SKID; + ret = ASN_NO_SKID; } /* SKID invalid size */ - if (sizeof(cert->akid) < sizeof(decoded->extSubjKeyId)) { - FreeDecodedCert(decoded); - #ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif - return MEMORY_E; + else if (sizeof(cert->akid) < sizeof(decoded->extSubjKeyId)) { + ret = MEMORY_E; } - /* Put the SKID of CA to AKID of certificate */ - XMEMCPY(cert->akid, decoded->extSubjKeyId, KEYID_SIZE); - cert->akidSz = KEYID_SIZE; + else { + /* Put the SKID of CA to AKID of certificate */ + XMEMCPY(cert->akid, decoded->extSubjKeyId, KEYID_SIZE); + cert->akidSz = KEYID_SIZE; + } - FreeDecodedCert(decoded); - #ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif + return ret; +} - return 0; +/* Set AKID from certificate contains in buffer (DER encoded) */ +int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + ret = SetAuthKeyIdFromDcert(cert, cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return ret; } @@ -12699,33 +12742,11 @@ int wc_SetExtKeyUsageOID(Cert *cert, const char *in, word32 sz, byte idx, #ifdef WOLFSSL_ALT_NAMES -/* Set Alt Names from der cert, return 0 on success */ -static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) +static int SetAltNamesFromDcert(Cert* cert, DecodedCert* decoded) { - int ret; -#ifdef WOLFSSL_SMALL_STACK - DecodedCert* decoded; -#else - DecodedCert decoded[1]; -#endif + int ret = 0; - if (derSz < 0) - return derSz; - -#ifdef WOLFSSL_SMALL_STACK - decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cert->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (decoded == NULL) - return MEMORY_E; -#endif - - InitDecodedCert(decoded, der, derSz, NULL); - ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); - - if (ret < 0) { - WOLFSSL_MSG("ParseCertRelative error"); - } - else if (decoded->extensions) { + if (decoded->extensions) { byte b; int length; word32 maxExtensionsIdx; @@ -12785,17 +12806,11 @@ static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) } } - FreeDecodedCert(decoded); -#ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret < 0 ? ret : 0; + return ret; } - -/* Set Dates from der cert, return 0 on success */ -static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) +/* Set Alt Names from der cert, return 0 on success */ +static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) { int ret; #ifdef WOLFSSL_SMALL_STACK @@ -12804,7 +12819,6 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) DecodedCert decoded[1]; #endif - WOLFSSL_ENTER("SetDatesFromCert"); if (derSz < 0) return derSz; @@ -12821,7 +12835,23 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) if (ret < 0) { WOLFSSL_MSG("ParseCertRelative error"); } - else if (decoded->beforeDate == NULL || decoded->afterDate == NULL) { + else { + ret = SetAltNamesFromDcert(cert, decoded); + } + + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret < 0 ? ret : 0; +} + +static int SetDatesFromDcert(Cert* cert, DecodedCert* decoded) +{ + int ret = 0; + + if (decoded->beforeDate == NULL || decoded->afterDate == NULL) { WOLFSSL_MSG("Couldn't extract dates"); ret = -1; } @@ -12838,21 +12868,106 @@ static int SetDatesFromCert(Cert* cert, const byte* der, int derSz) cert->afterDateSz = decoded->afterDateLen; } - FreeDecodedCert(decoded); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret < 0 ? ret : 0; + return ret; } #endif /* WOLFSSL_ALT_NAMES */ +static void SetNameFromDcert(CertName* cn, DecodedCert* decoded) +{ + int sz; + + if (decoded->subjectCN) { + sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->commonName, decoded->subjectCN, CTC_NAME_SIZE); + cn->commonName[sz] = '\0'; + cn->commonNameEnc = decoded->subjectCNEnc; + } + if (decoded->subjectC) { + sz = (decoded->subjectCLen < CTC_NAME_SIZE) ? decoded->subjectCLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->country, decoded->subjectC, CTC_NAME_SIZE); + cn->country[sz] = '\0'; + cn->countryEnc = decoded->subjectCEnc; + } + if (decoded->subjectST) { + sz = (decoded->subjectSTLen < CTC_NAME_SIZE) ? decoded->subjectSTLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->state, decoded->subjectST, CTC_NAME_SIZE); + cn->state[sz] = '\0'; + cn->stateEnc = decoded->subjectSTEnc; + } + if (decoded->subjectL) { + sz = (decoded->subjectLLen < CTC_NAME_SIZE) ? decoded->subjectLLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->locality, decoded->subjectL, CTC_NAME_SIZE); + cn->locality[sz] = '\0'; + cn->localityEnc = decoded->subjectLEnc; + } + if (decoded->subjectO) { + sz = (decoded->subjectOLen < CTC_NAME_SIZE) ? decoded->subjectOLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->org, decoded->subjectO, CTC_NAME_SIZE); + cn->org[sz] = '\0'; + cn->orgEnc = decoded->subjectOEnc; + } + if (decoded->subjectOU) { + sz = (decoded->subjectOULen < CTC_NAME_SIZE) ? decoded->subjectOULen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->unit, decoded->subjectOU, CTC_NAME_SIZE); + cn->unit[sz] = '\0'; + cn->unitEnc = decoded->subjectOUEnc; + } + if (decoded->subjectSN) { + sz = (decoded->subjectSNLen < CTC_NAME_SIZE) ? decoded->subjectSNLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->sur, decoded->subjectSN, CTC_NAME_SIZE); + cn->sur[sz] = '\0'; + cn->surEnc = decoded->subjectSNEnc; + } + if (decoded->subjectSND) { + sz = (decoded->subjectSNDLen < CTC_NAME_SIZE) ? decoded->subjectSNDLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->serialDev, decoded->subjectSND, CTC_NAME_SIZE); + cn->serialDev[sz] = '\0'; + cn->serialDevEnc = decoded->subjectSNDEnc; + } +#ifdef WOLFSSL_CERT_EXT + if (decoded->subjectBC) { + sz = (decoded->subjectBCLen < CTC_NAME_SIZE) ? decoded->subjectBCLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->busCat, decoded->subjectBC, CTC_NAME_SIZE); + cn->busCat[sz] = '\0'; + cn->busCatEnc = decoded->subjectBCEnc; + } + if (decoded->subjectJC) { + sz = (decoded->subjectJCLen < CTC_NAME_SIZE) ? decoded->subjectJCLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->joiC, decoded->subjectJC, CTC_NAME_SIZE); + cn->joiC[sz] = '\0'; + cn->joiCEnc = decoded->subjectJCEnc; + } + if (decoded->subjectJS) { + sz = (decoded->subjectJSLen < CTC_NAME_SIZE) ? decoded->subjectJSLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->joiSt, decoded->subjectJS, CTC_NAME_SIZE); + cn->joiSt[sz] = '\0'; + cn->joiStEnc = decoded->subjectJSEnc; + } +#endif + if (decoded->subjectEmail) { + sz = (decoded->subjectEmailLen < CTC_NAME_SIZE) + ? decoded->subjectEmailLen : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->email, decoded->subjectEmail, CTC_NAME_SIZE); + cn->email[sz] = '\0'; + } +} + /* Set cn name from der buffer, return 0 on success */ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) { - int ret, sz; + int ret; #ifdef WOLFSSL_SMALL_STACK DecodedCert* decoded; #else @@ -12876,91 +12991,7 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) WOLFSSL_MSG("ParseCertRelative error"); } else { - if (decoded->subjectCN) { - sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen - : CTC_NAME_SIZE - 1; - XSTRNCPY(cn->commonName, decoded->subjectCN, CTC_NAME_SIZE); - cn->commonName[sz] = '\0'; - cn->commonNameEnc = decoded->subjectCNEnc; - } - if (decoded->subjectC) { - sz = (decoded->subjectCLen < CTC_NAME_SIZE) ? decoded->subjectCLen - : CTC_NAME_SIZE - 1; - XSTRNCPY(cn->country, decoded->subjectC, CTC_NAME_SIZE); - cn->country[sz] = '\0'; - cn->countryEnc = decoded->subjectCEnc; - } - if (decoded->subjectST) { - sz = (decoded->subjectSTLen < CTC_NAME_SIZE) ? decoded->subjectSTLen - : CTC_NAME_SIZE - 1; - XSTRNCPY(cn->state, decoded->subjectST, CTC_NAME_SIZE); - cn->state[sz] = '\0'; - cn->stateEnc = decoded->subjectSTEnc; - } - if (decoded->subjectL) { - sz = (decoded->subjectLLen < CTC_NAME_SIZE) ? decoded->subjectLLen - : CTC_NAME_SIZE - 1; - XSTRNCPY(cn->locality, decoded->subjectL, CTC_NAME_SIZE); - cn->locality[sz] = '\0'; - cn->localityEnc = decoded->subjectLEnc; - } - if (decoded->subjectO) { - sz = (decoded->subjectOLen < CTC_NAME_SIZE) ? decoded->subjectOLen - : CTC_NAME_SIZE - 1; - XSTRNCPY(cn->org, decoded->subjectO, CTC_NAME_SIZE); - cn->org[sz] = '\0'; - cn->orgEnc = decoded->subjectOEnc; - } - if (decoded->subjectOU) { - sz = (decoded->subjectOULen < CTC_NAME_SIZE) ? decoded->subjectOULen - : CTC_NAME_SIZE - 1; - XSTRNCPY(cn->unit, decoded->subjectOU, CTC_NAME_SIZE); - cn->unit[sz] = '\0'; - cn->unitEnc = decoded->subjectOUEnc; - } - if (decoded->subjectSN) { - sz = (decoded->subjectSNLen < CTC_NAME_SIZE) ? decoded->subjectSNLen - : CTC_NAME_SIZE - 1; - XSTRNCPY(cn->sur, decoded->subjectSN, CTC_NAME_SIZE); - cn->sur[sz] = '\0'; - cn->surEnc = decoded->subjectSNEnc; - } - if (decoded->subjectSND) { - sz = (decoded->subjectSNDLen < CTC_NAME_SIZE) ? decoded->subjectSNDLen - : CTC_NAME_SIZE - 1; - XSTRNCPY(cn->serialDev, decoded->subjectSND, CTC_NAME_SIZE); - cn->serialDev[sz] = '\0'; - cn->serialDevEnc = decoded->subjectSNDEnc; - } - #ifdef WOLFSSL_CERT_EXT - if (decoded->subjectBC) { - sz = (decoded->subjectBCLen < CTC_NAME_SIZE) ? decoded->subjectBCLen - : CTC_NAME_SIZE - 1; - XSTRNCPY(cn->busCat, decoded->subjectBC, CTC_NAME_SIZE); - cn->busCat[sz] = '\0'; - cn->busCatEnc = decoded->subjectBCEnc; - } - if (decoded->subjectJC) { - sz = (decoded->subjectJCLen < CTC_NAME_SIZE) ? decoded->subjectJCLen - : CTC_NAME_SIZE - 1; - XSTRNCPY(cn->joiC, decoded->subjectJC, CTC_NAME_SIZE); - cn->joiC[sz] = '\0'; - cn->joiCEnc = decoded->subjectJCEnc; - } - if (decoded->subjectJS) { - sz = (decoded->subjectJSLen < CTC_NAME_SIZE) ? decoded->subjectJSLen - : CTC_NAME_SIZE - 1; - XSTRNCPY(cn->joiSt, decoded->subjectJS, CTC_NAME_SIZE); - cn->joiSt[sz] = '\0'; - cn->joiStEnc = decoded->subjectJSEnc; - } - #endif - if (decoded->subjectEmail) { - sz = (decoded->subjectEmailLen < CTC_NAME_SIZE) - ? decoded->subjectEmailLen : CTC_NAME_SIZE - 1; - XSTRNCPY(cn->email, decoded->subjectEmail, CTC_NAME_SIZE); - cn->email[sz] = '\0'; - } + SetNameFromDcert(cn, decoded); } FreeDecodedCert(decoded); @@ -12972,112 +13003,6 @@ static int SetNameFromCert(CertName* cn, const byte* der, int derSz) return ret < 0 ? ret : 0; } -#ifdef WOLFSSL_CERT_EXT -/* Set raw subject from der buffer, return 0 on success */ -static int SetSubjectRawFromCert(byte* sbjRaw, const byte* der, int derSz) -{ - int ret; -#ifdef WOLFSSL_SMALL_STACK - DecodedCert* decoded; -#else - DecodedCert decoded[1]; -#endif - - if ((derSz < 0) || (sbjRaw == NULL)) { - return BAD_FUNC_ARG; - } - -#ifdef WOLFSSL_SMALL_STACK - decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (decoded == NULL) { - return MEMORY_E; - } -#endif - - InitDecodedCert(decoded, der, derSz, NULL); - ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); - - if (ret < 0) { - WOLFSSL_MSG("ParseCertRelative error"); - } -#ifndef IGNORE_NAME_CONSTRAINT - else { - if ((decoded->subjectRaw) && - (decoded->subjectRawLen <= (int)sizeof(CertName))) { - XMEMCPY(sbjRaw, decoded->subjectRaw, decoded->subjectRawLen); - } - } -#else - else { - /* Fields are not accessible */ - ret = -1; - WOLFSSL_MSG("IGNORE_NAME_CONSTRAINT excludes raw subject"); - } -#endif - - FreeDecodedCert(decoded); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret < 0 ? ret : 0; -} - -/* Set raw issuer from der buffer, return 0 on success */ -static int SetIssuerRawFromCert(byte* issuerRaw, const byte* der, int derSz) -{ - int ret; -#ifdef WOLFSSL_SMALL_STACK - DecodedCert* decoded; -#else - DecodedCert decoded[1]; -#endif - - if ((derSz < 0) || (issuerRaw == NULL)) { - return BAD_FUNC_ARG; - } - -#ifdef WOLFSSL_SMALL_STACK - decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (decoded == NULL) { - return MEMORY_E; - } -#endif - - InitDecodedCert(decoded, der, derSz, NULL); - ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); - - if (ret < 0) { - WOLFSSL_MSG("ParseCertRelative error"); - } -#ifndef IGNORE_NAME_CONSTRAINT - else { - if ((decoded->issuerRaw) && - (decoded->issuerRawLen <= (int)sizeof(CertName))) { - XMEMCPY(issuerRaw, decoded->issuerRaw, decoded->issuerRawLen); - } - } -#else - else { - /* Fields are not accessible */ - ret = -1; - WOLFSSL_MSG("IGNORE_NAME_CONSTRAINT excludes raw issuer"); - } -#endif - - FreeDecodedCert(decoded); - -#ifdef WOLFSSL_SMALL_STACK - XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - return ret < 0 ? ret : 0; -} -#endif /* WOLFSSL_CERT_EXT */ - #ifndef NO_FILESYSTEM /* Set cert issuer from issuerFile in PEM */ @@ -13161,48 +13086,116 @@ int wc_SetAltNames(Cert* cert, const char* file) /* Set cert issuer from DER buffer */ int wc_SetIssuerBuffer(Cert* cert, const byte* der, int derSz) { - if (cert == NULL) { - return BAD_FUNC_ARG; - } - - cert->selfSigned = 0; - return SetNameFromCert(&cert->issuer, der, derSz); -} - -/* Set cert subject from DER buffer */ -int wc_SetSubjectBuffer(Cert* cert, const byte* der, int derSz) -{ - if (cert == NULL) { - return BAD_FUNC_ARG; - } - - return SetNameFromCert(&cert->subject, der, derSz); -} -#ifdef WOLFSSL_CERT_EXT -/* Set cert raw subject from DER buffer */ -int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz) -{ - int ret; + int ret = 0; if (cert == NULL) { ret = BAD_FUNC_ARG; } else { - ret = SetSubjectRawFromCert(cert->sbjRaw, der, derSz); + cert->selfSigned = 0; + + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + SetNameFromDcert(&cert->issuer, cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } } + + return ret; +} + +/* Set cert subject from DER buffer */ +int wc_SetSubjectBuffer(Cert* cert, const byte* der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + SetNameFromDcert(&cert->subject, cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return ret; +} +#ifdef WOLFSSL_CERT_EXT +/* Set cert raw subject from DER buffer */ +int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + if ((((DecodedCert*)cert->decodedCert)->subjectRaw) && + (((DecodedCert*)cert->decodedCert)->subjectRawLen <= + (int)sizeof(CertName))) { + XMEMCPY(cert->sbjRaw, + ((DecodedCert*)cert->decodedCert)->subjectRaw, + ((DecodedCert*)cert->decodedCert)->subjectRawLen); + } +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + return ret; } /* Set cert raw issuer from DER buffer */ int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz) { - int ret; + int ret = 0; if (cert == NULL) { ret = BAD_FUNC_ARG; } else { - ret = SetIssuerRawFromCert(cert->issRaw, der, derSz); + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + if ((((DecodedCert*)cert->decodedCert)->issuerRaw) && + (((DecodedCert*)cert->decodedCert)->issuerRawLen <= + (int)sizeof(CertName))) { + XMEMCPY(cert->issRaw, + ((DecodedCert*)cert->decodedCert)->issuerRaw, + ((DecodedCert*)cert->decodedCert)->issuerRawLen); + } +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } } return ret; } @@ -13213,13 +13206,53 @@ int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz) /* Set cert alt names from DER buffer */ int wc_SetAltNamesBuffer(Cert* cert, const byte* der, int derSz) { - return SetAltNamesFromCert(cert, der, derSz); + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + ret = SetAltNamesFromDcert(cert, cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return(ret); } /* Set cert dates from DER buffer */ int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz) { - return SetDatesFromCert(cert, der, derSz); + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + ret = SetDatesFromDcert(cert, cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return(ret); } #endif /* WOLFSSL_ALT_NAMES */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index e6d84179c..3918a63b0 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -357,6 +357,10 @@ int cert_test(void); !defined(NO_FILESYSTEM) int certext_test(void); #endif +#if defined(WOLFSSL_CERT_GEN_CACHE) && defined(WOLFSSL_TEST_CERT) && \ + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) +int decodedCertCache_test(void); +#endif #ifdef HAVE_IDEA int idea_test(void); #endif @@ -946,6 +950,14 @@ initDefaultName(); printf( "CERT EXT test passed!\n"); #endif +#if defined(WOLFSSL_CERT_GEN_CACHE) && defined(WOLFSSL_TEST_CERT) && \ + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) + if ( (ret = decodedCertCache_test()) != 0) + return err_sys("DECODED CERT CACHE test failed!\n", ret); + else + printf( "DECODED CERT CACHE test passed!\n"); +#endif + #ifdef HAVE_CURVE25519 if ( (ret = curve25519_test()) != 0) return err_sys("CURVE25519 test failed!\n", ret); @@ -9078,6 +9090,122 @@ int certext_test(void) } #endif /* WOLFSSL_CERT_EXT && WOLFSSL_TEST_CERT */ +#if defined(WOLFSSL_CERT_GEN_CACHE) && defined(WOLFSSL_TEST_CERT) && \ + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) +int decodedCertCache_test(void) +{ + int ret = 0; + Cert cert; + FILE* file; + byte* der; + word32 derSz; + + derSz = FOURK_BUF; + der = XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) + ret = -1; + + if (ret == 0) { + /* load cert.der */ + file = fopen(certDerFile, "rb"); + if (file != NULL) { + derSz = fread(der, 1, FOURK_BUF, file); + fclose(file); + } + else + ret = -1; + } + + if (ret == 0) { + if (wc_InitCert(&cert)) { + ret = -1; + } + } + + if (ret == 0) { + ret = wc_SetSubjectBuffer(&cert, der, derSz); + } + + if (ret == 0) { + if(wc_SetSubjectBuffer(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -1; + } + + if (ret == 0) { + if (wc_SetSubjectRaw(&cert, der, derSz) != 0) + ret = -1; + } + + if (ret == 0) { + if(wc_SetSubjectRaw(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -1; + } + + if (ret == 0) { + if(wc_SetIssuerBuffer(&cert, der, derSz) != 0) + ret = -1; + } + + if (ret == 0) { + if(wc_SetIssuerBuffer(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -1; + } + + if (ret == 0) { + if(wc_SetIssuerRaw(&cert, der, derSz) != 0) + ret = -1; + } + + if (ret == 0) { + if(wc_SetIssuerRaw(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -1; + } + +#ifdef WOLFSSL_ALT_NAMES + if (ret == 0) { + if(wc_SetAltNamesBuffer(&cert, der, derSz) != 0) + ret = -1; + } + + if (ret == 0) { + if(wc_SetAltNamesBuffer(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -1; + } + + if (ret == 0) { + if(wc_SetDatesBuffer(&cert, der, derSz) != 0) + ret = -1; + } + + if (ret == 0) { + if(wc_SetDatesBuffer(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -1; + } +#endif + + if (ret == 0) { + if(wc_SetAuthKeyIdFromCert(&cert, der, derSz) != 0) + ret = -1; + } + + if (ret == 0) { + if(wc_SetAuthKeyIdFromCert(NULL, der, derSz) != BAD_FUNC_ARG) + ret = -1; + } + + wc_SetCert_Free(&cert); + if (ret == 0) { + if(cert.decodedCert != NULL) + ret = -1; + } + + XFREE(der, HEAP_HINT ,DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif /* defined(WOLFSSL_CERT_GEN_CACHE) && defined(WOLFSSL_TEST_CERT) && + defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_CERT_GEN) */ + #if !defined(NO_ASN) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) static int rsa_flatten_test(RsaKey* key) { diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 97e52e717..70e9d50ae 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -297,7 +297,9 @@ typedef struct Cert { #ifdef WOLFSSL_CERT_REQ char challengePw[CTC_NAME_SIZE]; #endif - void* heap; /* heap hint */ + void* decodedCert; /* internal DecodedCert allocated from heap */ + byte* der; /* Pointer to buffer of current DecodedCert cache */ + void* heap; /* heap hint */ } Cert; @@ -336,6 +338,11 @@ WOLFSSL_API int wc_SetSubject(Cert*, const char*); #ifdef WOLFSSL_ALT_NAMES WOLFSSL_API int wc_SetAltNames(Cert*, const char*); #endif + +#ifdef WOLFSSL_CERT_GEN_CACHE +WOLFSSL_API void wc_SetCert_Free(Cert* cert); +#endif + WOLFSSL_API int wc_SetIssuerBuffer(Cert*, const byte*, int); WOLFSSL_API int wc_SetSubjectBuffer(Cert*, const byte*, int); WOLFSSL_API int wc_SetAltNamesBuffer(Cert*, const byte*, int); @@ -545,4 +552,3 @@ WOLFSSL_API int wc_ParseCertPIV(wc_CertPIV* cert, const byte* buf, word32 totalS #endif #endif /* WOLF_CRYPT_ASN_PUBLIC_H */ - From 8b6bd306f3cb93adf65f96f69f55528bea3ffe16 Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Mon, 11 Mar 2019 18:03:29 -0500 Subject: [PATCH 2/3] Update from review --- wolfcrypt/test/test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 3918a63b0..13897c98d 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -9107,9 +9107,9 @@ int decodedCertCache_test(void) if (ret == 0) { /* load cert.der */ - file = fopen(certDerFile, "rb"); + file = XFOPEN(certDerFile, "rb"); if (file != NULL) { - derSz = fread(der, 1, FOURK_BUF, file); + derSz = XFREAD(der, 1, FOURK_BUF, file); fclose(file); } else From 2b59aefe80bfaf2ca7fb885bfe79b70c0610d98e Mon Sep 17 00:00:00 2001 From: Eric Blankenhorn Date: Mon, 11 Mar 2019 18:14:37 -0500 Subject: [PATCH 3/3] Update from review --- wolfcrypt/test/test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 13897c98d..7483045eb 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -9110,7 +9110,7 @@ int decodedCertCache_test(void) file = XFOPEN(certDerFile, "rb"); if (file != NULL) { derSz = XFREAD(der, 1, FOURK_BUF, file); - fclose(file); + XFCLOSE(file); } else ret = -1;