Merge remote-tracking branch 'origin/pr/2536' into development

* origin/pr/2536:
  Update crypto submodule
  Minor fixes in get certificate policies oid test
  Add certificate policy oid x509 extension
diff --git a/.travis.yml b/.travis.yml
index 4fc31c9..c45d408 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -31,7 +31,8 @@
 - tests/scripts/travis-log-failure.sh
 env:
   global:
-    secure: "barHldniAfXyoWOD/vcO+E6/Xm4fmcaUoC9BeKW+LwsHqlDMLvugaJnmLXkSpkbYhVL61Hzf3bo0KPJn88AFc5Rkf8oYHPjH4adMnVXkf3B9ghHCgznqHsAH3choo6tnPxaFgOwOYmLGb382nQxfE5lUdvnM/W/psQjWt66A1+k="
+    - SEED=1
+    - secure: "barHldniAfXyoWOD/vcO+E6/Xm4fmcaUoC9BeKW+LwsHqlDMLvugaJnmLXkSpkbYhVL61Hzf3bo0KPJn88AFc5Rkf8oYHPjH4adMnVXkf3B9ghHCgznqHsAH3choo6tnPxaFgOwOYmLGb382nQxfE5lUdvnM/W/psQjWt66A1+k="
 
 addons:
   apt:
diff --git a/ChangeLog b/ChangeLog
index 984de6a..5093c4e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -18,12 +18,15 @@
      Junhwan Park, #2106.
    * Reduce stack usage of hkdf tests. Fixes #2195.
    * Fix 1-byte buffer overflow in mbedtls_mpi_write_string() when
-     used with negative inputs. Found by Guido Vranken in #2404.
+     used with negative inputs. Found by Guido Vranken in #2404. Credit to
+     OSS-Fuzz.
    * Fix bugs in the AEAD test suite which would be exposed by ciphers which
      either used both encrypt and decrypt key schedules, or which perform padding.
      GCM and CCM were not affected. Fixed by Jack Lloyd.
    * Fix incorrect default port number in ssl_mail_client example's usage.
      Found and fixed by irwir. #2337
+   * Add psa_util.h to test/cpp_dummy_build to fix build_default_make_gcc_and_cxx.
+     Fixed by Peter Kolbus (Garmin). #2579
 
 Changes
    * Server's RSA certificate in certs.c was SHA-1 signed. In the default
diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h
index 0fe2574..fd91d70 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -1777,6 +1777,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_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.
+ *
+ * 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_ca_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
  *
  * Enable verification of the keyUsage extension (CA and leaf certificates).
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index b793ac0..135be05 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -928,6 +928,10 @@
     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)
@@ -1090,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;
@@ -1366,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 *),
@@ -1490,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.)
@@ -2071,6 +2109,63 @@
                                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 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,
+                             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/include/mbedtls/x509_crt.h b/include/mbedtls/x509_crt.h
index b3f27be..eea2632 100644
--- a/include/mbedtls/x509_crt.h
+++ b/include/mbedtls/x509_crt.h
@@ -166,6 +166,14 @@
 {
     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)
@@ -371,7 +379,7 @@
                           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 +419,27 @@
  *                 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.
+ *                 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.
  *
- * \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 +449,8 @@
                      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 +459,28 @@
  *                 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.
+ *                 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.
  *
- * \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 +497,20 @@
  *                 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.
+ *                 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.
+ * \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
@@ -501,6 +525,73 @@
                      void *p_vrfy,
                      mbedtls_x509_crt_restart_ctx *rs_ctx );
 
+/**
+ * \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_ca_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 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 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 set \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 );
+
+#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
+ *                 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.
+ *                 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.
+ *
+ * \return         See \c mbedtls_crt_verify_with_profile().
+ */
+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,
+                     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.
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index c969089..b8e10d6 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -2818,6 +2818,11 @@
 
     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;
diff --git a/library/ssl_tls.c b/library/ssl_tls.c
index 660d548..abe2450 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1238,7 +1238,7 @@
 
         if( ret == 0 )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Successfully setup PSA-based encryption cipher context" ) );
+            MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based encryption cipher context" ) );
             psa_fallthrough = 0;
         }
         else
@@ -1281,7 +1281,7 @@
 
         if( ret == 0 )
         {
-            MBEDTLS_SSL_DEBUG_MSG( 1, ( "Successfully setup PSA-based decryption cipher context" ) );
+            MBEDTLS_SSL_DEBUG_MSG( 3, ( "Successfully setup PSA-based decryption cipher context" ) );
             psa_fallthrough = 0;
         }
         else
@@ -6035,35 +6035,76 @@
     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;
+
+    int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *);
+    void *p_vrfy;
 
     if( authmode == MBEDTLS_SSL_VERIFY_NONE )
         return( 0 );
 
-#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
-    if( ssl->handshake->sni_ca_chain != NULL )
+    if( ssl->f_vrfy != NULL )
     {
-        ca_chain = ssl->handshake->sni_ca_chain;
-        ca_crl   = ssl->handshake->sni_ca_crl;
+        MBEDTLS_SSL_DEBUG_MSG( 3, ( "Use context-specific verification callback" ) );
+        f_vrfy = ssl->f_vrfy;
+        p_vrfy = ssl->p_vrfy;
     }
     else
