Skip to content

Commit 0ac3b93

Browse files
committed
Enable allowing unsupported critical extensions in runtime
When compile time flag MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION is not set, certificate parsing fails if certificate contains unsupported critical extension. This patch allows to modify this behavior in runtime. Signed-off-by: Lev Stipakov <[email protected]>
1 parent d414c32 commit 0ac3b93

File tree

9 files changed

+166
-16
lines changed

9 files changed

+166
-16
lines changed

include/mbedtls/oid.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,17 @@ int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_b
470470
*/
471471
int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type );
472472

473+
/**
474+
* \brief Translate supported and unsupported X.509 extension OID into local values
475+
*
476+
* \param oid OID to use
477+
* \param ext_type place to store the extension type
478+
* \param is_supported place to store flag if extension is supported (1 - supported, 0 otherwise)
479+
*
480+
* \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND
481+
*/
482+
int mbedtls_oid_get_x509_ext_type_supported( const mbedtls_asn1_buf *oid, int *ext_type, int *is_supported);
483+
473484
/**
474485
* \brief Translate an X.509 attribute type OID into the short name
475486
* (e.g. the OID for an X520 Common Name into "CN")

include/mbedtls/ssl.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,6 +1063,10 @@ struct mbedtls_ssl_config
10631063
retransmission timeout (ms) */
10641064
#endif
10651065

1066+
uint32_t allowed_unsupported_critical_exts; /*!< Bit flags which represent runtime-enabled
1067+
unsupported critical extensions, e.g.
1068+
MBEDTLS_X509_EXT_NAME_CONSTRAINTS */
1069+
10661070
#if defined(MBEDTLS_SSL_RENEGOTIATION)
10671071
int renego_max_records; /*!< grace period for renegotiation */
10681072
unsigned char renego_period[8]; /*!< value of the record counters
@@ -3417,6 +3421,24 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf,
34173421
const unsigned char period[8] );
34183422
#endif /* MBEDTLS_SSL_RENEGOTIATION */
34193423

3424+
/**
3425+
* \brief Allows unsupported critical extensions
3426+
*
3427+
* Without compile-time flag MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION
3428+
* mbedTLS fails certificate verification if certificate contains
3429+
* unsupported critical extensions.
3430+
*
3431+
* This method allows to modify behavior in runtime by providing
3432+
* bit flags which represent unsupported extensions (for example MBEDTLS_X509_EXT_NAME_CONSTRAINTS)
3433+
* which should be allowed despite missing above mentioned compile-time flag.
3434+
*
3435+
* \param conf SSL configuration
3436+
* \param exts Bit flags which represent runtime-enabled unsupported critical extensions,
3437+
* e.g. MBEDTLS_X509_EXT_NAME_CONSTRAINTS
3438+
*
3439+
*/
3440+
void mbedtls_ssl_conf_allow_unsupported_critical_exts( mbedtls_ssl_config *conf, uint32_t exts );
3441+
34203442
/**
34213443
* \brief Check if there is data already read from the
34223444
* underlying transport but not yet processed.

include/mbedtls/x509_crt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ typedef struct mbedtls_x509_crt
9696
mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */
9797
void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */
9898

99+
uint32_t allowed_unsupported_critical_exts; /**< Optional Bit flags which represent runtime-enabled unsupported critical extensions, e.g. MBEDTLS_X509_EXT_NAME_CONSTRAINTS */
100+
99101
struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */
100102
}
101103
mbedtls_x509_crt;

library/oid.c

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -253,42 +253,96 @@ FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, co
253253
typedef struct {
254254
mbedtls_oid_descriptor_t descriptor;
255255
int ext_type;
256+
int is_supported;
256257
} oid_x509_ext_t;
257258

