diff --git a/ChangeLog.d/x509-basic-constraints-integer-first.txt b/ChangeLog.d/x509-basic-constraints-integer-first.txt new file mode 100644 index 0000000000..409a626aa0 --- /dev/null +++ b/ChangeLog.d/x509-basic-constraints-integer-first.txt @@ -0,0 +1,5 @@ +Bugfix + * Accept a basicConstraints extension that omits cA and contains only + pathLenConstraint, interpreting it as cA=FALSE as specified by RFC 5280. + This restores compatibility with certificates emitted by some devices + without accepting them as CA certificates. Fixes #11006. diff --git a/library/x509_crt.c b/library/x509_crt.c index a6fcd1b4e6..e3549a1c2b 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -518,17 +518,19 @@ static int x509_get_basic_constraints(unsigned char **p, } if ((ret = mbedtls_asn1_get_bool(p, end, ca_istrue)) != 0) { - /* If the SEQUENCE starts with an INTEGER and not a BOOLEAN, - * according to RFC 5280, it's syntactically valid, but it's - * something that a CA MUST NOT produce. So we reject it. + /* cA is DEFAULT FALSE. If it is absent, the first element must + * be pathLenConstraint. Keep cA false and let the INTEGER parser + * below validate the element. * * Note: historically, from XySSL 0.9 to Mbed TLS 3.6.6/4.1.0, * `SEQUENCE { INTEGER n }` was interpreted as cA=FALSE if n == 0 * and cA=TRUE if n != 0. This was dangerous since * `SEQUENCE { INTEGER n }` should be parsed as cA=FALSE - * according to RFC 5280, so we stopped doing it. + * according to RFC 5280. */ - return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); + } } /* `SEQUENCE { BOOLEAN FALSE }` is not DER since default-value fields * must be omitted in DER. But it seems harmless, and Mbed TLS has diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index b0cb873f2b..19ddc79a6f 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -2062,11 +2062,27 @@ mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-c X509 CRT ASN1: basicConstraints: no cA but pathLenConstraint (bad signature) depends_on:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 -mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-integer-first.badsign.crt":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG):0 +mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-integer-first.badsign.crt":0:1 + +X509 CRT ASN1: basicConstraints: no cA, pathLen only: not a CA +depends_on:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 +mbedtls_x509_get_ca_istrue:"../framework/data_files/parse_input/server5.basic-constraints-integer-first.badsign.crt":0 X509 CRT ASN1: basicConstraints: no cA but pathLenConstraint (good self signature) depends_on:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 -mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-integer-first.selfsigned.crt":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG):0 +mbedtls_x509_crt_parse_file:"../framework/data_files/parse_input/server5.basic-constraints-integer-first.selfsigned.crt":0:1 + +X509 CRT ASN1: basicConstraints: no cA but zero pathLenConstraint +depends_on:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 +x509_crt_parse_basic_constraints:"308201573081fea003020102020c53a2cb4b124ead837da894b2300a06082a8648ce3d040302300e310c300a06035504030c03457665301e170d3236303531323039353330345a170d3336303531323039353330345a300e310c300a06035504030c034576653059301306072a8648ce3d020106082a8648ce3d0301070342000437cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f768225962924ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edffa3423040300f0603551d130101ff04053003020100300e0603551d0f0101ff040403020780301d0603551d0e041604145061a58fd407d9d782010ce5657f8c6346a713be300a06082a8648ce3d0403020348003045022100d67d572af0aa540cd0f9d86d43788c178ca9501d8c0f4f6690c773f4b82c4b9a022011620feee62aca3944b8321636849030014ef80604550031312bb707b7f2bf04":0:0:0 + +X509 CRT ASN1: basicConstraints: invalid cA BOOLEAN length +depends_on:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 +x509_crt_parse_basic_constraints:"308201573081fea003020102020c53a2cb4b124ead837da894b2300a06082a8648ce3d040302300e310c300a06035504030c03457665301e170d3236303531323039353330345a170d3336303531323039353330345a300e310c300a06035504030c034576653059301306072a8648ce3d020106082a8648ce3d0301070342000437cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f768225962924ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edffa3423040300f0603551d130101ff040530030100ff300e0603551d0f0101ff040403020780301d0603551d0e041604145061a58fd407d9d782010ce5657f8c6346a713be300a06082a8648ce3d0403020348003045022100d67d572af0aa540cd0f9d86d43788c178ca9501d8c0f4f6690c773f4b82c4b9a022011620feee62aca3944b8321636849030014ef80604550031312bb707b7f2bf04":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_INVALID_LENGTH):0:0 + +X509 CRT ASN1: basicConstraints: neither cA nor pathLenConstraint +depends_on:PSA_HAVE_ALG_ECDSA_VERIFY:PSA_WANT_ECC_SECP_R1_256:PSA_WANT_ALG_SHA_256 +x509_crt_parse_basic_constraints:"308201573081fea003020102020c53a2cb4b124ead837da894b2300a06082a8648ce3d040302300e310c300a06035504030c03457665301e170d3236303531323039353330345a170d3336303531323039353330345a300e310c300a06035504030c034576653059301306072a8648ce3d020106082a8648ce3d0301070342000437cc56d976091e5a723ec7592dff206eee7cf9069174d0ad14b5f768225962924ee500d82311ffea2fd2345d5d16bd8a88c26b770d55cd8a2a0efa01c8b4edffa3423040300f0603551d130101ff04053003050100300e0603551d0f0101ff040403020780301d0603551d0e041604145061a58fd407d9d782010ce5657f8c6346a713be300a06082a8648ce3d0403020348003045022100d67d572af0aa540cd0f9d86d43788c178ca9501d8c0f4f6690c773f4b82c4b9a022011620feee62aca3944b8321636849030014ef80604550031312bb707b7f2bf04":MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG):0:0 X509 CRT ASN1 (TBS, inv extBasicConstraint, no pathlen length) depends_on:PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY:PSA_WANT_ALG_SHA_256 diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index 25d229d6f1..e095cb2b83 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -1127,6 +1127,28 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C */ +void x509_crt_parse_basic_constraints(data_t *buf, int result, + int ca_istrue, int path_len_constraint) +{ + mbedtls_x509_crt crt; + + mbedtls_x509_crt_init(&crt); + USE_PSA_INIT(); + + TEST_EQUAL(mbedtls_x509_crt_parse_der(&crt, buf->x, buf->len), result); + if (result == 0) { + TEST_EQUAL(mbedtls_x509_crt_get_ca_istrue(&crt), ca_istrue); + /* max_pathlen is 1 higher than pathLenConstraint. */ + TEST_EQUAL(crt.max_pathlen, path_len_constraint + 1); + } + +exit: + mbedtls_x509_crt_free(&crt); + USE_PSA_DONE(); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_X509_CRT_PARSE_C */ void x509parse_crt(data_t *buf, char *result_str, int result) {