-#endif
     {
-        ca_chain = ssl->conf->ca_chain;
-        ca_crl   = ssl->conf->ca_crl;
+        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
      */
-    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_ca_cb(
+            chain,
+            ssl->conf->f_ca_cb,
+            ssl->conf->p_ca_cb,
+            ssl->conf->cert_profile,
+            ssl->hostname,
+            &ssl->session_negotiate->verify_result,
+            f_vrfy, 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,
+            f_vrfy, p_vrfy, rs_ctx );
+    }
 
     if( ret != 0 )
     {
@@ -6119,7 +6160,7 @@
         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;
@@ -7875,7 +7916,29 @@
 {
     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_crt_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)
@@ -7902,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
@@ -10444,7 +10517,7 @@
     psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;
     psa_algorithm_t hash_alg = mbedtls_psa_translate_md( md_alg );
 
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Perform PSA-based computation of digest of ServerKeyExchange" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "Perform PSA-based computation of digest of ServerKeyExchange" ) );
 
     if( ( status = psa_hash_setup( &hash_operation,
                                    hash_alg ) ) != PSA_SUCCESS )
@@ -10507,7 +10580,7 @@
     const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
     *hashlen = mbedtls_md_get_size( md_info );
 
-    MBEDTLS_SSL_DEBUG_MSG( 1, ( "Perform mbedtls-based computation of digest of ServerKeyExchange" ) );
+    MBEDTLS_SSL_DEBUG_MSG( 3, ( "Perform mbedtls-based computation of digest of ServerKeyExchange" ) );
 
     mbedtls_md_init( &ctx );
 
diff --git a/library/version_features.c b/library/version_features.c
index 59eacc4..b36893e 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -546,6 +546,9 @@
 #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 */
diff --git a/library/x509_crt.c b/library/x509_crt.c
index 8024b51..605d8ef 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -377,6 +377,10 @@
     }
 
     ver_chain->len = 0;
+
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+    ver_chain->trust_ca_cb_result = NULL;
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
 }
 
 /*
@@ -2319,6 +2323,8 @@
                 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 )
@@ -2334,6 +2340,7 @@
     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 */
@@ -2393,8 +2400,32 @@
 #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 );
 
@@ -2550,36 +2581,6 @@
 }
 
 /*
- * 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
  *
  * This function:
@@ -2588,10 +2589,19 @@
  *    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 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,
+                     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 *),
@@ -2627,7 +2637,8 @@
         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 )
@@ -2640,6 +2651,13 @@
     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 );
@@ -2663,6 +2681,77 @@
     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( x509_crt_verify_restartable_ca_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( x509_crt_verify_restartable_ca_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_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,
+                     const char *cn, uint32_t *flags,
+                     int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *),
+                     void *p_vrfy )
+{
+    return( x509_crt_verify_restartable_ca_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( x509_crt_verify_restartable_ca_cb( crt, trust_ca, ca_crl,
+                                                 NULL, NULL,
+                                                 profile, cn, flags,
+                                                 f_vrfy, p_vrfy, rs_ctx ) );
+}
+
+
 /*
  * Initialize a certificate chain
  */
diff --git a/programs/Makefile b/programs/Makefile
index 753524c..c172385 100644
--- a/programs/Makefile
+++ b/programs/Makefile
@@ -73,7 +73,7 @@
 	ssl/ssl_mail_client$(EXEXT)	random/gen_entropy$(EXEXT)	\
 	random/gen_random_havege$(EXEXT)				\
 	random/gen_random_ctr_drbg$(EXEXT)				\
-	test/ssl_cert_test$(EXEXT)	test/benchmark$(EXEXT)		\
+	test/benchmark$(EXEXT)                          		\
 	test/selftest$(EXEXT)		test/udp_proxy$(EXEXT)		\
 	test/zeroize$(EXEXT)						\
 	test/query_compile_time_config$(EXEXT)				\
@@ -247,10 +247,6 @@
 	echo "  CC    ssl/mini_client.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/mini_client.c   $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
 
-test/ssl_cert_test$(EXEXT): test/ssl_cert_test.c $(DEP)
-	echo "  CC    test/ssl_cert_test.c"
-	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/ssl_cert_test.c   $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
-
 test/benchmark$(EXEXT): test/benchmark.c $(DEP)
 	echo "  CC    test/benchmark.c"
 	$(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/benchmark.c   $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@
diff --git a/programs/README.md b/programs/README.md
index eb25a7f..d26349d 100644
--- a/programs/README.md
+++ b/programs/README.md
@@ -99,8 +99,6 @@
 
 * [`test/selftest.c`](test/selftest.c): runs the self-test function in each library module.
 
-* [`test/ssl_cert_test.c`](test/ssl_cert_test.c): demonstrates how to verify X.509 certificates, and (for RSA keys only) how to check that each certificate matches the corresponding private key. This program requires some test data which is not provided.
-
 * [`test/udp_proxy.c`](test/udp_proxy.c): a UDP proxy that can inject certain failures (delay, duplicate, drop). Useful for testing DTLS.
 
 * [`test/zeroize.c`](test/zeroize.c): a test program for `mbedtls_platform_zeroize`, used by [`tests/scripts/test_zeroize.gdb`](tests/scripts/test_zeroize.gdb).
diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c
index 6ea9012..143a45d 100644
--- a/programs/ssl/query_config.c
+++ b/programs/ssl/query_config.c
@@ -1498,6 +1498,14 @@
     }
 #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 )
     {
diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c
index f7e2459..2cddfb4 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
@@ -80,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
@@ -122,11 +125,23 @@
 #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"
 
 #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" \
@@ -174,6 +189,14 @@
 #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"
@@ -312,6 +335,7 @@
     "                        options: none, optional, required\n" \
     USAGE_IO                                                \
     USAGE_KEY_OPAQUE                                        \
+    USAGE_CA_CALLBACK                                       \
     "\n"                                                    \
     USAGE_PSK                                               \
     USAGE_ECJPAKE                                           \
@@ -326,6 +350,7 @@
     USAGE_TICKETS                                           \
     USAGE_MAX_FRAG_LEN                                      \
     USAGE_TRUNC_HMAC                                        \
+    USAGE_CONTEXT_CRT_CB                                    \
     USAGE_ALPN                                              \
     USAGE_FALLBACK                                          \
     USAGE_EMS                                               \
@@ -386,6 +411,9 @@
 #if defined(MBEDTLS_USE_PSA_CRYPTO)
     int psk_opaque;
 #endif
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+    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              */
     const char *ecjpake_pw;     /* the EC J-PAKE password                   */
@@ -419,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 );
@@ -439,6 +468,62 @@
     fflush(  (FILE *) ctx  );
 }
 
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+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;
+
+    /* 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 or matching key identifiers. */
+    ((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;
+        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( ret );
+}
+#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
@@ -685,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;
@@ -698,6 +784,9 @@
 #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;
     opt.ec_max_ops          = DFL_EC_MAX_OPS;
@@ -759,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 );
@@ -806,6 +901,10 @@
         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;
         else if( strcmp( p, "ecjpake_pw" ) == 0 )
