Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for trusted CA callbacks #2532

Merged
merged 29 commits into from
Apr 16, 2019
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
288dedc
Add compile-time option to enable X.509 CA callbacks
Mar 27, 2019
5c8df78
Add X.509 CRT verification API using trusted CA callbacks
Mar 27, 2019
902451d
Improve documentation of old X.509 CRT verification functions
Mar 27, 2019
8bf74f3
Add SSL configuration API for trusted CA callbacks
Mar 27, 2019
03cd120
Test for ca list callback
Mar 27, 2019
912ed33
Change callback name to ca_callback
Mar 27, 2019
557426a
Add a failure testcase for ca callback
Mar 27, 2019
1b4a2ba
Add possibility to use ca_callbacks in ssl programs
Mar 27, 2019
5adaad9
Add X.509 CA callback to SSL configuration and implement setter API
Mar 27, 2019
afd0b0a
Make use of CA callback if present when verifying peer CRT chain
Mar 27, 2019
3116fb3
Add prototype for CRT verification with static and dynamic CA list
Mar 28, 2019
f53893b
Implement X.509 CRT verification using CA callback
Mar 28, 2019
e15dae7
Declare CA callback type even if feature is disabled
Mar 28, 2019
cbb5903
Minor fixes to CA callback tests
Mar 28, 2019
0350d56
Only run X.509 CRT verification tests with CA callback tests if !CRL
Mar 28, 2019
746aaf3
Add ssl-opt.sh tests for trusted CA callbacks
Mar 28, 2019
fa738d1
Update query_config.c
Mar 28, 2019
3f932bb
Remove trailing whitespace in test_suite_x509parse.function
Mar 28, 2019
fed5d9d
Update version_features.c
Mar 28, 2019
1bac87c
Correct placement of usage macro in ssl_client2
Mar 29, 2019
d6d100b
Fix ssl_client2 and ssl_server2 if !PLATFORM_C
Mar 30, 2019
31d9db6
Change the verify function naming
Apr 1, 2019
f49fedc
Change docs according to review comments
Apr 1, 2019
2ee67a6
Remove mbedtls_ from the static function name
Apr 1, 2019
f7a7f9e
Address review comments regarding ssl_client2 and ssl tests
Apr 1, 2019
dfd22c4
Address comments for x509 tests
Apr 1, 2019
9822c0d
Fix name to function call
Apr 1, 2019
d7ecbd6
Fix style issues and a typo
yanesca Apr 5, 2019
846ae7a
Document and test flags in x509_verify
yanesca Apr 5, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 19 additions & 0 deletions include/mbedtls/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -1744,6 +1744,25 @@
*/
//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION

/**
* \def MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK
*
* If set, this enables the X.509 API `mbedtls_x509_crt_verify_with_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
*
Expand Down
61 changes: 61 additions & 0 deletions include/mbedtls/ssl.h
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,10 @@ struct mbedtls_ssl_config
mbedtls_ssl_key_cert *key_cert; /*!< own certificate/key pair(s) */
mbedtls_x509_crt *ca_chain; /*!< trusted CAs */
mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */
#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
mbedtls_x509_crt_ca_cb_t f_ca_cb;
void *p_ca_cb;
#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
#endif /* MBEDTLS_X509_CRT_PARSE_C */

#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
Expand Down Expand Up @@ -2071,6 +2075,63 @@ void mbedtls_ssl_conf_ca_chain( mbedtls_ssl_config *conf,
mbedtls_x509_crt *ca_chain,
mbedtls_x509_crl *ca_crl );

