Merge remote-tracking branch 'origin/pr/2539' into development
Resolve conflicts by performing the following:
- Ensure calls to mbedtls_x509_crt_verify_* are made with callbacks
* origin/pr/2539:
Make CRT callback tests more robust
Rename constant in client2.c
Fix typo
Add test for configuration specific CRT callback
Fix doxygen documentation of mbedtls_ssl_set_verify()
Add test exercising context-specific CRT callback to ssl-opt.sh
Add cmd to use context-specific CRT callback in ssl_client2
Implement context-specific verification callbacks
Add context-specific CRT verification callbacks
Improve documentation of mbedtls_ssl_conf_verify()
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 35e5764..135be05 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -1094,6 +1094,12 @@
unsigned badmac_seen; /*!< records with a bad MAC received */
#endif /* MBEDTLS_SSL_DTLS_BADMAC_LIMIT */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+ /** Callback to customize X.509 certificate chain verification */
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
+ void *p_vrfy; /*!< context for X.509 verify callback */
+#endif
+
mbedtls_ssl_send_t *f_send; /*!< Callback for network send */
mbedtls_ssl_recv_t *f_recv; /*!< Callback for network receive */
mbedtls_ssl_recv_timeout_t *f_recv_timeout;
@@ -1370,13 +1376,17 @@
/**
* \brief Set the verification callback (Optional).
*
- * If set, the verify callback is called for each
- * certificate in the chain. For implementation
- * information, please see \c mbedtls_x509_crt_verify()
+ * If set, the provided verify callback is called for each
+ * certificate in the peer's CRT chain, including the trusted
+ * root. For more information, please see the documentation of
+ * \c mbedtls_x509_crt_verify().
*
- * \param conf SSL configuration
- * \param f_vrfy verification function
- * \param p_vrfy verification parameter
+ * \note For per context callbacks and contexts, please use
+ * mbedtls_ssl_set_verify() instead.
+ *
+ * \param conf The SSL configuration to use.
+ * \param f_vrfy The verification callback to use during CRT verification.
+ * \param p_vrfy The opaque context to be passed to the callback.
*/
void mbedtls_ssl_conf_verify( mbedtls_ssl_config *conf,
int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
@@ -1494,6 +1504,30 @@
void mbedtls_ssl_set_mtu( mbedtls_ssl_context *ssl, uint16_t mtu );
#endif /* MBEDTLS_SSL_PROTO_DTLS */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+/**
+ * \brief Set a connection-specific verification callback (optional).
+ *
+ * If set, the provided verify callback is called for each
+ * certificate in the peer's CRT chain, including the trusted
+ * root. For more information, please see the documentation of
+ * \c mbedtls_x509_crt_verify().
+ *
+ * \note This call is analogous to mbedtls_ssl_conf_verify() but
+ * binds the verification callback and context to an SSL context
+ * as opposed to an SSL configuration.
+ * If mbedtls_ssl_conf_verify() and mbedtls_ssl_set_verify()
+ * are both used, mbedtls_ssl_set_verify() takes precedence.
+ *
+ * \param ssl The SSL context to use.
+ * \param f_vrfy The verification callback to use during CRT verification.
+ * \param p_vrfy The opaque context to be passed to the callback.
+ */
+void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy );
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
/**
* \brief Set the timeout period for mbedtls_ssl_read()
* (Default: no timeout.)
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 09645cd..dac160d 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -6037,9 +6037,25 @@
ssl->transform_negotiate->ciphersuite_info;
int have_ca_chain = 0;
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
+ void *p_vrfy;
+
if( authmode == MBEDTLS_SSL_VERIFY_NONE )
return( 0 );
+ if( ssl->f_vrfy != NULL )
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use context-specific verification callback" ) );
+ f_vrfy = ssl->f_vrfy;
+ p_vrfy = ssl->p_vrfy;
+ }
+ else
+ {
+ MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use configuration-specific verification callback" ) );
+ f_vrfy = ssl->conf->f_vrfy;
+ p_vrfy = ssl->conf->p_vrfy;
+ }
+
/*
* Main check: verify certificate
*/
@@ -6057,7 +6073,7 @@
ssl->conf->cert_profile,
ssl->hostname,
&ssl->session_negotiate->verify_result,
- ssl->conf->f_vrfy, ssl->conf->p_vrfy );
+ f_vrfy, p_vrfy );
}
else
#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
@@ -6087,7 +6103,7 @@
ssl->conf->cert_profile,
ssl->hostname,
&ssl->session_negotiate->verify_result,
- ssl->conf->f_vrfy, ssl->conf->p_vrfy, rs_ctx );
+ f_vrfy, p_vrfy, rs_ctx );
}
if( ret != 0 )
@@ -7949,6 +7965,16 @@
}
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl,
+ int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+ void *p_vrfy )
+{
+ ssl->f_vrfy = f_vrfy;
+ ssl->p_vrfy = p_vrfy;
+}
+#endif
+
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
/*
* Set EC J-PAKE password for current handshake
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index f0c7164..2cddfb4 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -82,6 +82,7 @@
#define DFL_REQUEST_PAGE "/"
#define DFL_REQUEST_SIZE -1
#define DFL_DEBUG_LEVEL 0
+#define DFL_CONTEXT_CRT_CB 0
#define DFL_NBIO 0
#define DFL_EVENT 0
#define DFL_READ_TIMEOUT 0
@@ -131,6 +132,16 @@
#define GET_REQUEST_END "\r\n\r\n"
#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#define USAGE_CONTEXT_CRT_CB \
+ " context_crt_cb=%%d This determines whether the CRT verification callback is bound\n" \
+ " to the SSL configuration of the SSL context.\n" \
+ " Possible values:\n"\
+ " - 0 (default): Use CRT callback bound to configuration\n" \
+ " - 1: Use CRT callback bound to SSL context\n"
+#else
+#define USAGE_CONTEXT_CRT_CB ""
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
#if defined(MBEDTLS_FS_IO)
#define USAGE_IO \
" ca_file=%%s The single file containing the top-level CA(s) you fully trust\n" \
@@ -339,6 +350,7 @@
USAGE_TICKETS \
USAGE_MAX_FRAG_LEN \
USAGE_TRUNC_HMAC \
+ USAGE_CONTEXT_CRT_CB \
USAGE_ALPN \
USAGE_FALLBACK \
USAGE_EMS \
@@ -435,6 +447,7 @@
int dgram_packing; /* allow/forbid datagram packing */
int extended_ms; /* negotiate extended master secret? */
int etm; /* negotiate encrypt then mac? */
+ int context_crt_cb; /* use context-specific CRT verify callback */
} opt;
int query_config( const char *config );
@@ -757,6 +770,7 @@
opt.debug_level = DFL_DEBUG_LEVEL;
opt.nbio = DFL_NBIO;
opt.event = DFL_EVENT;
+ opt.context_crt_cb = DFL_CONTEXT_CRT_CB;
opt.read_timeout = DFL_READ_TIMEOUT;
opt.max_resend = DFL_MAX_RESEND;
opt.request_page = DFL_REQUEST_PAGE;
@@ -834,6 +848,12 @@
if( opt.debug_level < 0 || opt.debug_level > 65535 )
goto usage;
}
+ else if( strcmp( p, "context_crt_cb" ) == 0 )
+ {
+ opt.context_crt_cb = atoi( q );
+ if( opt.context_crt_cb != 0 && opt.context_crt_cb != 1 )
+ goto usage;
+ }
else if( strcmp( p, "nbio" ) == 0 )
{
opt.nbio = atoi( q );
@@ -1590,7 +1610,9 @@
mbedtls_ssl_conf_sig_hashes( &conf, ssl_sig_hashes_for_test );
}
- mbedtls_ssl_conf_verify( &conf, my_verify, NULL );
+ if( opt.context_crt_cb == 0 )
+ mbedtls_ssl_conf_verify( &conf, my_verify, NULL );
+
memset( peer_crt_info, 0, sizeof( peer_crt_info ) );
#endif /* MBEDTLS_X509_CRT_PARSE_C */
@@ -1799,6 +1821,11 @@
}
#endif
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+ if( opt.context_crt_cb == 1 )
+ mbedtls_ssl_set_verify( &ssl, my_verify, NULL );
+#endif /* MBEDTLS_X509_CRT_PARSE_C */
+
if( opt.nbio == 2 )
mbedtls_ssl_set_bio( &ssl, &server_fd, my_send, my_recv, NULL );
else
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index ac717ab..a6d41b1 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -1031,6 +1031,27 @@
-u "IV used" \
-U "IV used"
+# Tests for certificate verification callback
+run_test "Configuration-specific CRT verification callback" \
+ "$P_SRV debug_level=3" \
+ "$P_CLI context_crt_cb=0 debug_level=3" \
+ 0 \
+ -S "error" \
+ -c "Verify requested for " \
+ -c "Use configuration-specific verification callback" \
+ -C "Use context-specific verification callback" \
+ -C "error"
+
+run_test "Context-specific CRT verification callback" \
+ "$P_SRV debug_level=3" \
+ "$P_CLI context_crt_cb=1 debug_level=3" \
+ 0 \
+ -S "error" \
+ -c "Verify requested for " \
+ -c "Use context-specific verification callback" \
+ -C "Use configuration-specific verification callback" \
+ -C "error"
+
# Tests for rc4 option
requires_config_enabled MBEDTLS_REMOVE_ARC4_CIPHERSUITES