@@ -1511,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 */
 
@@ -1600,7 +1701,12 @@
     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 )
@@ -1715,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/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c
index 7858db3..d1e45be 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -30,6 +30,7 @@
 #else
 #include <stdio.h>
 #include <stdlib.h>
+#define mbedtls_calloc     calloc
 #define mbedtls_free       free
 #define mbedtls_time       time
 #define mbedtls_time_t     time_t
@@ -166,6 +167,7 @@
 #define DFL_DGRAM_PACKING        1
 #define DFL_EXTENDED_MS         -1
 #define DFL_ETM                 -1
+#define DFL_CA_CALLBACK         0
 
 #define LONG_RESPONSE "<p>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 +266,13 @@
 #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 +428,7 @@
     USAGE_SNI                                               \
     "\n"                                                    \
     USAGE_PSK                                               \
+    USAGE_CA_CALLBACK                                       \
     USAGE_ECJPAKE                                           \
     "\n"                                                    \
     "    allow_legacy=%%d     default: (library default: no)\n"      \
@@ -507,6 +516,9 @@
     int psk_opaque;
     int psk_list_opaque;
 #endif
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+    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              */
     char *psk_list;             /* list of PSK id/key pairs for callback    */
@@ -564,6 +576,62 @@
     fflush(  (FILE *) ctx  );
 }
 
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+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;
+
+    /* 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;
+        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( ret );
+}
+#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
@@ -1458,6 +1526,9 @@
     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;
     opt.ecjpake_pw          = DFL_ECJPAKE_PW;
@@ -1592,6 +1663,10 @@
         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;
         else if( strcmp( p, "psk_list" ) == 0 )
@@ -2570,7 +2645,12 @@
     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 )
     {
diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt
index 65ff249..282ef58 100644
--- a/programs/test/CMakeLists.txt
+++ b/programs/test/CMakeLists.txt
@@ -21,9 +21,6 @@
     target_link_libraries(cpp_dummy_build ${libs})
 endif()
 
-add_executable(ssl_cert_test ssl_cert_test.c)
-target_link_libraries(ssl_cert_test ${libs})
-
 add_executable(udp_proxy udp_proxy.c)
 target_link_libraries(udp_proxy ${libs})
 
@@ -34,6 +31,6 @@
 target_sources(query_compile_time_config PUBLIC ../ssl/query_config.c)
 target_link_libraries(query_compile_time_config ${libs})
 
-install(TARGETS selftest benchmark ssl_cert_test udp_proxy query_compile_time_config
+install(TARGETS selftest benchmark udp_proxy query_compile_time_config
         DESTINATION "bin"
         PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
diff --git a/programs/test/cpp_dummy_build.cpp b/programs/test/cpp_dummy_build.cpp
index c652884..9cd5090 100644
--- a/programs/test/cpp_dummy_build.cpp
+++ b/programs/test/cpp_dummy_build.cpp
@@ -81,6 +81,7 @@
 #include "mbedtls/platform_time.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/poly1305.h"
+#include "mbedtls/psa_util.h"
 #include "mbedtls/ripemd160.h"
 #include "mbedtls/rsa.h"
 #include "mbedtls/rsa_internal.h"
diff --git a/programs/test/ssl_cert_test.c b/programs/test/ssl_cert_test.c
deleted file mode 100644
index fdf30ef..0000000
--- a/programs/test/ssl_cert_test.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- *  SSL certificate functionality tests
- *
- *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
- *  SPDX-License-Identifier: Apache-2.0
- *
- *  Licensed under the Apache License, Version 2.0 (the "License"); you may
- *  not use this file except in compliance with the License.
- *  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- *  This file is part of mbed TLS (https://tls.mbed.org)
- */
-
-#if !defined(MBEDTLS_CONFIG_FILE)
-#include "mbedtls/config.h"
-#else
-#include MBEDTLS_CONFIG_FILE
-#endif
-
-#if defined(MBEDTLS_PLATFORM_C)
-#include "mbedtls/platform.h"
-#else
-#include <stdio.h>
-#include <stdlib.h>
-#define mbedtls_snprintf        snprintf
-#define mbedtls_printf          printf
-#define mbedtls_exit            exit
-#define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
-#define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
-#endif /* MBEDTLS_PLATFORM_C */
-
-#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_X509_CRT_PARSE_C) && \
-    defined(MBEDTLS_FS_IO) && defined(MBEDTLS_X509_CRL_PARSE_C)
-#include "mbedtls/certs.h"
-#include "mbedtls/x509_crt.h"
-
-#include <stdio.h>
-#include <string.h>
-#endif
-
-#define MAX_CLIENT_CERTS    8
-
-#if !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \
-    !defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_X509_CRL_PARSE_C)
-int main( void )
-{
-    mbedtls_printf("MBEDTLS_RSA_C and/or MBEDTLS_X509_CRT_PARSE_C "
-           "MBEDTLS_FS_IO and/or MBEDTLS_X509_CRL_PARSE_C "
-           "not defined.\n");
-    return( 0 );
-}
-#else
-const char *client_certificates[MAX_CLIENT_CERTS] =
-{
-    "client1.crt",
-    "client2.crt",
-    "server1.crt",
-    "server2.crt",
-    "cert_sha224.crt",
-    "cert_sha256.crt",
-    "cert_sha384.crt",
-    "cert_sha512.crt"
-};
-
-const char *client_private_keys[MAX_CLIENT_CERTS] =
-{
-    "client1.key",
-    "client2.key",
-    "server1.key",
-    "server2.key",
-    "cert_digest.key",
-    "cert_digest.key",
-    "cert_digest.key",
-    "cert_digest.key"
-};
-
-#if defined(MBEDTLS_CHECK_PARAMS)
-#include "mbedtls/platform_util.h"
-void mbedtls_param_failed( const char *failure_condition,
-                           const char *file,
-                           int line )
-{
-    mbedtls_printf( "%s:%i: Input param failed - %s\n",
-                    file, line, failure_condition );
-    mbedtls_exit( MBEDTLS_EXIT_FAILURE );
-}
-#endif
-
-int main( void )
-{
-    int ret = 1, i;
-    int exit_code = MBEDTLS_EXIT_FAILURE;
-    mbedtls_x509_crt cacert;
-    mbedtls_x509_crl crl;
-    char buf[10240];
-
-    mbedtls_x509_crt_init( &cacert );
-    mbedtls_x509_crl_init( &crl );
-
-    /*
-     * 1.1. Load the trusted CA
-     */
-    mbedtls_printf( "\n  . Loading the CA root certificate ..." );
-    fflush( stdout );
-
-    /*
-     * Alternatively, you may load the CA certificates from a .pem or
-     * .crt file by calling mbedtls_x509_crt_parse_file( &cacert, "myca.crt" ).
-     */
-    ret = mbedtls_x509_crt_parse_file( &cacert, "ssl/test-ca/test-ca.crt" );
-    if( ret != 0 )
-    {
-        mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse_file returned %d\n\n", ret );
-        goto exit;
-    }
-
-    mbedtls_printf( " ok\n" );
-
-    mbedtls_x509_crt_info( buf, 1024, "CRT: ", &cacert );
-    mbedtls_printf("%s\n", buf );
-
-    /*
-     * 1.2. Load the CRL
-     */
-    mbedtls_printf( "  . Loading the CRL ..." );
-    fflush( stdout );
-
-    ret = mbedtls_x509_crl_parse_file( &crl, "ssl/test-ca/crl.pem" );
-    if( ret != 0 )
-    {
-        mbedtls_printf( " failed\n  !  mbedtls_x509_crl_parse_file returned %d\n\n", ret );
-        goto exit;
-    }
-
-    mbedtls_printf( " ok\n" );
-
-    mbedtls_x509_crl_info( buf, 1024, "CRL: ", &crl );
-    mbedtls_printf("%s\n", buf );
-
-    for( i = 0; i < MAX_CLIENT_CERTS; i++ )
-    {
-        /*
-         * 1.3. Load own certificate
-         */
-        char    name[512];
-        uint32_t flags;
-        mbedtls_x509_crt clicert;
-        mbedtls_pk_context pk;
-
-        mbedtls_x509_crt_init( &clicert );
-        mbedtls_pk_init( &pk );
-
-        mbedtls_snprintf(name, 512, "ssl/test-ca/%s", client_certificates[i]);
-
-        mbedtls_printf( "  . Loading the client certificate %s...", name );
-        fflush( stdout );
-
-        ret = mbedtls_x509_crt_parse_file( &clicert, name );
-        if( ret != 0 )
-        {
-            mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse_file returned %d\n\n", ret );
-            goto exit;
-        }
-
-        mbedtls_printf( " ok\n" );
-
-        /*
-         * 1.4. Verify certificate validity with CA certificate
-         */
-        mbedtls_printf( "  . Verify the client certificate with CA certificate..." );
-        fflush( stdout );
-
-        ret = mbedtls_x509_crt_verify( &clicert, &cacert, &crl, NULL, &flags, NULL,
-                               NULL );
-        if( ret != 0 )
-        {
-            if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
-            {
-                 char vrfy_buf[512];
-
-                 mbedtls_printf( " failed\n" );
-                 mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", flags );
-                 mbedtls_printf( "%s\n", vrfy_buf );
-             }
-             else
-             {
-                mbedtls_printf( " failed\n  !  mbedtls_x509_crt_verify returned %d\n\n", ret );
-                goto exit;
-            }
-        }
-
-        mbedtls_printf( " ok\n" );
-
-        /*
-         * 1.5. Load own private key
-         */
-        mbedtls_snprintf(name, 512, "ssl/test-ca/%s", client_private_keys[i]);
-
-        mbedtls_printf( "  . Loading the client private key %s...", name );
-        fflush( stdout );
-
-        ret = mbedtls_pk_parse_keyfile( &pk, name, NULL );
-        if( ret != 0 )
-        {
-            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned %d\n\n", ret );
-            goto exit;
-        }
-
-        mbedtls_printf( " ok\n" );
-
-        /*
-         * 1.6. Verify certificate validity with private key
-         */
-        mbedtls_printf( "  . Verify the client certificate with private key..." );
-        fflush( stdout );
-
-
-        /* EC NOT IMPLEMENTED YET */
-        if( ! mbedtls_pk_can_do( &clicert.pk, MBEDTLS_PK_RSA ) )
-        {
-            mbedtls_printf( " failed\n  !  certificate's key is not RSA\n\n" );
-            goto exit;
-        }
-
-        ret = mbedtls_mpi_cmp_mpi(&mbedtls_pk_rsa( pk )->N, &mbedtls_pk_rsa( clicert.pk )->N);
-        if( ret != 0 )
-        {
-            mbedtls_printf( " failed\n  !  mbedtls_mpi_cmp_mpi for N returned %d\n\n", ret );
-            goto exit;
-        }
-
-        ret = mbedtls_mpi_cmp_mpi(&mbedtls_pk_rsa( pk )->E, &mbedtls_pk_rsa( clicert.pk )->E);
-        if( ret != 0 )
-        {
-            mbedtls_printf( " failed\n  !  mbedtls_mpi_cmp_mpi for E returned %d\n\n", ret );
-            goto exit;
-        }
-
-        ret = mbedtls_rsa_check_privkey( mbedtls_pk_rsa( pk ) );
-        if( ret != 0 )
-        {
-            mbedtls_printf( " failed\n  !  mbedtls_rsa_check_privkey returned %d\n\n", ret );
-            goto exit;
-        }
-
-        mbedtls_printf( " ok\n" );
-
-        mbedtls_x509_crt_free( &clicert );
-        mbedtls_pk_free( &pk );
-    }
-
-    exit_code = MBEDTLS_EXIT_SUCCESS;
-
-exit:
-    mbedtls_x509_crt_free( &cacert );
-    mbedtls_x509_crl_free( &crl );
-
-#if defined(_WIN32)
-    mbedtls_printf( "  + Press Enter to exit this program.\n" );
-    fflush( stdout ); getchar();
-#endif
-
-    return( exit_code );
-}
-#endif /* MBEDTLS_RSA_C && MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_FS_IO &&
-          MBEDTLS_X509_CRL_PARSE_C */
diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile
index aa9fc36..748514d 100644
--- a/tests/data_files/Makefile
+++ b/tests/data_files/Makefile
@@ -153,7 +153,7 @@
 all_final += test-int-ca3-badsign.crt
 server10_int3-bs.pem: server10.crt test-int-ca3-badsign.crt
 	cat server10.crt test-int-ca3-badsign.crt > $@