#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
/**
* \brief Set the trusted certificate callback.
*
* This API allows to register the set of trusted certificates
* through a callback, instead of a linked list as configured
* by mbedtls_ssl_conf_ca_chain().
*
* This is useful for example in contexts where a large number
* of CAs are used, and the inefficiency of maintaining them
* in a linked list cannot be tolerated. It is also useful when
* the set of trusted CAs needs to be modified frequently.
*
* See the documentation of `mbedtls_x509_crt_ca_cb_t` for
* more information.
*
* \param conf The SSL configuration to register the callback with.
* \param f_ca_cb The trusted certificate callback to use when verifying
* certificate chains.
* \param p_ca_cb The context to be passed to \p f_ca_cb (for example,
* a reference to a trusted CA database).
*
* \note This API is incompatible with mbedtls_ssl_conf_ca_chain():
* Any call to this function overwrites the values set through
* earlier calls to mbedtls_ssl_conf_ca_chain() or
* mbedtls_ssl_conf_ca_cb().
*
* \note This API is incompatible with CA indication in
* CertificateRequest messages: A server-side SSL context which
* is bound to an SSL configuration that uses a CA callback
* configured via mbedtls_ssl_conf_ca_cb(), and which requires
* client authentication, will send an empty CA list in the
* corresponding CertificateRequest message.
*
* \note This API is incompatible with mbedtls_ssl_set_hs_ca_chain():
* If an SSL context is bound to an SSL configuration which uses
* CA callbacks configured via mbedtls_ssl_conf_ca_cb(), then
* calls to mbedtls_ssl_set_hs_ca_chain() have no effect.
*
* \note The use of this API disables the use of restartable ECC
* during X.509 CRT signature verification (but doesn't affect
* other uses).
*
* \warning This API is incompatible with the use of CRLs. Any call to
* mbedtls_ssl_conf_ca_cb() unsets CRLs configured through
* earlier calls to mbedtls_ssl_conf_ca_chain().
*
* \warning In multi-threaded environments, the callback \p f_ca_cb
* must be thread-safe, and it is the user's responsibility
* to guaranteee this (for example through a mutex
* contained in the callback context pointed to by \p p_ca_cb).
*/
void mbedtls_ssl_conf_ca_cb( mbedtls_ssl_config *conf,
mbedtls_x509_crt_ca_cb_t f_ca_cb,
void *p_ca_cb );
#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */

/**
* \brief Set own certificate chain and private key
*
Expand Down
171 changes: 127 additions & 44 deletions include/mbedtls/x509_crt.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,14 @@ typedef struct
{
mbedtls_x509_crt_verify_chain_item items[MBEDTLS_X509_MAX_VERIFY_CHAIN_SIZE];
unsigned len;

#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
/* This stores the list of potential trusted signers obtained from
* the CA callback used for the CRT verification, if configured.
* We must track it somewhere because the callback passes its
* ownership to the caller. */
mbedtls_x509_crt *trust_ca_cb_result;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe trusted_ca_cb_result would be better.
Current name implies this would be true/false without knowing the type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Jarno's comment, but I don't think this needs to be changed right now, as this would either make newer code less consistent with existing names, or require changing existing names, which is what I would prefer, but probably out of scope for this PR.

#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
} mbedtls_x509_crt_verify_chain;

#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE)
Expand Down Expand Up @@ -371,7 +379,7 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
uint32_t flags );

