Parsing of custom extensions in X.509 certificates.

This commit is contained in:
Anthony Hu
2022-02-18 16:55:11 -05:00
parent c22282a8aa
commit cb95aed41b
2 changed files with 59 additions and 4 deletions

View File

@ -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;
}

View File

@ -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,