-all_final += server10-bs_int3-bs.pem
+all_final += server10_int3-bs.pem
 
 rsa_pkcs1_2048_public.pem: server8.key
 	$(OPENSSL)  rsa -in $< -outform PEM -RSAPublicKey_out -out $@
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index d8374cc..999fe6e 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -611,6 +611,17 @@
 #### Build and test many configurations and targets
 ################################################################
 
+component_test_default_out_of_box () {
+    msg "build: make, default config (out-of-box)" # ~1min
+    make
+
+    msg "test: main suites make, default config (out-of-box)" # ~10s
+    make test
+
+    msg "selftest: make, default config (out-of-box)" # ~10s
+    programs/test/selftest
+}
+
 component_test_default_cmake_gcc_asan () {
     msg "build: cmake, gcc, ASan" # ~ 1 min 50s
     CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
@@ -678,23 +689,6 @@
     if_build_succeeded tests/compat.sh -t RSA
 }
 
-component_test_new_ecdh_context () {
-    msg "build: new ECDH context (ASan build)" # ~ 6 min
-    scripts/config.pl unset MBEDTLS_ECDH_LEGACY_CONTEXT
-    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
-    make
-
-    msg "test: new ECDH context - main suites (inc. selftests) (ASan build)" # ~ 50s
-    make test
-
-    msg "test: new ECDH context - ECDH-related part of ssl-opt.sh (ASan build)" # ~ 5s
-    if_build_succeeded tests/ssl-opt.sh -f ECDH
-
-    msg "test: new ECDH context - compat.sh with some ECDH ciphersuites (ASan build)" # ~ 3 min
-    # Exclude some symmetric ciphers that are redundant here to gain time.
-    if_build_succeeded tests/compat.sh -f ECDH -V NO -e 'ARCFOUR\|ARIA\|CAMELLIA\|CHACHA\|DES\|RC4'
-}
-
 component_test_small_ssl_out_content_len () {
     msg "build: small SSL_OUT_CONTENT_LEN (ASan build)"
     scripts/config.pl set MBEDTLS_SSL_IN_CONTENT_LEN 16384
@@ -1043,34 +1037,6 @@
     make test
 }
 
