diff --git a/doc/dox_comments/header_files/asn_public.h b/doc/dox_comments/header_files/asn_public.h index b4c537ec712..a67a39ea944 100644 --- a/doc/dox_comments/header_files/asn_public.h +++ b/doc/dox_comments/header_files/asn_public.h @@ -3889,6 +3889,62 @@ int wc_SetCustomExtension(Cert *cert, int critical, const char *oid, */ int wc_SetUnknownExtCallback(DecodedCert* cert, wc_UnknownExtCallback cb); + +/*! + \ingroup ASN + + \brief This function registers a callback that will be used anytime + wolfSSL encounters an unknown OID within the Extended Key Usage (EKU) + extension in a certificate while parsing. The prototype of the callback + should be: + + \code + int myUnknownEKUCallback(const word16* oid, word32 oidSz); + \endcode + + \return 0 Returned on success. + \return BAD_FUNC_ARG Returned when cert is NULL. + + \param cert the DecodedCert struct that is to be associated with this + callback. + \param cb function to register as the unknown EKU OID callback. + + _Example_ + \code + int ret = 0; + DecodedCert cert; + + // Unknown EKU callback prototype + int myUnknownEKUCallback(const word16* oid, word32 oidSz); + + // Initialize cert, then register callback + ret = wc_SetUnknownExtKeyUsageCallback(&cert, myUnknownEKUCallback); + if (ret != 0) { + // failed to set the callback + } + + // oid: Array of integers that are the dot separated values in an OID. + // For example, OID 1.2.3.4.5 would be {1, 2, 3, 4, 5}. + // oidSz: Number of values in oid array. + int myUnknownEKUCallback(const word16* oid, word32 oidSz) { + + // Logic to handle unknown EKU OID goes here. + // For example, check if the OID is acceptable for your application. + + // NOTE: by returning zero, we are accepting this OID and + // informing wolfSSL that it is acceptable. If you find an OID + // that you do not find acceptable, you should return an error + // which will cause certificate parsing to fail. + return 0; + } + \endcode + + \sa ParseCert + \sa wc_SetUnknownExtCallback +*/ +int wc_SetUnknownExtKeyUsageCallback(DecodedCert* cert, + wc_UnknownExtKeyUsageCallback cb); + /*! \ingroup ASN diff --git a/src/x509.c b/src/x509.c index fd46e89c40c..b27fbe08b4e 100644 --- a/src/x509.c +++ b/src/x509.c @@ -3602,7 +3602,7 @@ static int wolfSSL_ASN1_STRING_into_old_ext_fmt(WOLFSSL_ASN1_STRING *asn1str, ret = DecodeExtKeyUsage((const byte*)asn1str->data, asn1str->length, &extExtKeyUsageSrc, &extExtKeyUsageSz, &extExtKeyUsageCount, - &extExtKeyUsage, &extExtKeyUsageSsh); + &extExtKeyUsage, &extExtKeyUsageSsh, NULL); if (ret != 0) return ret; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 231d250b6ed..b63983ac7a9 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -22031,6 +22031,7 @@ enum { * @param [out] extExtKeyUsageCount Number of usages read. * @param [out] extExtKeyUsage Usages read. * @param [out] extExtKeyUsageSsh SSH usages read. + * @param [in] unknownCb Callback for unknown EKU OIDs. * @return 0 on success. * @return ASN_BITSTR_E when the expected BIT_STRING tag is not found. * @return ASN_PARSE_E when BER encoded data does not match ASN.1 items or @@ -22040,11 +22041,20 @@ enum { int DecodeExtKeyUsage(const byte* input, word32 sz, const byte **extExtKeyUsageSrc, word32 *extExtKeyUsageSz, word32 *extExtKeyUsageCount, byte *extExtKeyUsage, - byte *extExtKeyUsageSsh) + byte *extExtKeyUsageSsh, +#ifdef WC_ASN_UNKNOWN_EXT_CB + wc_UnknownExtKeyUsageCallback unknownCb +#else + void *unknownCb +#endif + ) { #ifndef WOLFSSL_ASN_TEMPLATE word32 idx = 0, oid; int length, ret; +#ifdef WC_ASN_UNKNOWN_EXT_CB + word32 oidStartIdx; +#endif WOLFSSL_ENTER("DecodeExtKeyUsage"); @@ -22052,6 +22062,9 @@ int DecodeExtKeyUsage(const byte* input, word32 sz, (void) extExtKeyUsageSz; (void) extExtKeyUsageCount; (void) extExtKeyUsageSsh; +#ifndef WC_ASN_UNKNOWN_EXT_CB + (void) unknownCb; +#endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) *extExtKeyUsageSrc = NULL; @@ -22074,9 +22087,34 @@ int DecodeExtKeyUsage(const byte* input, word32 sz, #endif while (idx < (word32)sz) { + #ifdef WC_ASN_UNKNOWN_EXT_CB + oidStartIdx = idx; + #endif ret = GetObjectId(input, &idx, &oid, oidCertKeyUseType, sz); - if (ret == WC_NO_ERR_TRACE(ASN_UNKNOWN_OID_E)) + if (ret == WC_NO_ERR_TRACE(ASN_UNKNOWN_OID_E)) { + #ifdef WC_ASN_UNKNOWN_EXT_CB + if (unknownCb != NULL) { + word16 decOid[MAX_OID_SZ]; + word32 decOidSz = sizeof(decOid); + /* Skip past the tag and length to get raw OID bytes */ + word32 oidIdx = oidStartIdx; + int oidLen; + byte tag; + if (GetASNTag(input, &oidIdx, &tag, sz) == 0 && + tag == ASN_OBJECT_ID && + GetLength(input, &oidIdx, &oidLen, sz) >= 0) { + ret = DecodeObjectId(input + oidIdx, (word32)oidLen, + decOid, &decOidSz); + if (ret == 0) { + ret = unknownCb(decOid, decOidSz); + } + if (ret != 0) + return ret; + } + } + #endif continue; + } else if (ret < 0) return ret; @@ -22127,6 +22165,9 @@ int DecodeExtKeyUsage(const byte* input, word32 sz, word32 idx = 0; int length; int ret = 0; +#ifdef WC_ASN_UNKNOWN_EXT_CB + int isKnownOid; +#endif WOLFSSL_ENTER("DecodeExtKeyUsage"); @@ -22134,6 +22175,9 @@ int DecodeExtKeyUsage(const byte* input, word32 sz, (void) extExtKeyUsageSz; (void) extExtKeyUsageCount; (void) extExtKeyUsageSsh; +#ifndef WC_ASN_UNKNOWN_EXT_CB + (void) unknownCb; +#endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) *extExtKeyUsageSrc = NULL; @@ -22171,9 +22215,29 @@ int DecodeExtKeyUsage(const byte* input, word32 sz, input, &idx, sz); /* Skip unknown OIDs. */ if (ret == WC_NO_ERR_TRACE(ASN_UNKNOWN_OID_E)) { + #ifdef WC_ASN_UNKNOWN_EXT_CB + if (unknownCb != NULL) { + word16 decOid[MAX_OID_SZ]; + word32 decOidSz = sizeof(decOid); + ret = DecodeObjectId( + dataASN[KEYPURPOSEIDASN_IDX_OID].data.oid.data, + dataASN[KEYPURPOSEIDASN_IDX_OID].data.oid.length, + decOid, &decOidSz); + if (ret == 0) { + ret = unknownCb(decOid, decOidSz); + } + } + else { + ret = 0; + } + #else ret = 0; + #endif } else if (ret == 0) { + #ifdef WC_ASN_UNKNOWN_EXT_CB + isKnownOid = 1; + #endif /* Store the bit for the OID. */ switch (dataASN[KEYPURPOSEIDASN_IDX_OID].data.oid.sum) { case EKU_ANY_OID: @@ -22197,7 +22261,28 @@ int DecodeExtKeyUsage(const byte* input, word32 sz, case EKU_OCSP_SIGN_OID: *extExtKeyUsage |= EXTKEYUSE_OCSP_SIGN; break; + #ifdef WC_ASN_UNKNOWN_EXT_CB + default: + isKnownOid = 0; + break; + #endif + } + + #ifdef WC_ASN_UNKNOWN_EXT_CB + /* Handle unknown OIDs that parsed successfully but aren't + * recognized */ + if (!isKnownOid && unknownCb != NULL) { + word16 decOid[MAX_OID_SZ]; + word32 decOidSz = sizeof(decOid); + ret = DecodeObjectId( + dataASN[KEYPURPOSEIDASN_IDX_OID].data.oid.data, + dataASN[KEYPURPOSEIDASN_IDX_OID].data.oid.length, + decOid, &decOidSz); + if (ret == 0) { + ret = unknownCb(decOid, decOidSz); + } } + #endif #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) /* Keep count for WOLFSSL_X509. */ @@ -22238,7 +22323,12 @@ static int DecodeExtKeyUsageInternal(const byte* input, word32 sz, #endif &cert->extExtKeyUsage, #ifdef WOLFSSL_WOLFSSH - &cert->extExtKeyUsageSsh + &cert->extExtKeyUsageSsh, +#else + NULL, +#endif +#ifdef WC_ASN_UNKNOWN_EXT_CB + cert->unknownExtKeyUsageCallback #else NULL #endif @@ -23663,6 +23753,16 @@ int wc_SetUnknownExtCallbackEx(DecodedCert* cert, cert->unknownExtCallbackExCtx = ctx; return 0; } + +int wc_SetUnknownExtKeyUsageCallback(DecodedCert* cert, + wc_UnknownExtKeyUsageCallback cb) { + if (cert == NULL) { + return BAD_FUNC_ARG; + } + + cert->unknownExtKeyUsageCallback = cb; + return 0; +} #endif /* WC_ASN_UNKNOWN_EXT_CB */ /* diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 340f189ec56..e5a95efa7bb 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1721,6 +1721,7 @@ typedef int (*wc_UnknownExtCallback)(const word16* oid, word32 oidSz, int crit, typedef int (*wc_UnknownExtCallbackEx)(const word16* oid, word32 oidSz, int crit, const unsigned char* der, word32 derSz, void *ctx); +typedef int (*wc_UnknownExtKeyUsageCallback)(const word16* oid, word32 oidSz); #endif struct DecodedCert { @@ -2052,6 +2053,7 @@ struct DecodedCert { wc_UnknownExtCallback unknownExtCallback; wc_UnknownExtCallbackEx unknownExtCallbackEx; void *unknownExtCallbackExCtx; + wc_UnknownExtKeyUsageCallback unknownExtKeyUsageCallback; #endif #ifdef WOLFSSL_DUAL_ALG_CERTS /* Subject Alternative Public Key Info */ @@ -2277,6 +2279,8 @@ WOLFSSL_API int wc_SetUnknownExtCallback(DecodedCert* cert, WOLFSSL_API int wc_SetUnknownExtCallbackEx(DecodedCert* cert, wc_UnknownExtCallbackEx cb, void *ctx); +WOLFSSL_API int wc_SetUnknownExtKeyUsageCallback(DecodedCert* cert, + wc_UnknownExtKeyUsageCallback cb); #endif WOLFSSL_LOCAL int DecodePolicyOID(char *out, word32 outSz, const byte *in, @@ -2341,7 +2345,13 @@ WOLFSSL_LOCAL int DecodeKeyUsage(const byte* input, word32 sz, WOLFSSL_LOCAL int DecodeExtKeyUsage(const byte* input, word32 sz, const byte **extExtKeyUsageSrc, word32 *extExtKeyUsageSz, word32 *extExtKeyUsageCount, byte *extExtKeyUsage, - byte *extExtKeyUsageSsh); + byte *extExtKeyUsageSsh, +#ifdef WC_ASN_UNKNOWN_EXT_CB + wc_UnknownExtKeyUsageCallback unknownCb +#else + void *unknownCb +#endif + ); WOLFSSL_LOCAL int TryDecodeRPKToKey(DecodedCert* cert); WOLFSSL_LOCAL int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate);