From 288dedcc7221901d61ed355026839b3cfa82c543 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Wed, 27 Mar 2019 11:00:53 +0000 Subject: [PATCH 01/29] Add compile-time option to enable X.509 CA callbacks --- include/mbedtls/config.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 3a2fed5289..ed8bafa756 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1744,6 +1744,25 @@ */ //#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION +/** + * \def MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK + * + * If set, this enables the X.509 API `mbedtls_x509_crt_verify_with_cb()` + * and the SSL API `mbedtls_ssl_conf_ca_cb()` which allow users to configure + * the set of trusted certificates through a callback instead of a linked + * list. + * + * This is useful for example in environments where a large number of trusted + * certificates is present and storing them in a linked list isn't efficient + * enough, or when the set of trusted certificates changes frequently. + * + * See the documentation of `mbedtls_x509_crt_verify_with_cb()` and + * `mbedtls_ssl_conf_ca_cb()` for more information. + * + * Uncomment to enable trusted certificate callbacks. + */ +//#define MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK + /** * \def MBEDTLS_X509_CHECK_KEY_USAGE * From 5c8df78feb7716bf3b0a53b51451225432fae582 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Wed, 27 Mar 2019 11:01:17 +0000 Subject: [PATCH 02/29] Add X.509 CRT verification API using trusted CA callbacks --- include/mbedtls/x509_crt.h | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index b3f27be930..2e3e6e9a1e 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -501,6 +501,70 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, void *p_vrfy, mbedtls_x509_crt_restart_ctx *rs_ctx ); +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/** + * \brief The type of trusted certificate callbacks. + * + * Callbacks of this type are passed to and used by the CRT + * verification routine mbedtls_x509_crt_verify_with_cb() + * when looking for trusted signers of a given certificate. + * + * On success, the callback returns a list of trusted + * certificates to be considered as potential signers + * for the input certificate. + * + * \param p_ctx An opaque context passed to the callback. + * \param child The certificate for which to search a potential signer. + * This must point to a readable certificate. + * \param candidate_cas The address at which to store the address of the first + * entry in the generated linked list of candidate signers. + * This must not be \c NULL. + * + * \note The callback must only return a non-zero value on a + * fatal error. If, in contrast, the search for a potential + * signer completes without a single candidate, the + * callback must return \c 0 and get \c *candidate_cas + * to \c NULL. + * + * \return \c 0 on success. In this case, \c *candidate_cas points + * to a heap-allocated linked list of instances of + * ::mbedtls_x509_crt, and ownership of this list is passed + * to the caller. + * \return A negative error code on failure. + */ +typedef int (*mbedtls_x509_crt_ca_cb_t)( void *p_ctx, + mbedtls_x509_crt const *child, + mbedtls_x509_crt **candidate_cas ); +/** + * \brief Version of \c mbedtls_x509_crt_verify_with_profile() which + * uses a callback to acquire the list of trusted CA + * certificates. + * + * \param crt The certificate chain to be verified. + * \param f_ca_cb The callback to be used to query for potential signers + * of a given child certificate. See the documentation of + * ::mbedtls_x509_crt_ca_cb_t for more information. + * \param p_ca_cb The opaque context to be passed to \p f_ca_cb. + * \param profile The security profile for the verification. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * + * \return See \c mbedtls_crt_verify_with_profile(). + */ +int mbedtls_x509_crt_verify_with_cb( mbedtls_x509_crt *crt, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + #if defined(MBEDTLS_X509_CHECK_KEY_USAGE) /** * \brief Check usage of certificate against keyUsage extension. From 902451db8bcac27b75b4ee200f62d77677ef9c0f Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Wed, 27 Mar 2019 11:48:40 +0000 Subject: [PATCH 03/29] Improve documentation of old X.509 CRT verification functions This commit applies the documentation improvements noticed and applied while adding the documentation for the new X.509 CRT verification API mbedtls_x509_crt_verify_with_cb() to the existing verification APIs. --- include/mbedtls/x509_crt.h | 94 +++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 42 deletions(-) diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 2e3e6e9a1e..64ee66e55c 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -371,7 +371,7 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, uint32_t flags ); /** - * \brief Verify the certificate signature + * \brief Verify a chain of certificates. * * The verify callback is a user-supplied callback that * can clear / modify / add flags for a certificate. If set, @@ -411,22 +411,25 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, * specific peers you know) - in that case, the self-signed * certificate doesn't need to have the CA bit set. * - * \param crt a certificate (chain) to be verified - * \param trust_ca the list of trusted CAs (see note above) - * \param ca_crl the list of CRLs for trusted CAs (see note above) - * \param cn expected Common Name (can be set to - * NULL if the CN must not be verified) - * \param flags result of the verification - * \param f_vrfy verification function - * \param p_vrfy verification parameter + * \param crt The certificate chain to be verified. + * \param trust_ca The list of trusted CAs. + * \param ca_crl The list of CRLs for trusted CAs. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. * - * \return 0 (and flags set to 0) if the chain was verified and valid, - * MBEDTLS_ERR_X509_CERT_VERIFY_FAILED if the chain was verified - * but found to be invalid, in which case *flags will have one - * or more MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX - * flags set, or another error (and flags set to 0xffffffff) - * in case of a fatal error encountered during the - * verification process. + * \return \c 0 if the chain is valid with respect to the + * passed CN, CAs, CRLs and security profile. + * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the + * certificate chain verification failed. In this case, + * \c *flags will have one or more + * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX + * flags set. + * \return Another negative error code in case of a fatal error + * encountered during the verification process. */ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, @@ -436,7 +439,8 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, void *p_vrfy ); /** - * \brief Verify the certificate signature according to profile + * \brief Verify a chain of certificates with respect to + * a configurable security profile. * * \note Same as \c mbedtls_x509_crt_verify(), but with explicit * security profile. @@ -445,22 +449,26 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, * for ECDSA) apply to all certificates: trusted root, * intermediate CAs if any, and end entity certificate. * - * \param crt a certificate (chain) to be verified - * \param trust_ca the list of trusted CAs - * \param ca_crl the list of CRLs for trusted CAs - * \param profile security profile for verification - * \param cn expected Common Name (can be set to - * NULL if the CN must not be verified) - * \param flags result of the verification - * \param f_vrfy verification function - * \param p_vrfy verification parameter + * \param crt The certificate chain to be verified. + * \param trust_ca The list of trusted CAs. + * \param ca_crl The list of CRLs for trusted CAs. + * \param profile The security profile to use for the verification. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. * - * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED - * in which case *flags will have one or more - * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags - * set, - * or another error in case of a fatal error encountered - * during the verification process. + * \return \c 0 if the chain is valid with respect to the + * passed CN, CAs, CRLs and security profile. + * \return #MBEDTLS_ERR_X509_CERT_VERIFY_FAILED in case the + * certificate chain verification failed. In this case, + * \c *flags will have one or more + * \c MBEDTLS_X509_BADCERT_XXX or \c MBEDTLS_X509_BADCRL_XXX + * flags set. + * \return Another negative error code in case of a fatal error + * encountered during the verification process. */ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, @@ -477,16 +485,18 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, * but can return early and restart according to the limit * set with \c mbedtls_ecp_set_max_ops() to reduce blocking. * - * \param crt a certificate (chain) to be verified - * \param trust_ca the list of trusted CAs - * \param ca_crl the list of CRLs for trusted CAs - * \param profile security profile for verification - * \param cn expected Common Name (can be set to - * NULL if the CN must not be verified) - * \param flags result of the verification - * \param f_vrfy verification function - * \param p_vrfy verification parameter - * \param rs_ctx restart context (NULL to disable restart) + * \param crt The certificate chain to be verified. + * \param trust_ca The list of trusted CAs. + * \param ca_crl The list of CRLs for trusted CAs. + * \param profile The security profile to use for the verification. + * \param cn The expected Common Name. This may be \c NULL if the + * CN need not be verified. + * \param flags The address at which to store the result of the verification. + * \param f_vrfy The verification callback to use. See the documentation + * of mbedtls_x509_crt_verify() for more information. + * \param p_vrfy The context to be passed to \p f_vrfy. + * \param rs_ctx The restart context to use. This may be set to \c NULL + * to disable restartable ECC. * * \return See \c mbedtls_crt_verify_with_profile(), or * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of From 8bf74f37dca6af98c3aa7e7a050fcec4fc8a9510 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Wed, 27 Mar 2019 11:01:30 +0000 Subject: [PATCH 04/29] Add SSL configuration API for trusted CA callbacks --- include/mbedtls/ssl.h | 57 +++++++++++++++++++++++++++++++++++++++++++ library/ssl_srv.c | 5 ++++ 2 files changed, 62 insertions(+) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index b793ac04bc..d1ba608dab 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2071,6 +2071,63 @@ void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, mbedtls_x509_crt *ca_chain, mbedtls_x509_crl *ca_crl ); +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/** + * \brief Set the trusted certificate callback. + * + * This API allows to register the set of trusted certificates + * through a callback, instead of a linked list as configured + * by mbedtls_ssl_conf_ca_chain(). + * + * This is useful for example in contexts where a large number + * of CAs are used, and the inefficiency of maintaining them + * in a linked list cannot be tolerated. It is also useful when + * the set of trusted CAs needs to be modified frequently. + * + * See the documentation of `mbedtls_x509_crt_ca_cb_t` for + * more information. + * + * \param conf The SSL configuration to register the callback with. + * \param f_ca_cb The trusted certificate callback to use when verifying + * certificate chains. + * \param p_ca_cb The context to be passed to \p f_ca_cb (for example, + * a reference to a trusted CA database). + * + * \note This API is incompatible with mbedtls_ssl_conf_ca_chain(): + * Any call to this function overwrites the values set through + * earlier calls to mbedtls_ssl_conf_ca_chain() or + * mbedtls_ssl_conf_ca_cb(). + * + * \note This API is incompatible with CA indication in + * CertificateRequest messages: A server-side SSL context which + * is bound to an SSL configuration that uses a CA callback + * configured via mbedtls_ssl_conf_ca_cb(), and which requires + * client authentication, will send an empty CA list in the + * corresponding CertificateRequest message. + * + * \note This API is incompatible with mbedtls_ssl_set_hs_ca_chain(): + * If an SSL context is bound to an SSL configuration which uses + * CA callbacks configured via mbedtls_ssl_conf_ca_cb(), then + * calls to mbedtls_ssl_set_hs_ca_chain() have no effect. + * + * \note The use of this API disables the use of restartable ECC + * during X.509 CRT signature verification (but doesn't affect + * other uses). + * + * \warning This API is incompatible with the use of CRLs. Any call to + * mbedtls_ssl_conf_ca_cb() unsets CRLs configured through + * earlier calls to mbedtls_ssl_conf_ca_chain(). + * + * \warning In multi-threaded environments, the callback \p f_ca_cb + * must be thread-safe, and it is the user's responsibility + * to guaranteee this (for example through a mutex + * contained in the callback context pointed to by \p p_ca_cb). + */ +void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb ); +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + /** * \brief Set own certificate chain and private key * diff --git a/library/ssl_srv.c b/library/ssl_srv.c index c969089566..b8e10d6dcf 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -2818,6 +2818,11 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl ) if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED ) { + /* NOTE: If trusted certificates are provisioned + * via a CA callback (configured through + * `mbedtls_ssl_conf_ca_cb()`, then the + * CertificateRequest is currently left empty. */ + #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) if( ssl->handshake->sni_ca_chain != NULL ) crt = ssl->handshake->sni_ca_chain; From 03cd120ce4f8d4d66b74e72bbef2e7c1689a4091 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Wed, 27 Mar 2019 15:45:04 +0200 Subject: [PATCH 05/29] Test for ca list callback --- tests/suites/test_suite_x509parse.function | 27 ++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index 4a826082bd..6b93a5fe15 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -68,6 +68,25 @@ int verify_all( void *data, mbedtls_x509_crt *crt, int certificate_depth, uint32 return 0; } +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +int verify_cb( void *data, mbedtls_x509_crt *child, mbedtls_x509_crt **candidates) +{ + mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data; + + mbedtls_x509_crt *first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + TEST_ASSERT( first != NULL); + TEST_ASSERT( mbedtls_x509_crt_init( first ) == 0 ); + TEST_ASSERT( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) == 0); + while( ca->next != NULL ) + { + ca = ca->next; + TEST_ASSERT( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) == 0); + } + *candidates = first; + return 0; +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + int verify_fatal( void *data, mbedtls_x509_crt *crt, int certificate_depth, uint32_t *flags ) { int *levels = (int *) data; @@ -374,6 +393,14 @@ void x509_verify( char *crt_file, char *ca_file, char *crl_file, TEST_ASSERT( res == ( result ) ); TEST_ASSERT( flags == (uint32_t)( flags_result ) ); +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + flags = 0; + + res = mbedtls_x509_crt_verify_with_cb( &crt, verify_cb, &ca, profile, cn_name, &flags, f_vrfy, NULL ); + + TEST_ASSERT( res == ( result ) ); + TEST_ASSERT( flags == (uint32_t)( flags_result ) ); +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ exit: mbedtls_x509_crt_free( &crt ); mbedtls_x509_crt_free( &ca ); From 912ed3399191860991d154a8a1dcef5163eb125d Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Wed, 27 Mar 2019 15:57:15 +0200 Subject: [PATCH 06/29] Change callback name to ca_callback --- tests/suites/test_suite_x509parse.function | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index 6b93a5fe15..f62b0a641d 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -69,7 +69,7 @@ int verify_all( void *data, mbedtls_x509_crt *crt, int certificate_depth, uint32 } #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) -int verify_cb( void *data, mbedtls_x509_crt *child, mbedtls_x509_crt **candidates) +int ca_callback( void *data, mbedtls_x509_crt *child, mbedtls_x509_crt **candidates) { mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data; @@ -396,7 +396,7 @@ void x509_verify( char *crt_file, char *ca_file, char *crl_file, #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) flags = 0; - res = mbedtls_x509_crt_verify_with_cb( &crt, verify_cb, &ca, profile, cn_name, &flags, f_vrfy, NULL ); + res = mbedtls_x509_crt_verify_with_cb( &crt, ca_callback, &ca, profile, cn_name, &flags, f_vrfy, NULL ); TEST_ASSERT( res == ( result ) ); TEST_ASSERT( flags == (uint32_t)( flags_result ) ); From 557426ad770fdbeaac8a622baaf27d120235d544 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Wed, 27 Mar 2019 17:08:29 +0200 Subject: [PATCH 07/29] Add a failure testcase for ca callback --- tests/suites/test_suite_x509parse.data | 4 +++ tests/suites/test_suite_x509parse.function | 36 ++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 042d653b51..38a75daf11 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -827,6 +827,10 @@ X509 Certificate verification #97 (next profile Valid Cert SHA256 Digest) depends_on:MBEDTLS_SHA256_C:MBEDTLS_PEM_PARSE_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_ECDSA_C:MBEDTLS_SHA1_C x509_verify:"data_files/cert_sha256.crt":"data_files/test-ca.crt":"data_files/crl-ec-sha256.pem":"NULL":0:0:"next":"NULL" +X509 Certificate verification with ca callback: failure +depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +x509_verify_ca_cb_failure:"data_files/server1.crt":"data_files/test-ca.crt":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:"depth 1 - serial 03 - subject C=NL, O=PolarSSL, CN=PolarSSL Test CA - flags 0x00000000\ndepth 0 - serial 01 - subject C=NL, O=PolarSSL, CN=PolarSSL Server 1 - flags 0x00000000\n" + X509 Certificate verification callback: bad name depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED x509_verify_callback:"data_files/server5.crt":"data_files/test-ca2.crt":"globalhost":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:"depth 1 - serial C1\:43\:E2\:7E\:62\:43\:CC\:E8 - subject C=NL, O=PolarSSL, CN=Polarssl Test EC CA - flags 0x00000000\ndepth 0 - serial 09 - subject C=NL, O=PolarSSL, CN=localhost - flags 0x00000004\n" diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index f62b0a641d..d7745a9012 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -69,6 +69,15 @@ int verify_all( void *data, mbedtls_x509_crt *crt, int certificate_depth, uint32 } #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +int ca_callback_fail( void *data, mbedtls_x509_crt *child, mbedtls_x509_crt **candidates) +{ + ((void) data); + ((void) child); + ((void) candidates); + + return -1; +} + int ca_callback( void *data, mbedtls_x509_crt *child, mbedtls_x509_crt **candidates) { mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data; @@ -408,6 +417,33 @@ exit: } /* END_CASE */ +/* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_X509_CRL_PARSE_C:MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +void x509_verify_ca_cb_failure( char *crt_file, char *ca_file, char *name, + int exp_ret, char *exp_vrfy_out ) +{ + int ret; + mbedtls_x509_crt crt; + mbedtls_x509_crt ca; + uint32_t flags = 0; + + mbedtls_x509_crt_init( &crt ); + mbedtls_x509_crt_init( &ca ); + + TEST_ASSERT( mbedtls_x509_crt_parse_file( &crt, crt_file ) == 0 ); + TEST_ASSERT( mbedtls_x509_crt_parse_file( &ca, ca_file ) == 0 ); + + if( strcmp( name, "NULL" ) == 0 ) + name = NULL; + + ret = mbedtls_x509_crt_verify_with_cb( &crt, ca_callback_fail, &ca, &compat_profile, name, &flags, verify_all, NULL ); + + TEST_ASSERT( ret == exp_ret ); +exit: + mbedtls_x509_crt_free( &crt ); + mbedtls_x509_crt_free( &ca ); +} +/* END_CASE */ + /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C */ void x509_verify_callback( char *crt_file, char *ca_file, char *name, int exp_ret, char *exp_vrfy_out ) From 1b4a2bad7ab78f45f951f1129769a9c25ac0b8b8 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Wed, 27 Mar 2019 17:55:27 +0200 Subject: [PATCH 08/29] Add possibility to use ca_callbacks in ssl programs --- programs/ssl/ssl_client2.c | 46 +++++++++++++++++++++++++++++++++++++- programs/ssl/ssl_server2.c | 46 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 89 insertions(+), 3 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index f7e24598d2..2e297e3621 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -122,6 +122,8 @@ int main( void ) #define DFL_FALLBACK -1 #define DFL_EXTENDED_MS -1 #define DFL_ETM -1 +#define DFL_CA_CALLBACK 0 + #define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: " #define GET_REQUEST_END "\r\n\r\n" @@ -169,6 +171,13 @@ int main( void ) #else #define USAGE_PSK_SLOT "" #endif /* MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +#define USAGE_CA_CALLBACK \ + " ca_callback=%%d default: 0 (disabled)\n" \ + " Enable this to use the trusted certificate callback function\n" +#else +#define USAGE_CA_CALLBACK "" +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #define USAGE_PSK USAGE_PSK_RAW USAGE_PSK_SLOT #else #define USAGE_PSK "" @@ -312,6 +321,7 @@ int main( void ) " options: none, optional, required\n" \ USAGE_IO \ USAGE_KEY_OPAQUE \ + USAGE_CA_CALLBACK \ "\n" \ USAGE_PSK \ USAGE_ECJPAKE \ @@ -385,6 +395,9 @@ struct options int key_opaque; /* handle private key as if it were opaque */ #if defined(MBEDTLS_USE_PSA_CRYPTO) int psk_opaque; +#endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + int use_ca_callback /* Use a callback for a trusted certificate list */ #endif const char *psk; /* the pre-shared key */ const char *psk_identity; /* the pre-shared key identity */ @@ -439,6 +452,25 @@ static void my_debug( void *ctx, int level, fflush( (FILE *) ctx ); } +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +int ca_callback( void *data, mbedtls_x509_crt *child, mbedtls_x509_crt **candidates) +{ + mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data; + + mbedtls_x509_crt *first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + TEST_ASSERT( first != NULL); + TEST_ASSERT( mbedtls_x509_crt_init( first ) == 0 ); + TEST_ASSERT( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) == 0); + while( ca->next != NULL ) + { + ca = ca->next; + TEST_ASSERT( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) == 0); + } + *candidates = first; + return 0; +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + /* * Test recv/send functions that make sure each try returns * WANT_READ/WANT_WRITE at least once before sucesseding @@ -697,6 +729,9 @@ int main( int argc, char *argv[] ) opt.psk = DFL_PSK; #if defined(MBEDTLS_USE_PSA_CRYPTO) opt.psk_opaque = DFL_PSK_OPAQUE; +#endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + opt.ca_callback = DFL_CA_CALLBACK; #endif opt.psk_identity = DFL_PSK_IDENTITY; opt.ecjpake_pw = DFL_ECJPAKE_PW; @@ -805,6 +840,10 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_USE_PSA_CRYPTO) else if( strcmp( p, "psk_opaque" ) == 0 ) opt.psk_opaque = atoi( q ); +#endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + else if( strcmp( p, "ca_callback" ) == 0) + opt.ca_callback = atoi( q ); #endif else if( strcmp( p, "psk_identity" ) == 0 ) opt.psk_identity = q; @@ -1600,7 +1639,12 @@ int main( int argc, char *argv[] ) if( strcmp( opt.ca_path, "none" ) != 0 && strcmp( opt.ca_file, "none" ) != 0 ) { - mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( opt.ca_callback != 0 ) + mbedtls_ssl_conf_ca_cb( &conf, ca_callback, &cacert); + else +#endif + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); } if( strcmp( opt.crt_file, "none" ) != 0 && strcmp( opt.key_file, "none" ) != 0 ) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 7858db3052..887fe4e96f 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -166,6 +166,7 @@ int main( void ) #define DFL_DGRAM_PACKING 1 #define DFL_EXTENDED_MS -1 #define DFL_ETM -1 +#define DFL_CA_CALLBACK 0 #define LONG_RESPONSE "