-component_test_aes_fewer_tables () {
-    msg "build: default config with AES_FEWER_TABLES enabled"
-    scripts/config.pl set MBEDTLS_AES_FEWER_TABLES
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra'
-
-    msg "test: AES_FEWER_TABLES"
-    make test
-}
-
-component_test_aes_rom_tables () {
-    msg "build: default config with AES_ROM_TABLES enabled"
-    scripts/config.pl set MBEDTLS_AES_ROM_TABLES
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra'
-
-    msg "test: AES_ROM_TABLES"
-    make test
-}
-
-component_test_aes_fewer_tables_and_rom_tables () {
-    msg "build: default config with AES_ROM_TABLES and AES_FEWER_TABLES enabled"
-    scripts/config.pl set MBEDTLS_AES_FEWER_TABLES
-    scripts/config.pl set MBEDTLS_AES_ROM_TABLES
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra'
-
-    msg "test: AES_FEWER_TABLES + AES_ROM_TABLES"
-    make test
-}
-
 component_test_make_shared () {
     msg "build/test: make shared" # ~ 40s
     make SHARED=1 all check
@@ -1096,10 +1062,16 @@
     # Build again with -O1, to compile in the i386 specific inline assembly
     msg "build: i386, make, gcc -O1 (ASan build)" # ~ 30s
     scripts/config.pl full
+    scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE
+    scripts/config.pl unset MBEDTLS_MEMORY_BUFFER_ALLOC_C
+    scripts/config.pl unset MBEDTLS_MEMORY_DEBUG
     make CC=gcc CFLAGS='-O1 -Werror -Wall -Wextra -m32 -fsanitize=address'
 
     msg "test: i386, make, gcc -O1 (ASan build)"
     make test
+
+    msg "test ssl-opt.sh, i386, make, gcc-O1"
+    if_build_succeeded tests/ssl-opt.sh
 }
 support_test_m32_o1 () {
     support_test_m32_o0 "$@"
@@ -1120,60 +1092,6 @@
     esac
 }
 