258259
static const oid_x509_ext_t oid_x509_ext[] =
259260
{
260261
{
261-
{ ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" },
262-
MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS,
262+
{ ADD_LEN( MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER ), "id-ce-authorityKeyIdentifier", "Authority Key Identifier" },
263+
MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER, 0,
263264
},
264265
{
265-
{ ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" },
266-
MBEDTLS_OID_X509_EXT_KEY_USAGE,
266+
{ ADD_LEN( MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER ), "id-ce-subjectKeyIdentifier", "Subject Key Identifier" },
267+
MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER, 0,
267268
},
268269
{
269-
{ ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" },
270-
MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE,
270+
{ ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" },
271+
MBEDTLS_OID_X509_EXT_KEY_USAGE, 1,
271272
},
272273
{
273-
{ ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" },
274-
MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME,
274+
{ ADD_LEN( MBEDTLS_OID_CERTIFICATE_POLICIES ), "id-ce-certificatePolicies", "Certificate Policies" },
275+
MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, 1,
275276
},
276277
{
277-
{ ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" },
278-
MBEDTLS_OID_X509_EXT_NS_CERT_TYPE,
278+
{ ADD_LEN( MBEDTLS_OID_POLICY_MAPPINGS ), "id-ce-policyMappings", "Policy Mapping" },
279+
MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS, 0,
279280
},
280281
{
281-
{ ADD_LEN( MBEDTLS_OID_CERTIFICATE_POLICIES ), "id-ce-certificatePolicies", "Certificate Policies" },
282-
MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES,
282+
{ ADD_LEN( MBEDTLS_OID_ISSUER_ALT_NAME ), "id-ce-issuerAltName", "Issuer Alt Name" },
283+
MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME, 0,
284+
},
285+
{
286+
{ ADD_LEN( MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS ), "id-ce-subjectDirectoryAttributes", "Subject Directory Attributes" },
287+
MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS, 0,
288+
},
289+
{
290+
{ ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" },
291+
MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, 1,
292+
},
293+
{
294+
{ ADD_LEN( MBEDTLS_OID_NAME_CONSTRAINTS ), "id-ce-nameConstraints", "Name Constraints" },
295+
MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS, 0,
296+
},
297+
{
298+
{ ADD_LEN( MBEDTLS_OID_POLICY_CONSTRAINTS ), "id-ce-policyConstraints", "Policy Constraints" },
299+
MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS, 0,
300+
},
301+
{
302+
{ ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" },
303+
MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, 1
304+
},
305+
{
306+
{ ADD_LEN( MBEDTLS_OID_CRL_DISTRIBUTION_POINTS ), "id-ce-cRLDistributionPoints", "CRL Distribution Points" },
307+
MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS, 0,
308+
},
309+
{
310+
{ ADD_LEN( MBEDTLS_OID_INIHIBIT_ANYPOLICY ), "id-ce-inhibitAnyPolicy", "Inhibit Any Policy" },
311+
MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY, 0,
312+
},
313+
{
314+
{ ADD_LEN( MBEDTLS_OID_FRESHEST_CRL ), "id-ce-freshestCRL", "Freshest CRL" },
315+
MBEDTLS_OID_X509_EXT_FRESHEST_CRL, 0,
316+
},
317+
{
318+
{ ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" },
319+
MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, 1
320+
},
321+
{
322+
{ ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" },
323+
MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, 1
283324
},
284325
{
285326
{ NULL, 0, NULL, NULL },
286-
0,
327+
0, 0
287328
},
288329
};
289330

331+
290332
FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext)
291-
FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type)
333+
FN_OID_GET_ATTR2(mbedtls_oid_get_x509_ext_type_supported, oid_x509_ext_t, x509_ext, int, ext_type, int, is_supported)
334+
335+
int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type )
336+
{
337+
int ret = 0;
338+
int is_supported = 0;
339+
340+
ret = mbedtls_oid_get_x509_ext_type_supported( oid, ext_type, &is_supported );
341+
if( is_supported == 0 )
342+
ret = MBEDTLS_ERR_OID_NOT_FOUND;
343+
344+
return( ret );
345+
}
292346

293347
static const mbedtls_oid_descriptor_t oid_ext_key_usage[] =
294348
{

library/ssl_tls.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,6 +2276,15 @@ static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
22762276
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
22772277
}
22782278

2279+
2280+
#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
2281+
if( ssl->session_negotiate->peer_cert != NULL )
2282+
{
2283+
ssl->session_negotiate->peer_cert->allowed_unsupported_critical_exts =
2284+
ssl->conf->allowed_unsupported_critical_exts;
2285+
}
2286+
#endif
2287+
22792288
/* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */
22802289
i += 3;
22812290

@@ -4752,6 +4761,11 @@ void mbedtls_ssl_conf_renegotiation_period( mbedtls_ssl_config *conf,
47524761
}
47534762
#endif /* MBEDTLS_SSL_RENEGOTIATION */
47544763

4764+
void mbedtls_ssl_conf_allow_unsupported_critical_exts( mbedtls_ssl_config *conf, uint32_t exts )
4765+
{
4766+
conf->allowed_unsupported_critical_exts = exts;
4767+
}
4768+
47554769
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
47564770
#if defined(MBEDTLS_SSL_CLI_C)
47574771
void mbedtls_ssl_conf_session_tickets( mbedtls_ssl_config *conf, int use_tickets )

library/x509_crt.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -891,6 +891,7 @@ static int x509_get_crt_ext( unsigned char **p,
891891
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
892892
size_t len;
893893
unsigned char *end_ext_data, *end_ext_octet;
894+
int is_supported;
894895

895896
if( *p == end )
896897
return( 0 );
@@ -945,16 +946,20 @@ static int x509_get_crt_ext( unsigned char **p,
945946
/*
946947
* Detect supported extensions
947948
*/
948-
ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type );
949+
ret = mbedtls_oid_get_x509_ext_type_supported( &extn_oid, &ext_type, &is_supported );
949950

950-
if( ret != 0 )
951+
if( ( ret != 0 ) || ( is_supported == 0 ) )
951952
{
952953
/* No parser found, skip extension */
953954
*p = end_ext_octet;
954955

955956
#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION)
956957
if( is_critical )
957958
{
959+
/* Do not fail if extension is found, but unsupported and allowed in runtime */
960+
if( ( ret == 0 ) && ( ext_type & crt->allowed_unsupported_critical_exts ) )
961+
continue;
962+
958963
/* Data is marked as critical: fail */
959964
return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS +
960965
MBEDTLS_ERR_ASN1_UNEXPECTED_TAG );
@@ -1346,6 +1351,7 @@ static int mbedtls_x509_crt_parse_der_internal( mbedtls_x509_crt *chain,
13461351

13471352
prev = crt;
13481353
mbedtls_x509_crt_init( crt->next );
1354+
crt->next->allowed_unsupported_critical_exts = crt->allowed_unsupported_critical_exts;
13491355
crt = crt->next;
13501356
}
13511357

tests/data_files/test-ca-nc.crt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIDSzCCAjOgAwIBAgIJAJx/NjT4C4viMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNV
3+
BAMMCExlZXZpQ0E0MB4XDTE4MDEyNzE1MDczMloXDTI4MDEyNTE1MDczMlowEzER
4+
MA8GA1UEAwwITGVldmlDQTQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
5+
AQDWN79RTlyFm5o0LVMSVjc68W0+gtl95xpaaD7IS6gDYjcbGnCwSefiq7y9rtck
6+
OM1A5Bzhj5+iWbmZStUmeJUhSGgxP/FxuUaAV0fsBGJ5jDrzmbhzDkHsNxDMB2ks
7+
XFyy4LfODcBs9TXxY43KUKuq/0meiT3WAaZWHMYle9vkQJM2l0RyH4IXHCHiIRwd
8+
2wntin6T9QOFJOc2ietNb7KsXVne81wb7h9BVMsjCIAsbPpHa+PZQs1xFuxmRxCs
9+
kpavnMy+SqevHhvqtvbHppcXYtZspTnkVoXWUdx3HHXgZMQKlAWlwyx57xpZBU2g
10+
qksO+KCLVYOQMN9usmuMOpHHAgMBAAGjgaEwgZ4wHQYDVR0eAQH/BBMwEaAPMA2C
11+
C2V4YW1wbGUuY29tMB0GA1UdDgQWBBR3T9IilPeRAFfLO8ocg216OBo+6DBDBgNV
12+
HSMEPDA6gBR3T9IilPeRAFfLO8ocg216OBo+6KEXpBUwEzERMA8GA1UEAwwITGVl
13+
dmlDQTSCCQCcfzY0+AuL4jAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjANBgkq
14+
hkiG9w0BAQsFAAOCAQEAR086ciNM3ujSQNhhguqFHYGfDRRuAgOk4l7GXIfFa9te
15+
B2KMLSwP367QaMwFxRrOoDvixIjzbpiiKB3cv+IXqGyfsRJw47XLwGK4FtSsXjst
16+
m2M8W5iXBQ94XoLj9OKb4ZJWKI930S/PF7uuxICtWttYSoylfyMkiR45+1SLj2eF
17+
X4EnXK3Q0H42v8LCDFqj9iNQ2WMLwA7kFPB+oOZxkFi2G0F3VuW+JZeBPQCpYdRO
18+
0kQQ/gIZE6KEdscKHi9y6OfGSeRlDBMADky9NiZy7I3AcspLcmMQh/191/DnooNe
19+
OwQ6w1HweApjB46bGyILpGUi9MZhvCnoLWg+cN3/wQ==
20+
-----END CERTIFICATE-----

tests/suites/test_suite_x509parse.data

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2518,6 +2518,12 @@ X509 File parse (trailing spaces, OK)
25182518
depends_on:MBEDTLS_ECDSA_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_SHA256_C:MBEDTLS_RSA_C
25192519
x509parse_crt_file:"data_files/server7_trailing_space.crt":0
25202520

2521+
X509 File parse (unsupported critical ext Name Constraints, fail)
2522+
x509parse_crt_file:"data_files/test-ca-nc.crt":MBEDTLS_ERR_X509_INVALID_EXTENSIONS + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG
2523+
2524+
X509 File parse (allowed unsupported critical ext Name Constraints, ok)
2525+
x509parse_crt_file_allow_exts:"data_files/test-ca-nc.crt":MBEDTLS_X509_EXT_NAME_CONSTRAINTS:0
2526+
25212527
X509 Get time (UTC no issues)
25222528
depends_on:MBEDTLS_X509_USE_C
25232529
x509_get_time:MBEDTLS_ASN1_UTC_TIME:"500101000000Z":0:1950:1:1:0:0:0

tests/suites/test_suite_x509parse.function

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -735,6 +735,21 @@ exit:
735735
}
736736
/* END_CASE */
737737

738+
/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_FS_IO */
739+
void x509parse_crt_file_allow_exts( char *crt_file, int exts, int result )
740+
{
741+
mbedtls_x509_crt crt;
742+
743+
mbedtls_x509_crt_init( &crt );
744+
crt.allowed_unsupported_critical_exts = exts;
745+
746+
TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == result );
747+
748+
exit:
749+
mbedtls_x509_crt_free( &crt );
750+
}
751+
/* END_CASE */
752+
738753
/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C */
739754
void x509parse_crt( data_t * buf, char * result_str, int result )
740755
{

0 commit comments

Comments
 (0)