01-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ "02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ @@ -264,7 +265,13 @@ int main( void ) #else #define USAGE_PSK "" #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ - +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +#define USAGE_CA_CALLBACK \ + " ca_callback=%%d default: 0 (disabled)\n" \ + " Enable this to use the trusted certificate callback function\n" +#else +#define USAGE_CA_CALLBACK "" +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) #define USAGE_TICKETS \ " tickets=%%d default: 1 (enabled)\n" \ @@ -420,6 +427,7 @@ int main( void ) USAGE_SNI \ "\n" \ USAGE_PSK \ + USAGE_CA_CALLBACK \ USAGE_ECJPAKE \ "\n" \ " allow_legacy=%%d default: (library default: no)\n" \ @@ -506,6 +514,9 @@ struct options #if defined(MBEDTLS_USE_PSA_CRYPTO) int psk_opaque; int psk_list_opaque; +#endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + int use_ca_callback /* Use a callback for a trusted certificate list */ #endif const char *psk; /* the pre-shared key */ const char *psk_identity; /* the pre-shared key identity */ @@ -564,6 +575,25 @@ static void my_debug( void *ctx, int level, fflush( (FILE *) ctx ); } +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +int ca_callback( void *data, mbedtls_x509_crt *child, mbedtls_x509_crt **candidates) +{ + mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data; + + mbedtls_x509_crt *first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + TEST_ASSERT( first != NULL); + TEST_ASSERT( mbedtls_x509_crt_init( first ) == 0 ); + TEST_ASSERT( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) == 0); + while( ca->next != NULL ) + { + ca = ca->next; + TEST_ASSERT( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) == 0); + } + *candidates = first; + return 0; +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + /* * Test recv/send functions that make sure each try returns * WANT_READ/WANT_WRITE at least once before sucesseding @@ -1457,6 +1487,9 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_USE_PSA_CRYPTO) opt.psk_opaque = DFL_PSK_OPAQUE; opt.psk_list_opaque = DFL_PSK_LIST_OPAQUE; +#endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + opt.ca_callback = DFL_CA_CALLBACK; #endif opt.psk_identity = DFL_PSK_IDENTITY; opt.psk_list = DFL_PSK_LIST; @@ -1591,6 +1624,10 @@ int main( int argc, char *argv[] ) opt.psk_opaque = atoi( q ); else if( strcmp( p, "psk_list_opaque" ) == 0 ) opt.psk_list_opaque = atoi( q ); +#endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + else if( strcmp( p, "ca_callback" ) == 0) + opt.ca_callback = atoi( q ); #endif else if( strcmp( p, "psk_identity" ) == 0 ) opt.psk_identity = q; @@ -2570,7 +2607,12 @@ int main( int argc, char *argv[] ) if( strcmp( opt.ca_path, "none" ) != 0 && strcmp( opt.ca_file, "none" ) != 0 ) { - mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( opt.ca_callback != 0 ) + mbedtls_ssl_conf_ca_cb( &conf, ca_callback, &cacert); + else +#endif + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); } if( key_cert_init ) { From 5adaad98467ef7becfcf3333412640b564f5d3e2 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Wed, 27 Mar 2019 16:54:37 +0000 Subject: [PATCH 09/29] Add X.509 CA callback to SSL configuration and implement setter API --- include/mbedtls/ssl.h | 4 ++++ library/ssl_tls.c | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index d1ba608dab..aabbb83cd9 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -928,6 +928,10 @@ struct mbedtls_ssl_config mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */ mbedtls_x509_crt *ca_chain; /*!< trusted CAs */ mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + mbedtls_x509_crt_ca_cb_t f_ca_cb; + void *p_ca_cb; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_ASYNC_PRIVATE) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 660d548e45..01f5dcceab 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -7875,7 +7875,29 @@ void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, { conf->ca_chain = ca_chain; conf->ca_crl = ca_crl; + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() + * cannot be used together. */ + conf->f_ca_cb = NULL; + conf->p_ca_cb = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ } + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf, + mbedtls_x509_ca_cb_t f_ca_cb, + void *p_ca_cb ) +{ + conf->f_ca_cb = f_ca_cb; + conf->p_ca_cb = p_ca_cb; + + /* mbedtls_ssl_conf_ca_chain() and mbedtls_ssl_conf_ca_cb() + * cannot be used together. */ + conf->ca_chain = NULL; + conf->ca_crl = NULL; +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) From afd0b0a1a7165b78e21a864754eafbd70c98d0c0 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Wed, 27 Mar 2019 16:55:01 +0000 Subject: [PATCH 10/29] Make use of CA callback if present when verifying peer CRT chain --- library/ssl_tls.c | 73 +++++++++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 24 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 01f5dcceab..3064b52491 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -6035,35 +6035,60 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, int ret = 0; const mbedtls_ssl_ciphersuite_t *ciphersuite_info = ssl->transform_negotiate->ciphersuite_info; - mbedtls_x509_crt *ca_chain; - mbedtls_x509_crl *ca_crl; + int have_ca_chain = 0; if( authmode == MBEDTLS_SSL_VERIFY_NONE ) return( 0 ); -#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) - if( ssl->handshake->sni_ca_chain != NULL ) - { - ca_chain = ssl->handshake->sni_ca_chain; - ca_crl = ssl->handshake->sni_ca_crl; - } - else -#endif - { - ca_chain = ssl->conf->ca_chain; - ca_crl = ssl->conf->ca_crl; - } - /* * Main check: verify certificate */ - ret = mbedtls_x509_crt_verify_restartable( - chain, - ca_chain, ca_crl, - ssl->conf->cert_profile, - ssl->hostname, - &ssl->session_negotiate->verify_result, - ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx ); +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( ssl->conf->f_ca_cb != NULL ) + { + ((void) rs_ctx); + have_ca_chain = 1; + + MBEDTLS_SSL_DEBUG_MSG( 3, ( "use CA callback for X.509 CRT verification" ) ); + ret = mbedtls_x509_crt_verify_with_cb( + chain, + ssl->conf->f_ca_cb, + ssl->conf->p_ca_cb, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + ssl->conf->f_vrfy, ssl->conf->p_vrfy ); + } + else +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + { + mbedtls_x509_crt *ca_chain; + mbedtls_x509_crl *ca_crl; + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) + if( ssl->handshake->sni_ca_chain != NULL ) + { + ca_chain = ssl->handshake->sni_ca_chain; + ca_crl = ssl->handshake->sni_ca_crl; + } + else +#endif + { + ca_chain = ssl->conf->ca_chain; + ca_crl = ssl->conf->ca_crl; + } + + if( ca_chain != NULL ) + have_ca_chain = 1; + + ret = mbedtls_x509_crt_verify_restartable( + chain, + ca_chain, ca_crl, + ssl->conf->cert_profile, + ssl->hostname, + &ssl->session_negotiate->verify_result, + ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx ); + } if( ret != 0 ) { @@ -6119,7 +6144,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, ret = 0; } - if( ca_chain == NULL && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) + if( have_ca_chain == 0 && authmode == MBEDTLS_SSL_VERIFY_REQUIRED ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no CA chain" ) ); ret = MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED; @@ -7886,7 +7911,7 @@ void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf, - mbedtls_x509_ca_cb_t f_ca_cb, + mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb ) { conf->f_ca_cb = f_ca_cb; From 3116fb362c72490b3e3427b0535c7bb25d4ea89a Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 28 Mar 2019 13:34:42 +0000 Subject: [PATCH 11/29] Add prototype for CRT verification with static and dynamic CA list So far, there were the following CRT verification functions: - `mbedtls_x509_crt_verify()` -- no profile, no restartable ECC - `mbedtls_x509_crt_verify_with_profile()` -- profile, no restartable ECC - `mbedtls_x509_crt_verify_restartable()` -- profile, restartable ECC all publicly declared and offering increasing functionality. On the implementation-side, - `mbedtls_x509_crt_verify()` resolves to a call to `mbedtls_x509_crt_verify_with_profile()` setting the profile to `NULL`, and - `mbedtls_x509_crt_verify_with_profile()` resolves to a call to ``mbedtls_x509_crt_verify_restartable()` setting the ECC restart context to NULL. This commit adds two more functions to this zoo: - `mbedtls_x509_crt_verify_with_cb()` - `x509_crt_verify_restartable_cb()` Here, `mbedtls_x509_crt_verify_with_cb()` is similar to `mbedtls_x509_crt_verify_with_profile()` but uses a CA callback instead of a static CA list, and no restart context. `x509_crt_verify_restartable_cb()` is similar to `mbedtls_x509_crt_verify_restartable()` but allows to either use a static list of trusted CAs _or_ a trusted CA callback. On the implementation-side, - the body of `mbedtls_x509_crt_verify_restartable()` is moved to `x509_crt_verify_restartable_cb()`, and the new version of `mbedtls_x509_crt_verify_restartable()` just resolves to `x509_crt_verify_restartable_cb()` with the trusted CA callback set to NULL. - The new function `mbedtls_x509_crt_verify_with_cb()` forward to `x509_crt_verify_restartable_cb()` with the restart context set to `NULL`. There's no change to the implementation yet, and in particular, `mbedtls_x509_crt_verify_with_cb()` isn't yet usable. --- library/x509_crt.c | 117 ++++++++++++++++++++++++++++++++------------- 1 file changed, 85 insertions(+), 32 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index 5d82816f2b..1e6cb8ec65 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2309,6 +2309,8 @@ static int x509_crt_verify_chain( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, const mbedtls_x509_crt_profile *profile, mbedtls_x509_crt_verify_chain *ver_chain, mbedtls_x509_crt_restart_ctx *rs_ctx ) @@ -2539,36 +2541,6 @@ static int x509_crt_merge_flags_with_cb( return( 0 ); } -/* - * Verify the certificate validity (default profile, not restartable) - */ -int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl, - &mbedtls_x509_crt_profile_default, cn, flags, - f_vrfy, p_vrfy, NULL ) ); -} - -/* - * Verify the certificate validity (user-chosen profile, not restartable) - */ -int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, - mbedtls_x509_crt *trust_ca, - mbedtls_x509_crl *ca_crl, - const mbedtls_x509_crt_profile *profile, - const char *cn, uint32_t *flags, - int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), - void *p_vrfy ) -{ - return( mbedtls_x509_crt_verify_restartable( crt, trust_ca, ca_crl, - profile, cn, flags, f_vrfy, p_vrfy, NULL ) ); -} - /* * Verify the certificate validity, with profile, restartable version * @@ -2578,10 +2550,19 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, * as that isn't done as part of chain building/verification currently * - builds and verifies the chain * - then calls the callback and merges the flags + * + * The parameters pairs `trust_ca`, `ca_crl` and `f_ca_cb`, `p_ca_cb` + * are mutually exclusive: If `f_ca_cb != NULL`, it will be used by the + * verification routine to search for trusted signers, and CRLs will + * be disabled. Otherwise, `trust_ca` will be used as the static list + * of trusted signers, and `ca_crl` will be use as the static list + * of CRLs. */ -int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, +static int mbedtls_x509_crt_verify_restartable_cb( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, const mbedtls_x509_crt_profile *profile, const char *cn, uint32_t *flags, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), @@ -2617,7 +2598,8 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; /* Check the chain */ - ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile, + ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, + f_ca_cb, p_ca_cb, profile, &ver_chain, rs_ctx ); if( ret != 0 ) @@ -2653,6 +2635,77 @@ exit: return( 0 ); } + +/* + * Verify the certificate validity (default profile, not restartable) + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( mbedtls_x509_crt_verify_restartable_cb( crt, trust_ca, ca_crl, + NULL, NULL, + &mbedtls_x509_crt_profile_default, + cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} + +/* + * Verify the certificate validity (user-chosen profile, not restartable) + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( mbedtls_x509_crt_verify_restartable_cb( crt, trust_ca, ca_crl, + NULL, NULL, + profile, cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +/* + * Verify the certificate validity (user-chosen profile, CA callback, + * not restartable). + */ +int mbedtls_x509_crt_verify_with_cb( mbedtls_x509_crt *crt, + mbedtls_x509_crt_ca_cb_t f_ca_cb, + void *p_ca_cb, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( mbedtls_x509_crt_verify_restartable_cb( crt, NULL, NULL, + f_ca_cb, p_ca_cb, + profile, cn, flags, + f_vrfy, p_vrfy, NULL ) ); +} +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy, + mbedtls_x509_crt_restart_ctx *rs_ctx ) +{ + return( mbedtls_x509_crt_verify_restartable_cb( crt, trust_ca, ca_crl, + NULL, NULL, + profile, cn, flags, + f_vrfy, p_vrfy, rs_ctx ) ); +} + + /* * Initialize a certificate chain */ From f53893b00ca418f51639ef5f9d99ccade3a5fcd3 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 28 Mar 2019 13:45:55 +0000 Subject: [PATCH 12/29] Implement X.509 CRT verification using CA callback --- include/mbedtls/x509_crt.h | 8 ++++++++ library/x509_crt.c | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 64ee66e55c..c38ddc77fc 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -166,6 +166,14 @@ typedef struct { mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE]; unsigned len; + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + /* This stores the list of potential trusted signers obtained from + * the CA callback used for the CRT verification, if configured. + * We must track it somewhere because the callback passes its + * ownership to the caller. */ + mbedtls_x509_crt *trust_ca_cb_result; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ } mbedtls_x509_crt_verify_chain; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) diff --git a/library/x509_crt.c b/library/x509_crt.c index 1e6cb8ec65..b74ebffa2b 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -377,6 +377,10 @@ static void x509_crt_verify_chain_reset( } ver_chain->len = 0; + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + ver_chain->trust_ca_cb_result = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ } /* @@ -2326,6 +2330,7 @@ static int x509_crt_verify_chain( int child_is_trusted; int signature_is_good; unsigned self_cnt; + mbedtls_x509_crt *cur_trust_ca = NULL; #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) /* resume if we had an operation in progress */ @@ -2385,8 +2390,32 @@ static int x509_crt_verify_chain( #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) find_parent: #endif + + /* Obtain list of potential trusted signers from CA callback, + * or use statically provided list. */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( f_ca_cb != NULL ) + { + mbedtls_x509_crt_free( ver_chain->trust_ca_cb_result ); + mbedtls_free( ver_chain->trust_ca_cb_result ); + ver_chain->trust_ca_cb_result = NULL; + + ret = f_ca_cb( p_ca_cb, child, &ver_chain->trust_ca_cb_result ); + if( ret != 0 ) + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + + cur_trust_ca = ver_chain->trust_ca_cb_result; + } + else +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + { + ((void) f_ca_cb); + ((void) p_ca_cb); + cur_trust_ca = trust_ca; + } + /* Look for a parent in trusted CAs or up the chain */ - ret = x509_crt_find_parent( child, trust_ca, &parent, + ret = x509_crt_find_parent( child, cur_trust_ca, &parent, &parent_is_trusted, &signature_is_good, ver_chain->len - 1, self_cnt, rs_ctx ); @@ -2612,6 +2641,13 @@ static int mbedtls_x509_crt_verify_restartable_cb( mbedtls_x509_crt *crt, ret = x509_crt_merge_flags_with_cb( flags, &ver_chain, f_vrfy, p_vrfy ); exit: + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + mbedtls_x509_crt_free( ver_chain.trust_ca_cb_result ); + mbedtls_free( ver_chain.trust_ca_cb_result ); + ver_chain.trust_ca_cb_result = NULL; +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + #if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) if( rs_ctx != NULL && ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) mbedtls_x509_crt_restart_free( rs_ctx ); From e15dae7fcf15ec3a09fd12fd651f07fb7e071ea9 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 28 Mar 2019 13:55:38 +0000 Subject: [PATCH 13/29] Declare CA callback type even if feature is disabled --- include/mbedtls/x509_crt.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index c38ddc77fc..800e64ba8d 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -519,7 +519,6 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, void *p_vrfy, mbedtls_x509_crt_restart_ctx *rs_ctx ); -#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /** * \brief The type of trusted certificate callbacks. * @@ -553,6 +552,8 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, typedef int (*mbedtls_x509_crt_ca_cb_t)( void *p_ctx, mbedtls_x509_crt const *child, mbedtls_x509_crt **candidate_cas ); + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /** * \brief Version of \c mbedtls_x509_crt_verify_with_profile() which * uses a callback to acquire the list of trusted CA From cbb590369c554c294b885c52b8a57774d810a1d9 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 28 Mar 2019 14:14:22 +0000 Subject: [PATCH 14/29] Minor fixes to CA callback tests --- programs/ssl/ssl_client2.c | 57 ++++++++++++++++---- programs/ssl/ssl_server2.c | 55 +++++++++++++++---- tests/suites/test_suite_x509parse.data | 2 +- tests/suites/test_suite_x509parse.function | 63 +++++++++++++++++----- 4 files changed, 145 insertions(+), 32 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 2e297e3621..0540c65895 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -397,7 +397,7 @@ struct options int psk_opaque; #endif #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - int use_ca_callback /* Use a callback for a trusted certificate list */ + int ca_callback; /* Use callback for trusted certificate list */ #endif const char *psk; /* the pre-shared key */ const char *psk_identity; /* the pre-shared key identity */ @@ -453,21 +453,58 @@ static void my_debug( void *ctx, int level, } #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) -int ca_callback( void *data, mbedtls_x509_crt *child, mbedtls_x509_crt **candidates) +int ca_callback( void *data, mbedtls_x509_crt const *child, + mbedtls_x509_crt **candidates) { + int ret = 0; mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data; - - mbedtls_x509_crt *first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); - TEST_ASSERT( first != NULL); - TEST_ASSERT( mbedtls_x509_crt_init( first ) == 0 ); - TEST_ASSERT( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) == 0); + mbedtls_x509_crt *first; + + /* This is a test-only implementation of the CA callback + * which always returns the entire list of trusted certificates. + * Production implementations managing a large number of CAs + * should use an efficient presentation and lookup for the + * set of trusted certificates (such as a hashtable) and only + * return those trusted certificates which satisfy basic + * parental checks, such as the matching of child `Issuer` + * and parent `Subject` field. */ + ((void) child); + + first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + if( first == NULL ) + { + ret = -1; + goto exit; + } + mbedtls_x509_crt_init( first ); + + if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 ) + { + ret = -1; + goto exit; + } + while( ca->next != NULL ) { ca = ca->next; - TEST_ASSERT( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) == 0); + if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 ) + { + ret = -1; + goto exit; + } } + +exit: + + if( ret != 0 ) + { + mbedtls_x509_crt_free( first ); + mbedtls_free( first ); + first = NULL; + } + *candidates = first; - return 0; + return( ret ); } #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ @@ -1641,7 +1678,7 @@ int main( int argc, char *argv[] ) { #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) if( opt.ca_callback != 0 ) - mbedtls_ssl_conf_ca_cb( &conf, ca_callback, &cacert); + mbedtls_ssl_conf_ca_cb( &conf, ca_callback, &cacert ); else #endif mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 887fe4e96f..476a6728ab 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -516,7 +516,7 @@ struct options int psk_list_opaque; #endif #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - int use_ca_callback /* Use a callback for a trusted certificate list */ + int ca_callback; /* Use callback for trusted certificate list */ #endif const char *psk; /* the pre-shared key */ const char *psk_identity; /* the pre-shared key identity */ @@ -576,21 +576,58 @@ static void my_debug( void *ctx, int level, } #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) -int ca_callback( void *data, mbedtls_x509_crt *child, mbedtls_x509_crt **candidates) +int ca_callback( void *data, mbedtls_x509_crt const *child, + mbedtls_x509_crt **candidates) { + int ret = 0; mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data; - - mbedtls_x509_crt *first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); - TEST_ASSERT( first != NULL); - TEST_ASSERT( mbedtls_x509_crt_init( first ) == 0 ); - TEST_ASSERT( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) == 0); + mbedtls_x509_crt *first; + + /* This is a test-only implementation of the CA callback + * which always returns the entire list of trusted certificates. + * Production implementations managing a large number of CAs + * should use an efficient presentation and lookup for the + * set of trusted certificates (such as a hashtable) and only + * return those trusted certificates which satisfy basic + * parental checks, such as the matching of child `Issuer` + * and parent `Subject` field. */ + ((void) child); + + first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + if( first == NULL ) + { + ret = -1; + goto exit; + } + mbedtls_x509_crt_init( first ); + + if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 ) + { + ret = -1; + goto exit; + } + while( ca->next != NULL ) { ca = ca->next; - TEST_ASSERT( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) == 0); + if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 ) + { + ret = -1; + goto exit; + } } + +exit: + + if( ret != 0 ) + { + mbedtls_x509_crt_free( first ); + mbedtls_free( first ); + first = NULL; + } + *candidates = first; - return 0; + return( ret ); } #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data index 38a75daf11..edd3a6fc59 100644 --- a/tests/suites/test_suite_x509parse.data +++ b/tests/suites/test_suite_x509parse.data @@ -829,7 +829,7 @@ x509_verify:"data_files/cert_sha256.crt":"data_files/test-ca.crt":"data_files/cr X509 Certificate verification with ca callback: failure depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_SHA1_C:MBEDTLS_RSA_C:MBEDTLS_PKCS1_V15:MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK -x509_verify_ca_cb_failure:"data_files/server1.crt":"data_files/test-ca.crt":"NULL":MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:"depth 1 - serial 03 - subject C=NL, O=PolarSSL, CN=PolarSSL Test CA - flags 0x00000000\ndepth 0 - serial 01 - subject C=NL, O=PolarSSL, CN=PolarSSL Server 1 - flags 0x00000000\n" +x509_verify_ca_cb_failure:"data_files/server1.crt":"data_files/test-ca.crt":"NULL":MBEDTLS_ERR_X509_FATAL_ERROR X509 Certificate verification callback: bad name depends_on:MBEDTLS_PEM_PARSE_C:MBEDTLS_ECDSA_C:MBEDTLS_SHA256_C:MBEDTLS_ECP_DP_SECP256R1_ENABLED:MBEDTLS_ECP_DP_SECP384R1_ENABLED diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index d7745a9012..e90ddc41d5 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -69,7 +69,7 @@ int verify_all( void *data, mbedtls_x509_crt *crt, int certificate_depth, uint32 } #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) -int ca_callback_fail( void *data, mbedtls_x509_crt *child, mbedtls_x509_crt **candidates) +int ca_callback_fail( void *data, mbedtls_x509_crt const *child, mbedtls_x509_crt **candidates) { ((void) data); ((void) child); @@ -78,21 +78,58 @@ int ca_callback_fail( void *data, mbedtls_x509_crt *child, mbedtls_x509_crt **ca return -1; } -int ca_callback( void *data, mbedtls_x509_crt *child, mbedtls_x509_crt **candidates) +int ca_callback( void *data, mbedtls_x509_crt const *child, + mbedtls_x509_crt **candidates) { + int ret = 0; mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data; - - mbedtls_x509_crt *first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); - TEST_ASSERT( first != NULL); - TEST_ASSERT( mbedtls_x509_crt_init( first ) == 0 ); - TEST_ASSERT( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) == 0); + mbedtls_x509_crt *first; + + /* This is a test-only implementation of the CA callback + * which always returns the entire list of trusted certificates. + * Production implementations managing a large number of CAs + * should use an efficient presentation and lookup for the + * set of trusted certificates (such as a hashtable) and only + * return those trusted certificates which satisfy basic + * parental checks, such as the matching of child `Issuer` + * and parent `Subject` field. */ + ((void) child); + + first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + if( first == NULL ) + { + ret = -1; + goto exit; + } + mbedtls_x509_crt_init( first ); + + if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 ) + { + ret = -1; + goto exit; + } + while( ca->next != NULL ) { ca = ca->next; - TEST_ASSERT( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) == 0); + if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 ) + { + ret = -1; + goto exit; + } } + +exit: + + if( ret != 0 ) + { + mbedtls_x509_crt_free( first ); + mbedtls_free( first ); + first = NULL; + } + *candidates = first; - return 0; + return( ret ); } #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ @@ -419,7 +456,7 @@ exit: /* BEGIN_CASE depends_on:MBEDTLS_FS_IO:MBEDTLS_X509_CRT_PARSE_C:MBEDTLS_X509_CRL_PARSE_C:MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ void x509_verify_ca_cb_failure( char *crt_file, char *ca_file, char *name, - int exp_ret, char *exp_vrfy_out ) + int exp_ret ) { int ret; mbedtls_x509_crt crt; @@ -434,8 +471,10 @@ void x509_verify_ca_cb_failure( char *crt_file, char *ca_file, char *name, if( strcmp( name, "NULL" ) == 0 ) name = NULL; - - ret = mbedtls_x509_crt_verify_with_cb( &crt, ca_callback_fail, &ca, &compat_profile, name, &flags, verify_all, NULL ); + + ret = mbedtls_x509_crt_verify_with_cb( &crt, ca_callback_fail, &ca, + &compat_profile, name, &flags, + verify_all, NULL ); TEST_ASSERT( ret == exp_ret ); exit: From 0350d562862e0ffe3a3869140693ca6111d4e1e6 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 28 Mar 2019 14:23:36 +0000 Subject: [PATCH 15/29] Only run X.509 CRT verification tests with CA callback tests if !CRL --- tests/suites/test_suite_x509parse.function | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index e90ddc41d5..1d9218adfa 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -440,12 +440,17 @@ void x509_verify( char *crt_file, char *ca_file, char *crl_file, TEST_ASSERT( flags == (uint32_t)( flags_result ) ); #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) - flags = 0; + /* CRLs aren't supported with CA callbacks, so skip the CA callback + * version of the test of CRLs are in use. */ + if( crl_file == NULL || strcmp( crl_file, "" ) == 0 ) + { + flags = 0; - res = mbedtls_x509_crt_verify_with_cb( &crt, ca_callback, &ca, profile, cn_name, &flags, f_vrfy, NULL ); + res = mbedtls_x509_crt_verify_with_cb( &crt, ca_callback, &ca, profile, cn_name, &flags, f_vrfy, NULL ); - TEST_ASSERT( res == ( result ) ); - TEST_ASSERT( flags == (uint32_t)( flags_result ) ); + TEST_ASSERT( res == ( result ) ); + TEST_ASSERT( flags == (uint32_t)( flags_result ) ); + } #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ exit: mbedtls_x509_crt_free( &crt ); From 746aaf3f387679a4b371578ad11777a97812cc3c Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 28 Mar 2019 15:25:23 +0000 Subject: [PATCH 16/29] Add ssl-opt.sh tests for trusted CA callbacks --- tests/ssl-opt.sh | 228 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 45b2c4e960..6f967da407 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -941,6 +941,33 @@ run_test "Default, DTLS" \ -s "Protocol is DTLSv1.2" \ -s "Ciphersuite is TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256" +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "CA callback on client" \ + "$P_SRV debug_level=3" \ + "$P_CLI ca_callback=1 debug_level=3 " \ + 0 \ + -c "use CA callback for X.509 CRT verification"\ + -s "Protocol is TLSv1.2" \ + -s "Ciphersuite is TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256" \ + -s "client hello v3, signature_algorithm ext: 6" \ + -s "ECDHE curve: secp521r1" \ + -S "error" \ + -C "error" + +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +requires_config_enabled MBEDTLS_X509_CRT_PARSE_C +requires_config_enabled MBEDTLS_ECDSA_C +requires_config_enabled MBEDTLS_SHA256_C +run_test "CA callback on server" \ + "$P_SRV auth_mode=required" \ + "$P_CLI ca_callback=1 debug_level=3 crt_file=data_files/server5.crt \ + key_file=data_files/server5.key" \ + 0 \ + -c "use CA callback for X.509 CRT verification"\ + -s "Verifying peer X.509 certificate... ok" \ + -S "error" \ + -C "error" + # Test using an opaque private key for client authentication requires_config_enabled MBEDTLS_USE_PSA_CRYPTO requires_config_enabled MBEDTLS_X509_CRT_PARSE_C @@ -2954,6 +2981,207 @@ run_test "Authentication: send CA list in CertificateRequest, client self sig -c "! mbedtls_ssl_handshake returned" \ -s "X509 - Certificate verification failed" +# Tests for auth_mode, using CA callback + +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: server badcert, client required" \ + "$P_SRV crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + "$P_CLI ca_callback=1 debug_level=3 auth_mode=required" \ + 1 \ + -c "use CA callback for X.509 CRT verification"\ + -c "x509_verify_cert() returned" \ + -c "! The certificate is not correctly signed by the trusted CA" \ + -c "! mbedtls_ssl_handshake returned" \ + -c "X509 - Certificate verification failed" + +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: server badcert, client optional" \ + "$P_SRV crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + "$P_CLI ca_callback=1 debug_level=3 auth_mode=optional" \ + 0 \ + -c "use CA callback for X.509 CRT verification"\ + -c "x509_verify_cert() returned" \ + -c "! The certificate is not correctly signed by the trusted CA" \ + -C "! mbedtls_ssl_handshake returned" \ + -C "X509 - Certificate verification failed" + +# The purpose of the next two tests is to test the client's behaviour when receiving a server +# certificate with an unsupported elliptic curve. This should usually not happen because +# the client informs the server about the supported curves - it does, though, in the +# corner case of a static ECDH suite, because the server doesn't check the curve on that +# occasion (to be fixed). If that bug's fixed, the test needs to be altered to use a +# different means to have the server ignoring the client's supported curve list. + +requires_config_enabled MBEDTLS_ECP_C +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: server ECDH p256v1, client required, p256v1 unsupported" \ + "$P_SRV debug_level=1 key_file=data_files/server5.key \ + crt_file=data_files/server5.ku-ka.crt" \ + "$P_CLI ca_callback=1 debug_level=3 auth_mode=required curves=secp521r1" \ + 1 \ + -c "use CA callback for X.509 CRT verification"\ + -c "bad certificate (EC key curve)"\ + -c "! Certificate verification flags"\ + -C "bad server certificate (ECDH curve)" # Expect failure at earlier verification stage + +requires_config_enabled MBEDTLS_ECP_C +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: server ECDH p256v1, client optional, p256v1 unsupported" \ + "$P_SRV debug_level=1 key_file=data_files/server5.key \ + crt_file=data_files/server5.ku-ka.crt" \ + "$P_CLI ca_callback=1 debug_level=3 auth_mode=optional curves=secp521r1" \ + 1 \ + -c "use CA callback for X.509 CRT verification"\ + -c "bad certificate (EC key curve)"\ + -c "! Certificate verification flags"\ + -c "bad server certificate (ECDH curve)" # Expect failure only at ECDH params check + +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: client SHA256, server required" \ + "$P_SRV ca_callback=1 debug_level=3 auth_mode=required" \ + "$P_CLI debug_level=3 crt_file=data_files/server6.crt \ + key_file=data_files/server6.key \ + force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384" \ + 0 \ + -s "use CA callback for X.509 CRT verification"\ + -c "Supported Signature Algorithm found: 4," \ + -c "Supported Signature Algorithm found: 5," + +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: client SHA384, server required" \ + "$P_SRV ca_callback=1 debug_level=3 auth_mode=required" \ + "$P_CLI debug_level=3 crt_file=data_files/server6.crt \ + key_file=data_files/server6.key \ + force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256" \ + 0 \ + -s "use CA callback for X.509 CRT verification"\ + -c "Supported Signature Algorithm found: 4," \ + -c "Supported Signature Algorithm found: 5," + +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: client badcert, server required" \ + "$P_SRV ca_callback=1 debug_level=3 auth_mode=required" \ + "$P_CLI debug_level=3 crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + 1 \ + -s "use CA callback for X.509 CRT verification"\ + -S "skip write certificate request" \ + -C "skip parse certificate request" \ + -c "got a certificate request" \ + -C "skip write certificate" \ + -C "skip write certificate verify" \ + -S "skip parse certificate verify" \ + -s "x509_verify_cert() returned" \ + -s "! The certificate is not correctly signed by the trusted CA" \ + -s "! mbedtls_ssl_handshake returned" \ + -s "send alert level=2 message=48" \ + -c "! mbedtls_ssl_handshake returned" \ + -s "X509 - Certificate verification failed" +# We don't check that the client receives the alert because it might +# detect that its write end of the connection is closed and abort +# before reading the alert message. + +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: client cert not trusted, server required" \ + "$P_SRV ca_callback=1 debug_level=3 auth_mode=required" \ + "$P_CLI debug_level=3 crt_file=data_files/server5-selfsigned.crt \ + key_file=data_files/server5.key" \ + 1 \ + -s "use CA callback for X.509 CRT verification"\ + -S "skip write certificate request" \ + -C "skip parse certificate request" \ + -c "got a certificate request" \ + -C "skip write certificate" \ + -C "skip write certificate verify" \ + -S "skip parse certificate verify" \ + -s "x509_verify_cert() returned" \ + -s "! The certificate is not correctly signed by the trusted CA" \ + -s "! mbedtls_ssl_handshake returned" \ + -c "! mbedtls_ssl_handshake returned" \ + -s "X509 - Certificate verification failed" + +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: client badcert, server optional" \ + "$P_SRV ca_callback=1 debug_level=3 auth_mode=optional" \ + "$P_CLI debug_level=3 crt_file=data_files/server5-badsign.crt \ + key_file=data_files/server5.key" \ + 0 \ + -s "use CA callback for X.509 CRT verification"\ + -S "skip write certificate request" \ + -C "skip parse certificate request" \ + -c "got a certificate request" \ + -C "skip write certificate" \ + -C "skip write certificate verify" \ + -S "skip parse certificate verify" \ + -s "x509_verify_cert() returned" \ + -s "! The certificate is not correctly signed by the trusted CA" \ + -S "! mbedtls_ssl_handshake returned" \ + -C "! mbedtls_ssl_handshake returned" \ + -S "X509 - Certificate verification failed" + +requires_full_size_output_buffer +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: server max_int chain, client default" \ + "$P_SRV crt_file=data_files/dir-maxpath/c09.pem \ + key_file=data_files/dir-maxpath/09.key" \ + "$P_CLI ca_callback=1 debug_level=3 server_name=CA09 ca_file=data_files/dir-maxpath/00.crt" \ + 0 \ + -c "use CA callback for X.509 CRT verification"\ + -C "X509 - A fatal error occurred" + +requires_full_size_output_buffer +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: server max_int+1 chain, client default" \ + "$P_SRV crt_file=data_files/dir-maxpath/c10.pem \ + key_file=data_files/dir-maxpath/10.key" \ + "$P_CLI debug_level=3 ca_callback=1 server_name=CA10 ca_file=data_files/dir-maxpath/00.crt" \ + 1 \ + -c "use CA callback for X.509 CRT verification"\ + -c "X509 - A fatal error occurred" + +requires_full_size_output_buffer +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: server max_int+1 chain, client optional" \ + "$P_SRV crt_file=data_files/dir-maxpath/c10.pem \ + key_file=data_files/dir-maxpath/10.key" \ + "$P_CLI ca_callback=1 server_name=CA10 ca_file=data_files/dir-maxpath/00.crt \ + debug_level=3 auth_mode=optional" \ + 1 \ + -c "use CA callback for X.509 CRT verification"\ + -c "X509 - A fatal error occurred" + +requires_full_size_output_buffer +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: client max_int+1 chain, server optional" \ + "$P_SRV ca_callback=1 debug_level=3 ca_file=data_files/dir-maxpath/00.crt auth_mode=optional" \ + "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \ + key_file=data_files/dir-maxpath/10.key" \ + 1 \ + -s "use CA callback for X.509 CRT verification"\ + -s "X509 - A fatal error occurred" + +requires_full_size_output_buffer +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: client max_int+1 chain, server required" \ + "$P_SRV ca_callback=1 debug_level=3 ca_file=data_files/dir-maxpath/00.crt auth_mode=required" \ + "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \ + key_file=data_files/dir-maxpath/10.key" \ + 1 \ + -s "use CA callback for X.509 CRT verification"\ + -s "X509 - A fatal error occurred" + +requires_full_size_output_buffer +requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK +run_test "Authentication, CA callback: client max_int chain, server required" \ + "$P_SRV ca_callback=1 debug_level=3 ca_file=data_files/dir-maxpath/00.crt auth_mode=required" \ + "$P_CLI crt_file=data_files/dir-maxpath/c09.pem \ + key_file=data_files/dir-maxpath/09.key" \ + 0 \ + -s "use CA callback for X.509 CRT verification"\ + -S "X509 - A fatal error occurred" + # Tests for certificate selection based on SHA verson run_test "Certificate hash: client TLS 1.2 -> SHA-2" \ From fa738d148d0af73d6af32c7f7ca792774544a74d Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 28 Mar 2019 17:06:04 +0000 Subject: [PATCH 17/29] Update query_config.c --- programs/ssl/query_config.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c index f2f7b46d6d..5e00a013f0 100644 --- a/programs/ssl/query_config.c +++ b/programs/ssl/query_config.c @@ -1490,6 +1490,14 @@ int query_config( const char *config ) } #endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( strcmp( "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK ); + return( 0 ); + } +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + #if defined(MBEDTLS_X509_CHECK_KEY_USAGE) if( strcmp( "MBEDTLS_X509_CHECK_KEY_USAGE", config ) == 0 ) { From 3f932bbc5ddba8f2869c2f3760867db0e25a2d7f Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 28 Mar 2019 17:06:47 +0000 Subject: [PATCH 18/29] Remove trailing whitespace in test_suite_x509parse.function --- tests/suites/test_suite_x509parse.function | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index 1d9218adfa..b08949ad48 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -467,7 +467,7 @@ void x509_verify_ca_cb_failure( char *crt_file, char *ca_file, char *name, mbedtls_x509_crt crt; mbedtls_x509_crt ca; uint32_t flags = 0; - + mbedtls_x509_crt_init( &crt ); mbedtls_x509_crt_init( &ca ); From fed5d9d1e9b30a25050a3cedf4b1b132d3edfc10 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 28 Mar 2019 17:07:12 +0000 Subject: [PATCH 19/29] Update version_features.c --- library/version_features.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/version_features.c b/library/version_features.c index 161788ca76..af3eb6ce5d 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -543,6 +543,9 @@ static const char *features[] = { #if defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) "MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION", #endif /* MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + "MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK", +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ #if defined(MBEDTLS_X509_CHECK_KEY_USAGE) "MBEDTLS_X509_CHECK_KEY_USAGE", #endif /* MBEDTLS_X509_CHECK_KEY_USAGE */ From 1bac87c5dcecf99072f8b046d20378854ec8322c Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Fri, 29 Mar 2019 12:02:26 +0000 Subject: [PATCH 20/29] Correct placement of usage macro in ssl_client2 --- programs/ssl/ssl_client2.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 0540c65895..2e99e964ca 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -171,6 +171,11 @@ int main( void ) #else #define USAGE_PSK_SLOT "" #endif /* MBEDTLS_USE_PSA_CRYPTO */ +#define USAGE_PSK USAGE_PSK_RAW USAGE_PSK_SLOT +#else +#define USAGE_PSK "" +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) #define USAGE_CA_CALLBACK \ " ca_callback=%%d default: 0 (disabled)\n" \ @@ -178,10 +183,6 @@ int main( void ) #else #define USAGE_CA_CALLBACK "" #endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ -#define USAGE_PSK USAGE_PSK_RAW USAGE_PSK_SLOT -#else -#define USAGE_PSK "" -#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ #if defined(MBEDTLS_SSL_SESSION_TICKETS) #define USAGE_TICKETS \ From d6d100beb742226dc337ab0b793a581ccc86c7e0 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Sat, 30 Mar 2019 06:27:43 +0000 Subject: [PATCH 21/29] Fix ssl_client2 and ssl_server2 if !PLATFORM_C The CA callback changes introduce mbedtls_calloc() and mbedtls_free() to ssl_client2 and ssl_server2, which wasn't defined unless MBEDTLS_PLATFORM_C was set. --- programs/ssl/ssl_client2.c | 2 ++ programs/ssl/ssl_server2.c | 1 + 2 files changed, 3 insertions(+) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 2e99e964ca..d4c73fc8de 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -35,6 +35,8 @@ #define mbedtls_printf printf #define mbedtls_fprintf fprintf #define mbedtls_snprintf snprintf +#define mbedtls_calloc calloc +#define mbedtls_free free #define mbedtls_exit exit #define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS #define MBEDTLS_EXIT_FAILURE EXIT_FAILURE diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 476a6728ab..d1e45be3c1 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -30,6 +30,7 @@ #else #include #include +#define mbedtls_calloc calloc #define mbedtls_free free #define mbedtls_time time #define mbedtls_time_t time_t From 31d9db6195d452ee4e66cd2f0f9214e9d28718d7 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Mon, 1 Apr 2019 14:33:49 +0300 Subject: [PATCH 22/29] Change the verify function naming Change the naming to reflect that the function uses a new ca callback feature to distinguish different callbacks. --- include/mbedtls/x509_crt.h | 4 ++-- library/x509_crt.c | 12 ++++++------ tests/suites/test_suite_x509parse.function | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 800e64ba8d..67a24f0299 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -523,7 +523,7 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, * \brief The type of trusted certificate callbacks. * * Callbacks of this type are passed to and used by the CRT - * verification routine mbedtls_x509_crt_verify_with_cb() + * verification routine mbedtls_x509_crt_verify_with_ca_cb() * when looking for trusted signers of a given certificate. * * On success, the callback returns a list of trusted @@ -574,7 +574,7 @@ typedef int (*mbedtls_x509_crt_ca_cb_t)( void *p_ctx, * * \return See \c mbedtls_crt_verify_with_profile(). */ -int mbedtls_x509_crt_verify_with_cb( mbedtls_x509_crt *crt, +int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb, const mbedtls_x509_crt_profile *profile, diff --git a/library/x509_crt.c b/library/x509_crt.c index b74ebffa2b..5850ccf77b 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2587,7 +2587,7 @@ static int x509_crt_merge_flags_with_cb( * of trusted signers, and `ca_crl` will be use as the static list * of CRLs. */ -static int mbedtls_x509_crt_verify_restartable_cb( mbedtls_x509_crt *crt, +static int mbedtls_x509_crt_verify_restartable_ca_cb( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, mbedtls_x509_crt_ca_cb_t f_ca_cb, @@ -2682,7 +2682,7 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { - return( mbedtls_x509_crt_verify_restartable_cb( crt, trust_ca, ca_crl, + return( mbedtls_x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, NULL, NULL, &mbedtls_x509_crt_profile_default, cn, flags, @@ -2700,7 +2700,7 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { - return( mbedtls_x509_crt_verify_restartable_cb( crt, trust_ca, ca_crl, + return( mbedtls_x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, NULL, NULL, profile, cn, flags, f_vrfy, p_vrfy, NULL ) ); @@ -2711,7 +2711,7 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, * Verify the certificate validity (user-chosen profile, CA callback, * not restartable). */ -int mbedtls_x509_crt_verify_with_cb( mbedtls_x509_crt *crt, +int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt, mbedtls_x509_crt_ca_cb_t f_ca_cb, void *p_ca_cb, const mbedtls_x509_crt_profile *profile, @@ -2719,7 +2719,7 @@ int mbedtls_x509_crt_verify_with_cb( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { - return( mbedtls_x509_crt_verify_restartable_cb( crt, NULL, NULL, + return( mbedtls_x509_crt_verify_restartable_ca_cb( crt, NULL, NULL, f_ca_cb, p_ca_cb, profile, cn, flags, f_vrfy, p_vrfy, NULL ) ); @@ -2735,7 +2735,7 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, void *p_vrfy, mbedtls_x509_crt_restart_ctx *rs_ctx ) { - return( mbedtls_x509_crt_verify_restartable_cb( crt, trust_ca, ca_crl, + return( mbedtls_x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, NULL, NULL, profile, cn, flags, f_vrfy, p_vrfy, rs_ctx ) ); diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index b08949ad48..c51d54aab6 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -446,7 +446,7 @@ void x509_verify( char *crt_file, char *ca_file, char *crl_file, { flags = 0; - res = mbedtls_x509_crt_verify_with_cb( &crt, ca_callback, &ca, profile, cn_name, &flags, f_vrfy, NULL ); + res = mbedtls_x509_crt_verify_with_ca_cb( &crt, ca_callback, &ca, profile, cn_name, &flags, f_vrfy, NULL ); TEST_ASSERT( res == ( result ) ); TEST_ASSERT( flags == (uint32_t)( flags_result ) ); @@ -477,7 +477,7 @@ void x509_verify_ca_cb_failure( char *crt_file, char *ca_file, char *name, if( strcmp( name, "NULL" ) == 0 ) name = NULL; - ret = mbedtls_x509_crt_verify_with_cb( &crt, ca_callback_fail, &ca, + ret = mbedtls_x509_crt_verify_with_ca_cb( &crt, ca_callback_fail, &ca, &compat_profile, name, &flags, verify_all, NULL ); From f49fedc34563262533a8a832f983ceacf43398c7 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Mon, 1 Apr 2019 14:58:30 +0300 Subject: [PATCH 23/29] Change docs according to review comments --- include/mbedtls/config.h | 4 ++-- include/mbedtls/x509_crt.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index ed8bafa756..fc9a1623ed 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -1747,7 +1747,7 @@ /** * \def MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK * - * If set, this enables the X.509 API `mbedtls_x509_crt_verify_with_cb()` + * If set, this enables the X.509 API `mbedtls_x509_crt_verify_with_ca_cb()` * and the SSL API `mbedtls_ssl_conf_ca_cb()` which allow users to configure * the set of trusted certificates through a callback instead of a linked * list. @@ -1756,7 +1756,7 @@ * certificates is present and storing them in a linked list isn't efficient * enough, or when the set of trusted certificates changes frequently. * - * See the documentation of `mbedtls_x509_crt_verify_with_cb()` and + * See the documentation of `mbedtls_x509_crt_verify_with_ca_cb()` and * `mbedtls_ssl_conf_ca_cb()` for more information. * * Uncomment to enable trusted certificate callbacks. diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 67a24f0299..96f0142871 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -532,15 +532,15 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, * * \param p_ctx An opaque context passed to the callback. * \param child The certificate for which to search a potential signer. - * This must point to a readable certificate. + * This will point to a readable certificate. * \param candidate_cas The address at which to store the address of the first * entry in the generated linked list of candidate signers. - * This must not be \c NULL. + * This will not be \c NULL. * * \note The callback must only return a non-zero value on a * fatal error. If, in contrast, the search for a potential * signer completes without a single candidate, the - * callback must return \c 0 and get \c *candidate_cas + * callback must return \c 0 and set \c *candidate_cas * to \c NULL. * * \return \c 0 on success. In this case, \c *candidate_cas points From 2ee67a66f42390050fa7bf5762ab6a547a3611ef Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Mon, 1 Apr 2019 14:59:33 +0300 Subject: [PATCH 24/29] Remove mbedtls_ from the static function name --- library/x509_crt.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/x509_crt.c b/library/x509_crt.c index 5850ccf77b..9ca562f8bd 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -2587,7 +2587,7 @@ static int x509_crt_merge_flags_with_cb( * of trusted signers, and `ca_crl` will be use as the static list * of CRLs. */ -static int mbedtls_x509_crt_verify_restartable_ca_cb( mbedtls_x509_crt *crt, +static int x509_crt_verify_restartable_ca_cb( mbedtls_x509_crt *crt, mbedtls_x509_crt *trust_ca, mbedtls_x509_crl *ca_crl, mbedtls_x509_crt_ca_cb_t f_ca_cb, @@ -2682,7 +2682,7 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { - return( mbedtls_x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, + return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, NULL, NULL, &mbedtls_x509_crt_profile_default, cn, flags, @@ -2700,7 +2700,7 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { - return( mbedtls_x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, + return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, NULL, NULL, profile, cn, flags, f_vrfy, p_vrfy, NULL ) ); @@ -2719,7 +2719,7 @@ int mbedtls_x509_crt_verify_with_ca_cb( mbedtls_x509_crt *crt, int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), void *p_vrfy ) { - return( mbedtls_x509_crt_verify_restartable_ca_cb( crt, NULL, NULL, + return( x509_crt_verify_restartable_ca_cb( crt, NULL, NULL, f_ca_cb, p_ca_cb, profile, cn, flags, f_vrfy, p_vrfy, NULL ) ); @@ -2735,7 +2735,7 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt, void *p_vrfy, mbedtls_x509_crt_restart_ctx *rs_ctx ) { - return( mbedtls_x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, + return( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl, NULL, NULL, profile, cn, flags, f_vrfy, p_vrfy, rs_ctx ) ); From f7a7f9ee433a0bcd2b38a8224610f0d9e3b22cc0 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Mon, 1 Apr 2019 15:11:54 +0300 Subject: [PATCH 25/29] Address review comments regarding ssl_client2 and ssl tests --- programs/ssl/ssl_client2.c | 2 +- tests/ssl-opt.sh | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index d4c73fc8de..e13c7cba7d 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -470,7 +470,7 @@ int ca_callback( void *data, mbedtls_x509_crt const *child, * set of trusted certificates (such as a hashtable) and only * return those trusted certificates which satisfy basic * parental checks, such as the matching of child `Issuer` - * and parent `Subject` field. */ + * and parent `Subject` field or matching key identifiers. */ ((void) child); first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 6f967da407..e9322ec0b9 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -947,10 +947,6 @@ run_test "CA callback on client" \ "$P_CLI ca_callback=1 debug_level=3 " \ 0 \ -c "use CA callback for X.509 CRT verification"\ - -s "Protocol is TLSv1.2" \ - -s "Ciphersuite is TLS-ECDHE-RSA-WITH-CHACHA20-POLY1305-SHA256" \ - -s "client hello v3, signature_algorithm ext: 6" \ - -s "ECDHE curve: secp521r1" \ -S "error" \ -C "error" @@ -2602,7 +2598,8 @@ run_test "DER format: with 9 trailing random bytes" \ 0 \ -c "Handshake was completed" \ -# Tests for auth_mode +# Tests for auth_mode, there are duplicated tests using ca callback for authentication +# When updating these tests, modify the matching authentication tests accordingly run_test "Authentication: server badcert, client required" \ "$P_SRV crt_file=data_files/server5-badsign.crt \ @@ -2981,7 +2978,8 @@ run_test "Authentication: send CA list in CertificateRequest, client self sig -c "! mbedtls_ssl_handshake returned" \ -s "X509 - Certificate verification failed" -# Tests for auth_mode, using CA callback +# Tests for auth_mode, using CA callback, these are duplicated from the authentication tests +# When updating these tests, modify the matching authentication tests accordingly requires_config_enabled MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK run_test "Authentication, CA callback: server badcert, client required" \ From dfd22c4dbdd272f73d1d5839fabfccc391353417 Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Mon, 1 Apr 2019 15:18:53 +0300 Subject: [PATCH 26/29] Address comments for x509 tests --- tests/suites/test_suite_x509parse.function | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index c51d54aab6..d574c941c8 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -441,7 +441,7 @@ void x509_verify( char *crt_file, char *ca_file, char *crl_file, #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) /* CRLs aren't supported with CA callbacks, so skip the CA callback - * version of the test of CRLs are in use. */ + * version of the test if CRLs are in use. */ if( crl_file == NULL || strcmp( crl_file, "" ) == 0 ) { flags = 0; @@ -479,7 +479,7 @@ void x509_verify_ca_cb_failure( char *crt_file, char *ca_file, char *name, ret = mbedtls_x509_crt_verify_with_ca_cb( &crt, ca_callback_fail, &ca, &compat_profile, name, &flags, - verify_all, NULL ); + NULL, NULL ); TEST_ASSERT( ret == exp_ret ); exit: From 9822c0d2f1fcbb52202302a9d76dad1fb704fa7c Mon Sep 17 00:00:00 2001 From: Jarno Lamsa Date: Mon, 1 Apr 2019 16:59:48 +0300 Subject: [PATCH 27/29] Fix name to function call --- library/ssl_tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 3064b52491..09645cd0a5 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -6050,7 +6050,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, have_ca_chain = 1; MBEDTLS_SSL_DEBUG_MSG( 3, ( "use CA callback for X.509 CRT verification" ) ); - ret = mbedtls_x509_crt_verify_with_cb( + ret = mbedtls_x509_crt_verify_with_ca_cb( chain, ssl->conf->f_ca_cb, ssl->conf->p_ca_cb, From d7ecbd6914be02237e9f4b6d4473ebb306248c60 Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 5 Apr 2019 14:52:17 +0100 Subject: [PATCH 28/29] Fix style issues and a typo --- include/mbedtls/ssl.h | 2 +- programs/ssl/ssl_client2.c | 2 +- tests/ssl-opt.sh | 38 +++++++++++----------- tests/suites/test_suite_x509parse.function | 8 ++--- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index aabbb83cd9..35e5764815 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2124,7 +2124,7 @@ void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf, * * \warning In multi-threaded environments, the callback \p f_ca_cb * must be thread-safe, and it is the user's responsibility - * to guaranteee this (for example through a mutex + * to guarantee this (for example through a mutex * contained in the callback context pointed to by \p p_ca_cb). */ void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf, diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index e13c7cba7d..f0c7164416 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -457,7 +457,7 @@ static void my_debug( void *ctx, int level, #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) int ca_callback( void *data, mbedtls_x509_crt const *child, - mbedtls_x509_crt **candidates) + mbedtls_x509_crt **candidates ) { int ret = 0; mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data; diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index e9322ec0b9..a9132a1c4a 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -946,7 +946,7 @@ run_test "CA callback on client" \ "$P_SRV debug_level=3" \ "$P_CLI ca_callback=1 debug_level=3 " \ 0 \ - -c "use CA callback for X.509 CRT verification"\ + -c "use CA callback for X.509 CRT verification" \ -S "error" \ -C "error" @@ -959,7 +959,7 @@ run_test "CA callback on server" \ "$P_CLI ca_callback=1 debug_level=3 crt_file=data_files/server5.crt \ key_file=data_files/server5.key" \ 0 \ - -c "use CA callback for X.509 CRT verification"\ + -c "use CA callback for X.509 CRT verification" \ -s "Verifying peer X.509 certificate... ok" \ -S "error" \ -C "error" @@ -2987,7 +2987,7 @@ run_test "Authentication, CA callback: server badcert, client required" \ key_file=data_files/server5.key" \ "$P_CLI ca_callback=1 debug_level=3 auth_mode=required" \ 1 \ - -c "use CA callback for X.509 CRT verification"\ + -c "use CA callback for X.509 CRT verification" \ -c "x509_verify_cert() returned" \ -c "! The certificate is not correctly signed by the trusted CA" \ -c "! mbedtls_ssl_handshake returned" \ @@ -2999,7 +2999,7 @@ run_test "Authentication, CA callback: server badcert, client optional" \ key_file=data_files/server5.key" \ "$P_CLI ca_callback=1 debug_level=3 auth_mode=optional" \ 0 \ - -c "use CA callback for X.509 CRT verification"\ + -c "use CA callback for X.509 CRT verification" \ -c "x509_verify_cert() returned" \ -c "! The certificate is not correctly signed by the trusted CA" \ -C "! mbedtls_ssl_handshake returned" \ @@ -3019,9 +3019,9 @@ run_test "Authentication, CA callback: server ECDH p256v1, client required, p crt_file=data_files/server5.ku-ka.crt" \ "$P_CLI ca_callback=1 debug_level=3 auth_mode=required curves=secp521r1" \ 1 \ - -c "use CA callback for X.509 CRT verification"\ - -c "bad certificate (EC key curve)"\ - -c "! Certificate verification flags"\ + -c "use CA callback for X.509 CRT verification" \ + -c "bad certificate (EC key curve)" \ + -c "! Certificate verification flags" \ -C "bad server certificate (ECDH curve)" # Expect failure at earlier verification stage requires_config_enabled MBEDTLS_ECP_C @@ -3031,7 +3031,7 @@ run_test "Authentication, CA callback: server ECDH p256v1, client optional, p crt_file=data_files/server5.ku-ka.crt" \ "$P_CLI ca_callback=1 debug_level=3 auth_mode=optional curves=secp521r1" \ 1 \ - -c "use CA callback for X.509 CRT verification"\ + -c "use CA callback for X.509 CRT verification" \ -c "bad certificate (EC key curve)"\ -c "! Certificate verification flags"\ -c "bad server certificate (ECDH curve)" # Expect failure only at ECDH params check @@ -3043,7 +3043,7 @@ run_test "Authentication, CA callback: client SHA256, server required" \ key_file=data_files/server6.key \ force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384" \ 0 \ - -s "use CA callback for X.509 CRT verification"\ + -s "use CA callback for X.509 CRT verification" \ -c "Supported Signature Algorithm found: 4," \ -c "Supported Signature Algorithm found: 5," @@ -3054,7 +3054,7 @@ run_test "Authentication, CA callback: client SHA384, server required" \ key_file=data_files/server6.key \ force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256" \ 0 \ - -s "use CA callback for X.509 CRT verification"\ + -s "use CA callback for X.509 CRT verification" \ -c "Supported Signature Algorithm found: 4," \ -c "Supported Signature Algorithm found: 5," @@ -3064,7 +3064,7 @@ run_test "Authentication, CA callback: client badcert, server required" \ "$P_CLI debug_level=3 crt_file=data_files/server5-badsign.crt \ key_file=data_files/server5.key" \ 1 \ - -s "use CA callback for X.509 CRT verification"\ + -s "use CA callback for X.509 CRT verification" \ -S "skip write certificate request" \ -C "skip parse certificate request" \ -c "got a certificate request" \ @@ -3087,7 +3087,7 @@ run_test "Authentication, CA callback: client cert not trusted, server requir "$P_CLI debug_level=3 crt_file=data_files/server5-selfsigned.crt \ key_file=data_files/server5.key" \ 1 \ - -s "use CA callback for X.509 CRT verification"\ + -s "use CA callback for X.509 CRT verification" \ -S "skip write certificate request" \ -C "skip parse certificate request" \ -c "got a certificate request" \ @@ -3106,7 +3106,7 @@ run_test "Authentication, CA callback: client badcert, server optional" \ "$P_CLI debug_level=3 crt_file=data_files/server5-badsign.crt \ key_file=data_files/server5.key" \ 0 \ - -s "use CA callback for X.509 CRT verification"\ + -s "use CA callback for X.509 CRT verification" \ -S "skip write certificate request" \ -C "skip parse certificate request" \ -c "got a certificate request" \ @@ -3126,7 +3126,7 @@ run_test "Authentication, CA callback: server max_int chain, client default" key_file=data_files/dir-maxpath/09.key" \ "$P_CLI ca_callback=1 debug_level=3 server_name=CA09 ca_file=data_files/dir-maxpath/00.crt" \ 0 \ - -c "use CA callback for X.509 CRT verification"\ + -c "use CA callback for X.509 CRT verification" \ -C "X509 - A fatal error occurred" requires_full_size_output_buffer @@ -3136,7 +3136,7 @@ run_test "Authentication, CA callback: server max_int+1 chain, client default key_file=data_files/dir-maxpath/10.key" \ "$P_CLI debug_level=3 ca_callback=1 server_name=CA10 ca_file=data_files/dir-maxpath/00.crt" \ 1 \ - -c "use CA callback for X.509 CRT verification"\ + -c "use CA callback for X.509 CRT verification" \ -c "X509 - A fatal error occurred" requires_full_size_output_buffer @@ -3147,7 +3147,7 @@ run_test "Authentication, CA callback: server max_int+1 chain, client optiona "$P_CLI ca_callback=1 server_name=CA10 ca_file=data_files/dir-maxpath/00.crt \ debug_level=3 auth_mode=optional" \ 1 \ - -c "use CA callback for X.509 CRT verification"\ + -c "use CA callback for X.509 CRT verification" \ -c "X509 - A fatal error occurred" requires_full_size_output_buffer @@ -3157,7 +3157,7 @@ run_test "Authentication, CA callback: client max_int+1 chain, server optiona "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \ key_file=data_files/dir-maxpath/10.key" \ 1 \ - -s "use CA callback for X.509 CRT verification"\ + -s "use CA callback for X.509 CRT verification" \ -s "X509 - A fatal error occurred" requires_full_size_output_buffer @@ -3167,7 +3167,7 @@ run_test "Authentication, CA callback: client max_int+1 chain, server require "$P_CLI crt_file=data_files/dir-maxpath/c10.pem \ key_file=data_files/dir-maxpath/10.key" \ 1 \ - -s "use CA callback for X.509 CRT verification"\ + -s "use CA callback for X.509 CRT verification" \ -s "X509 - A fatal error occurred" requires_full_size_output_buffer @@ -3177,7 +3177,7 @@ run_test "Authentication, CA callback: client max_int chain, server required" "$P_CLI crt_file=data_files/dir-maxpath/c09.pem \ key_file=data_files/dir-maxpath/09.key" \ 0 \ - -s "use CA callback for X.509 CRT verification"\ + -s "use CA callback for X.509 CRT verification" \ -S "X509 - A fatal error occurred" # Tests for certificate selection based on SHA verson diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index d574c941c8..cd6e292eb0 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -69,7 +69,7 @@ int verify_all( void *data, mbedtls_x509_crt *crt, int certificate_depth, uint32 } #if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) -int ca_callback_fail( void *data, mbedtls_x509_crt const *child, mbedtls_x509_crt **candidates) +int ca_callback_fail( void *data, mbedtls_x509_crt const *child, mbedtls_x509_crt **candidates ) { ((void) data); ((void) child); @@ -79,7 +79,7 @@ int ca_callback_fail( void *data, mbedtls_x509_crt const *child, mbedtls_x509_cr } int ca_callback( void *data, mbedtls_x509_crt const *child, - mbedtls_x509_crt **candidates) + mbedtls_x509_crt **candidates ) { int ret = 0; mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data; @@ -478,8 +478,8 @@ void x509_verify_ca_cb_failure( char *crt_file, char *ca_file, char *name, name = NULL; ret = mbedtls_x509_crt_verify_with_ca_cb( &crt, ca_callback_fail, &ca, - &compat_profile, name, &flags, - NULL, NULL ); + &compat_profile, name, &flags, + NULL, NULL ); TEST_ASSERT( ret == exp_ret ); exit: From 846ae7a70d1399347411106669dc0cb4b3f54b8e Mon Sep 17 00:00:00 2001 From: Janos Follath Date: Fri, 5 Apr 2019 16:45:01 +0100 Subject: [PATCH 29/29] Document and test flags in x509_verify --- include/mbedtls/x509_crt.h | 8 ++++++++ tests/suites/test_suite_x509parse.function | 1 + 2 files changed, 9 insertions(+) diff --git a/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h index 96f0142871..eea263201e 100644 --- a/include/mbedtls/x509_crt.h +++ b/include/mbedtls/x509_crt.h @@ -425,6 +425,8 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, * \param cn The expected Common Name. This may be \c NULL if the * CN need not be verified. * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. * \param f_vrfy The verification callback to use. See the documentation * of mbedtls_x509_crt_verify() for more information. * \param p_vrfy The context to be passed to \p f_vrfy. @@ -464,6 +466,8 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, * \param cn The expected Common Name. This may be \c NULL if the * CN need not be verified. * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. * \param f_vrfy The verification callback to use. See the documentation * of mbedtls_x509_crt_verify() for more information. * \param p_vrfy The context to be passed to \p f_vrfy. @@ -500,6 +504,8 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, * \param cn The expected Common Name. This may be \c NULL if the * CN need not be verified. * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. * \param f_vrfy The verification callback to use. See the documentation * of mbedtls_x509_crt_verify() for more information. * \param p_vrfy The context to be passed to \p f_vrfy. @@ -568,6 +574,8 @@ typedef int (*mbedtls_x509_crt_ca_cb_t)( void *p_ctx, * \param cn The expected Common Name. This may be \c NULL if the * CN need not be verified. * \param flags The address at which to store the result of the verification. + * If the verification couldn't be completed, the flag value is + * set to (uint32_t) -1. * \param f_vrfy The verification callback to use. See the documentation * of mbedtls_x509_crt_verify() for more information. * \param p_vrfy The context to be passed to \p f_vrfy. diff --git a/tests/suites/test_suite_x509parse.function b/tests/suites/test_suite_x509parse.function index cd6e292eb0..b11ab849af 100644 --- a/tests/suites/test_suite_x509parse.function +++ b/tests/suites/test_suite_x509parse.function @@ -482,6 +482,7 @@ void x509_verify_ca_cb_failure( char *crt_file, char *ca_file, char *name, NULL, NULL ); TEST_ASSERT( ret == exp_ret ); + TEST_ASSERT( flags == (uint32_t)( -1 ) ); exit: mbedtls_x509_crt_free( &crt ); mbedtls_x509_crt_free( &ca );