diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index b6c8ee3cd..1e45814bf 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -16565,11 +16565,14 @@ exit: * @return Other -ve value on error. */ static int DecodeExtensionType(const byte* input, int length, word32 oid, - byte critical, DecodedCert* cert) + byte critical, DecodedCert* cert, int *unknown) { int ret = 0; word32 idx = 0; + if (unknown != NULL) + *unknown = 0; + switch (oid) { /* Basic Constraints. */ case BASIC_CA_OID: @@ -16753,6 +16756,8 @@ static int DecodeExtensionType(const byte* input, int length, word32 oid, return ASN_PARSE_E; break; default: + if (unknown != NULL) + *unknown = 1; #ifndef WOLFSSL_NO_ASN_STRICT /* While it is a failure to not support critical extensions, * still parse the certificate ignoring the unsupported @@ -16806,6 +16811,16 @@ enum { #define certExtASN_Length (sizeof(certExtASN) / sizeof(ASNItem)) #endif +#if defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ASN_TEMPLATE) \ + && defined(HAVE_OID_DECODING) +WOLFSSL_ASN_API void SetUnknownExtCallback(DecodedCert* cert, + wc_UnknownExtCallback cb) { + if (cert != NULL) { + cert->unknownExtCallback = cb; + } +} +#endif + /* * Processing the Certificate Extensions. This does not modify the current * index. It is works starting with the recorded extensions pointer. @@ -16893,7 +16908,8 @@ static int DecodeCertExtensions(DecodedCert* cert) return ret; } - ret = DecodeExtensionType(input + idx, length, oid, critical, cert); + ret = DecodeExtensionType(input + idx, length, oid, critical, cert, + NULL); if (ret == ASN_CRIT_EXT_E) { ret = 0; criticalFail = 1; @@ -16938,6 +16954,7 @@ end: /* Parse each extension. */ while ((ret == 0) && (idx < (word32)sz)) { byte critical = 0; + int unknown = 0; /* Clear dynamic data. */ XMEMSET(dataASN, 0, sizeof(*dataASN) * certExtASN_Length); @@ -16953,7 +16970,30 @@ end: int length = dataASN[CERTEXTASN_IDX_VAL].length; /* Decode the extension by type. */ - ret = DecodeExtensionType(input + idx, length, oid, critical, cert); + ret = DecodeExtensionType(input + idx, length, oid, critical, cert, + &unknown); +#if defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ASN_TEMPLATE) \ + && defined(HAVE_OID_DECODING) + if (unknown && (cert->unknownExtCallback != NULL)) { + word16 decOid[16]; + word32 decOidSz = sizeof(decOid); + ret = DecodeObjectId( + dataASN[CERTEXTASN_IDX_OID].data.oid.data, + dataASN[CERTEXTASN_IDX_OID].data.oid.length, + decOid, &decOidSz); + if (ret != 0) { + /* Should never get here as the extension was successfully + * decoded earlier. */ + printf("DecodeObjectId failed: %d\n", ret); + } + + ret = cert->unknownExtCallback(decOid, decOidSz, critical, + dataASN[CERTEXTASN_IDX_VAL].data.buffer.data, + dataASN[CERTEXTASN_IDX_VAL].length); + } +#endif + (void)unknown; + /* Move index on to next extension. */ idx += length; } diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index a2b207a1f..d82d0b3d2 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -513,7 +513,7 @@ WOLFSSL_LOCAL void SetASN_OID(ASNSetData *dataASN, int oid, int oidType); */ #define SetASN_Buffer(dataASN, d, l) \ do { \ - (dataASN)->data.buffer.data = d; \ + (dataASN)->data.buffer.data = (const byte *) d; \ (dataASN)->data.buffer.length = l; \ } while (0) @@ -1459,6 +1459,11 @@ typedef struct TrustedPeerCert TrustedPeerCert; typedef struct SignatureCtx SignatureCtx; typedef struct CertSignCtx CertSignCtx; +#if defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ASN_TEMPLATE) \ + && defined(HAVE_OID_DECODING) +typedef int (*wc_UnknownExtCallback)(const word16* oid, word32 oidSz, int crit, + const unsigned char* der, word32 derSz); +#endif struct DecodedCert { const byte* publicKey; @@ -1689,6 +1694,10 @@ struct DecodedCert { #ifdef WOLFSSL_CERT_REQ byte isCSR : 1; /* Do we intend on parsing a CSR? */ #endif +#if defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ASN_TEMPLATE) \ + && defined(HAVE_OID_DECODING) + wc_UnknownExtCallback unknownExtCallback; +#endif }; #ifdef NO_SHA @@ -1816,6 +1825,12 @@ WOLFSSL_ASN_API void FreeDecodedCert(DecodedCert* cert); WOLFSSL_ASN_API int ParseCert(DecodedCert* cert, int type, int verify, void* cm); +#if defined(WOLFSSL_CUSTOM_OID) && defined(WOLFSSL_ASN_TEMPLATE) \ + && defined(HAVE_OID_DECODING) +WOLFSSL_ASN_API void SetUnknownExtCallback(DecodedCert* cert, + wc_UnknownExtCallback cb); +#endif + WOLFSSL_LOCAL int DecodePolicyOID(char *out, word32 outSz, const byte *in, word32 inSz); WOLFSSL_LOCAL int EncodePolicyOID(byte *out, word32 *outSz,