-component_test_min_mpi_window_size () {
-    msg "build: Default + MBEDTLS_MPI_WINDOW_SIZE=1 (ASan build)" # ~ 10s
-    scripts/config.pl set MBEDTLS_MPI_WINDOW_SIZE 1
-    CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
-    make
-
-    msg "test: MBEDTLS_MPI_WINDOW_SIZE=1 - main suites (inc. selftests) (ASan build)" # ~ 10s
-    make test
-}
-
-component_test_have_int32 () {
-    msg "build: gcc, force 32-bit bignum limbs"
-    scripts/config.pl unset MBEDTLS_HAVE_ASM
-    scripts/config.pl unset MBEDTLS_AESNI_C
-    scripts/config.pl unset MBEDTLS_PADLOCK_C
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT32'
-
-    msg "test: gcc, force 32-bit bignum limbs"
-    make test
-}
-
-component_test_have_int64 () {
-    msg "build: gcc, force 64-bit bignum limbs"
-    scripts/config.pl unset MBEDTLS_HAVE_ASM
-    scripts/config.pl unset MBEDTLS_AESNI_C
-    scripts/config.pl unset MBEDTLS_PADLOCK_C
-    make CC=gcc CFLAGS='-Werror -Wall -Wextra -DMBEDTLS_HAVE_INT64'
-
-    msg "test: gcc, force 64-bit bignum limbs"
-    make test
-}
-
-component_test_no_udbl_division () {
-    msg "build: MBEDTLS_NO_UDBL_DIVISION native" # ~ 10s
-    scripts/config.pl full
-    scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
-    scripts/config.pl set MBEDTLS_NO_UDBL_DIVISION
-    make CFLAGS='-Werror -O1'
-
-    msg "test: MBEDTLS_NO_UDBL_DIVISION native" # ~ 10s
-    make test
-}
-
-component_test_no_64bit_multiplication () {
-    msg "build: MBEDTLS_NO_64BIT_MULTIPLICATION native" # ~ 10s
-    scripts/config.pl full
-    scripts/config.pl unset MBEDTLS_MEMORY_BACKTRACE # too slow for tests
-    scripts/config.pl set MBEDTLS_NO_64BIT_MULTIPLICATION
-    make CFLAGS='-Werror -O1'
-
-    msg "test: MBEDTLS_NO_64BIT_MULTIPLICATION native" # ~ 10s
-    make test
-}
-
 component_build_arm_none_eabi_gcc () {
     msg "build: arm-none-eabi-gcc, make" # ~ 10s
     scripts/config.pl full
@@ -1320,10 +1238,8 @@
     msg "test: main suites valgrind (Release)"
     make memcheck
 
-    # Optional part(s)
-    # Currently broken, programs don't seem to receive signals
-    # under valgrind on OS X
-
+    # Optional parts (slow; currently broken on OS X because programs don't
+    # seem to receive signals under valgrind on OS X).
     if [ "$MEMORY" -gt 0 ]; then
         msg "test: ssl-opt.sh --memcheck (Release)"
         if_build_succeeded tests/ssl-opt.sh --memcheck
diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh
index d952f33..08d4be3 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -767,8 +767,8 @@
 run_test_psa() {
     requires_config_enabled MBEDTLS_USE_PSA_CRYPTO
     run_test    "PSA-supported ciphersuite: $1" \
-                "$P_SRV debug_level=2 force_version=tls1_2" \
-                "$P_CLI debug_level=2 force_version=tls1_2 force_ciphersuite=$1" \
+                "$P_SRV debug_level=3 force_version=tls1_2" \
+                "$P_CLI debug_level=3 force_version=tls1_2 force_ciphersuite=$1" \
                 0 \
                 -c "Successfully setup PSA-based decryption cipher context" \
                 -c "Successfully setup PSA-based encryption cipher context" \
@@ -941,6 +941,29 @@
             -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 "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
@@ -1008,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
@@ -2575,7 +2619,8 @@
             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 \
@@ -2954,6 +2999,208 @@
             -c "! mbedtls_ssl_handshake returned" \
             -s "X509 - Certificate verification failed"
 
+# 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" \
+            "$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" \
diff --git a/tests/suites/test_suite_cipher.function b/tests/suites/test_suite_cipher.function
index 9a0637e..ca39937 100644
--- a/tests/suites/test_suite_cipher.function
+++ b/tests/suites/test_suite_cipher.function
@@ -1011,6 +1011,20 @@
     TEST_ASSERT( memcmp( output, clear->x, clear->len ) == 0 );
 
     /* then encrypt the clear->x and make sure we get the same ciphertext and tag->x */
+    mbedtls_cipher_free( &ctx );
+#if defined(MBEDTLS_USE_PSA_CRYPTO)
+    if( use_psa == 1 )
+    {
+        TEST_ASSERT( 0 == mbedtls_cipher_setup_psa( &ctx,
+                              mbedtls_cipher_info_from_type( cipher_id ),
+                              tag->len ) );
+    }
+    else
+#endif
+    {
+        TEST_ASSERT( 0 == mbedtls_cipher_setup( &ctx,
+                              mbedtls_cipher_info_from_type( cipher_id ) ) );
+    }
     TEST_ASSERT( 0 == mbedtls_cipher_setkey( &ctx, key->x, 8 * key->len,
                                              MBEDTLS_ENCRYPT ) );
 
diff --git a/tests/suites/test_suite_x509parse.data b/tests/suites/test_suite_x509parse.data
index 042d653..edd3a6f 100644
--- a/tests/suites/test_suite_x509parse.data
+++ b/tests/suites/test_suite_x509parse.data
@@ -827,6 +827,10 @@
 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_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
 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 4a82608..b11ab84 100644
--- a/tests/suites/test_suite_x509parse.function
+++ b/tests/suites/test_suite_x509parse.function
@@ -68,6 +68,71 @@
     return 0;
 }
 
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+int ca_callback_fail( void *data, mbedtls_x509_crt const *child, mbedtls_x509_crt **candidates )
+{
+    ((void) data);
+    ((void) child);
+    ((void) candidates);
+
+    return -1;
+}
+
+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;
+
+    /* 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;
+        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( ret );
+}
+#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 +439,19 @@
     TEST_ASSERT( res == ( result ) );
     TEST_ASSERT( flags == (uint32_t)( flags_result ) );
 
+#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
+    /* CRLs aren't supported with CA callbacks, so skip the CA callback
+     * version of the test if CRLs are in use. */
+    if( crl_file == NULL || strcmp( crl_file, "" ) == 0 )
+    {
+        flags = 0;
+
+        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 ) );
+    }
+#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
 exit:
     mbedtls_x509_crt_free( &crt );
     mbedtls_x509_crt_free( &ca );