/**
* \brief Verify the certificate signature
* \brief Verify a chain of certificates.
*
* The verify callback is a user-supplied callback that
* can clear / modify / add flags for a certificate. If set,
Expand Down Expand Up @@ -411,22 +419,25 @@ int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix,
* specific peers you know) - in that case, the self-signed
* certificate doesn't need to have the CA bit set.
*
* \param crt a certificate (chain) to be verified
* \param trust_ca the list of trusted CAs (see note above)
* \param ca_crl the list of CRLs for trusted CAs (see note above)
* \param cn expected Common Name (can be set to
* NULL if the CN must not be verified)
* \param flags result of the verification
* \param f_vrfy verification function
* \param p_vrfy verification parameter
*
* \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.
* \param crt The certificate chain to be verified.
* \param trust_ca The list of trusted CAs.
* \param ca_crl The list of CRLs for trusted CAs.
* \param cn The expected Common Name. This may be \c NULL if the
* CN need not be verified.
* \param flags The address at which to store the result of the verification.
* \param f_vrfy The verification callback to use. See the documentation
* of mbedtls_x509_crt_verify() for more information.
* \param p_vrfy The context to be passed to \p f_vrfy.
*
* \return \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,
Expand All @@ -436,7 +447,8 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
void *p_vrfy );

/**
* \brief Verify the certificate signature according to profile
* \brief Verify a chain of certificates with respect to
* a configurable security profile.
*
* \note Same as \c mbedtls_x509_crt_verify(), but with explicit
* security profile.
Expand All @@ -445,22 +457,26 @@ int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt,
* for ECDSA) apply to all certificates: trusted root,
* intermediate CAs if any, and end entity certificate.
*
* \param crt a certificate (chain) to be verified
* \param trust_ca the list of trusted CAs
* \param ca_crl the list of CRLs for trusted CAs
* \param profile security profile for verification
* \param cn expected Common Name (can be set to
* NULL if the CN must not be verified)
* \param flags result of the verification
* \param f_vrfy verification function
* \param p_vrfy verification parameter
*
* \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.
* \param crt The certificate chain to be verified.
* \param trust_ca The list of trusted CAs.
* \param ca_crl The list of CRLs for trusted CAs.
* \param profile The security profile to use for the verification.
* \param cn The expected Common Name. This may be \c NULL if the
* CN need not be verified.
* \param flags The address at which to store the result of the verification.
* \param f_vrfy The verification callback to use. See the documentation
* of mbedtls_x509_crt_verify() for more information.
* \param p_vrfy The context to be passed to \p f_vrfy.
*
* \return \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,
Expand All @@ -477,16 +493,18 @@ int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt,
* but can return early and restart according to the limit
* set with \c mbedtls_ecp_set_max_ops() to reduce blocking.
*
* \param crt a certificate (chain) to be verified
* \param trust_ca the list of trusted CAs
* \param ca_crl the list of CRLs for trusted CAs
* \param profile security profile for verification
* \param cn expected Common Name (can be set to
* NULL if the CN must not be verified)
* \param flags result of the verification
* \param f_vrfy verification function
* \param p_vrfy verification parameter
* \param rs_ctx restart context (NULL to disable restart)
* \param crt The certificate chain to be verified.
* \param trust_ca The list of trusted CAs.
* \param ca_crl The list of CRLs for trusted CAs.
* \param profile The security profile to use for the verification.
* \param cn The expected Common Name. This may be \c NULL if the
* CN need not be verified.
* \param flags The address at which to store the result of the verification.
* \param f_vrfy The verification callback to use. See the documentation
* of mbedtls_x509_crt_verify() for more information.
* \param p_vrfy The context to be passed to \p f_vrfy.
* \param rs_ctx The restart context to use. This may be set to \c NULL
* to disable restartable ECC.
*
* \return See \c mbedtls_crt_verify_with_profile(), or
* \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of
Expand All @@ -501,6 +519,71 @@ int mbedtls_x509_crt_verify_restartable( mbedtls_x509_crt *crt,
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.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree with this change, as indicated in the response to @mpg's comment.

*
* \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.
Patater marked this conversation as resolved.
Show resolved Hide resolved
* \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.
Expand Down
5 changes: 5 additions & 0 deletions library/ssl_srv.c
Original file line number Diff line number Diff line change
Expand Up @@ -2818,6 +2818,11 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )

if( ssl->conf->cert_req_ca_list == MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED )
{
/* NOTE: If trusted certificates are provisioned
* via a CA callback (configured through
* `mbedtls_ssl_conf_ca_cb()`, then the
* CertificateRequest is currently left empty. */

#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
if( ssl->handshake->sni_ca_chain != NULL )
crt = ssl->handshake->sni_ca_chain;
Expand Down