@@ -381,6 +459,36 @@
 }
 /* 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 )
+{
+    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_ca_cb( &crt, ca_callback_fail, &ca,
+                                              &compat_profile, name, &flags,
+                                              NULL, NULL );
+
+    TEST_ASSERT( ret == exp_ret );
+    TEST_ASSERT( flags == (uint32_t)( -1 ) );
+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 )
diff --git a/visualc/VS2010/mbedTLS.sln b/visualc/VS2010/mbedTLS.sln
index 85429b8..5d2c99c 100644
--- a/visualc/VS2010/mbedTLS.sln
+++ b/visualc/VS2010/mbedTLS.sln
@@ -183,11 +183,6 @@
 		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

 	EndProjectSection

 EndProject

-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_cert_test", "ssl_cert_test.vcxproj", "{3FE0C0E1-D9BA-6A26-380C-F293E543B914}"

-	ProjectSection(ProjectDependencies) = postProject

-		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

-	EndProjectSection

-EndProject

 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "benchmark", "benchmark.vcxproj", "{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}"

 	ProjectSection(ProjectDependencies) = postProject

 		{46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554}

@@ -552,14 +547,6 @@
 		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|Win32.Build.0 = Release|Win32

 		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|x64.ActiveCfg = Release|x64

 		{5FCC71F6-FF33-EBCF-FBA2-8FC783D5318E}.Release|x64.Build.0 = Release|x64

-		{3FE0C0E1-D9BA-6A26-380C-F293E543B914}.Debug|Win32.ActiveCfg = Debug|Win32

-		{3FE0C0E1-D9BA-6A26-380C-F293E543B914}.Debug|Win32.Build.0 = Debug|Win32

-		{3FE0C0E1-D9BA-6A26-380C-F293E543B914}.Debug|x64.ActiveCfg = Debug|x64

-		{3FE0C0E1-D9BA-6A26-380C-F293E543B914}.Debug|x64.Build.0 = Debug|x64

-		{3FE0C0E1-D9BA-6A26-380C-F293E543B914}.Release|Win32.ActiveCfg = Release|Win32

-		{3FE0C0E1-D9BA-6A26-380C-F293E543B914}.Release|Win32.Build.0 = Release|Win32

-		{3FE0C0E1-D9BA-6A26-380C-F293E543B914}.Release|x64.ActiveCfg = Release|x64

-		{3FE0C0E1-D9BA-6A26-380C-F293E543B914}.Release|x64.Build.0 = Release|x64

 		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|Win32.ActiveCfg = Debug|Win32

 		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|Win32.Build.0 = Debug|Win32

 		{90EFD9A4-C6B0-3EE8-1F06-0A0E0D55AEDA}.Debug|x64.ActiveCfg = Debug|x64

diff --git a/visualc/VS2010/ssl_cert_test.vcxproj b/visualc/VS2010/ssl_cert_test.vcxproj
deleted file mode 100644
index b8f014e..0000000
--- a/visualc/VS2010/ssl_cert_test.vcxproj
+++ /dev/null
@@ -1,174 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>

-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-  <ItemGroup Label="ProjectConfigurations">

-    <ProjectConfiguration Include="Debug|Win32">

-      <Configuration>Debug</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Debug|x64">

-      <Configuration>Debug</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|Win32">

-      <Configuration>Release</Configuration>

-      <Platform>Win32</Platform>

-    </ProjectConfiguration>

-    <ProjectConfiguration Include="Release|x64">

-      <Configuration>Release</Configuration>

-      <Platform>x64</Platform>

-    </ProjectConfiguration>

-  </ItemGroup>

-  <ItemGroup>

-    <ClCompile Include="..\..\programs\test\ssl_cert_test.c" />

-  </ItemGroup>

-  <ItemGroup>

-    <ProjectReference Include="mbedTLS.vcxproj">
-      <Project>{46cf2d25-6a36-4189-b59c-e4815388e554}</Project>

-      <LinkLibraryDependencies>true</LinkLibraryDependencies>

-    </ProjectReference>

-  </ItemGroup>

-  <PropertyGroup Label="Globals">

-    <ProjectGuid>{3FE0C0E1-D9BA-6A26-380C-F293E543B914}</ProjectGuid>

-    <Keyword>Win32Proj</Keyword>

-    <RootNamespace>ssl_cert_test</RootNamespace>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <UseDebugLibraries>true</UseDebugLibraries>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <UseDebugLibraries>true</UseDebugLibraries>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>Unicode</CharacterSet>

-  </PropertyGroup>

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">

-    <ConfigurationType>Application</ConfigurationType>

-    <UseDebugLibraries>false</UseDebugLibraries>

-    <WholeProgramOptimization>true</WholeProgramOptimization>

-    <CharacterSet>Unicode</CharacterSet>

-    <PlatformToolset>Windows7.1SDK</PlatformToolset>

-  </PropertyGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />

-  <ImportGroup Label="ExtensionSettings">

-  </ImportGroup>

-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">

-    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />

-  </ImportGroup>

-  <PropertyGroup Label="UserMacros" />

-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <LinkIncremental>true</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <LinkIncremental>false</LinkIncremental>
-    <IntDir>$(Configuration)\$(TargetName)\</IntDir>
-  </PropertyGroup>
-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

-    <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <Optimization>Disabled</Optimization>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>

-    </ClCompile>

-    <Link>

-      <SubSystem>Console</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <ShowProgress>NotSet</ShowProgress>

-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

-    </Link>

-    <ProjectReference>

-      <LinkLibraryDependencies>false</LinkLibraryDependencies>

-    </ProjectReference>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">

-    <ClCompile>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <WarningLevel>Level3</WarningLevel>

-      <Optimization>Disabled</Optimization>

-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>

-    </ClCompile>

-    <Link>

-      <SubSystem>Console</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <ShowProgress>NotSet</ShowProgress>

-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>Debug</AdditionalLibraryDirectories>

-    </Link>

-    <ProjectReference>

-      <LinkLibraryDependencies>false</LinkLibraryDependencies>

-    </ProjectReference>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">

-    <ClCompile>

-      <WarningLevel>Level3</WarningLevel>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>

-    </ClCompile>

-    <Link>

-      <SubSystem>Console</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

-      <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
-    </Link>

-  </ItemDefinitionGroup>

-  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">

-    <ClCompile>

-      <WarningLevel>Level3</WarningLevel>

-      <PrecompiledHeader>

-      </PrecompiledHeader>

-      <Optimization>MaxSpeed</Optimization>

-      <FunctionLevelLinking>true</FunctionLevelLinking>

-      <IntrinsicFunctions>true</IntrinsicFunctions>

-      <PreprocessorDefinitions>WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>

-      <AdditionalIncludeDirectories>../../include</AdditionalIncludeDirectories>

-    </ClCompile>

-    <Link>

-      <SubSystem>Console</SubSystem>

-      <GenerateDebugInformation>true</GenerateDebugInformation>

-      <EnableCOMDATFolding>true</EnableCOMDATFolding>

-      <OptimizeReferences>true</OptimizeReferences>

-      <AdditionalLibraryDirectories>Release</AdditionalLibraryDirectories>

-      <AdditionalDependencies>%(AdditionalDependencies);</AdditionalDependencies>

-    </Link>

-  </ItemDefinitionGroup>

-  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

-  <ImportGroup Label="ExtensionTargets">

-  </ImportGroup>

-</Project>