mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2025-01-26 05:01:08 +00:00
Merge pull request #583 from ARMmbed/remove_peer_crt_after_handshake-baremetal
[Baremetal] Allow removal of peer certificate to reduce RAM usage
This commit is contained in:
commit
79cf74a95f
|
@ -42,6 +42,13 @@ Features
|
|||
API Changes
|
||||
* Add a new X.509 API call `mbedtls_x509_parse_der_nocopy()`.
|
||||
See the Features section for more information.
|
||||
* Allow to opt in to the removal the API mbedtls_ssl_get_peer_cert()
|
||||
for the benefit of saving RAM, by disabling the new compile-time
|
||||
option MBEDTLS_SSL_KEEP_PEER_CERTIFICATE (enabled by default for
|
||||
API stability). Disabling this option makes mbedtls_ssl_get_peer_cert()
|
||||
always return NULL, and removes the peer_cert field from the
|
||||
mbedtls_ssl_session structure which otherwise stores the peer's
|
||||
certificate.
|
||||
|
||||
Bugfix
|
||||
* Server's RSA certificate in certs.c was SHA-1 signed. In the default
|
||||
|
|
|
@ -278,6 +278,14 @@
|
|||
#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) && \
|
||||
!defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \
|
||||
( !defined(MBEDTLS_SHA256_C) && \
|
||||
!defined(MBEDTLS_SHA512_C) && \
|
||||
!defined(MBEDTLS_SHA1_C) )
|
||||
#error "MBEDTLS_SSL_KEEP_PEER_CERTIFICATE defined, but not all prerequesites"
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \
|
||||
( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) )
|
||||
#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites"
|
||||
|
|
|
@ -1404,6 +1404,28 @@
|
|||
*/
|
||||
#define MBEDTLS_SSL_FALLBACK_SCSV
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
|
||||
*
|
||||
* This option controls the availability of the API mbedtls_ssl_get_peer_cert()
|
||||
* giving access to the peer's certificate after completion of the handshake.
|
||||
*
|
||||
* Unless you need mbedtls_ssl_peer_cert() in your application, it is
|
||||
* recommended to disable this option for reduced RAM usage.
|
||||
*
|
||||
* \note If this option is disabled, mbedtls_ssl_get_peer_cert() is still
|
||||
* defined, but always returns \c NULL.
|
||||
*
|
||||
* \note This option has no influence on the protection against the
|
||||
* triple handshake attack. Even if it is disabled, Mbed TLS will
|
||||
* still ensure that certificates do not change during renegotiation,
|
||||
* for exaple by keeping a hash of the peer's certificate.
|
||||
*
|
||||
* Comment this macro to disable storing the peer's certificate
|
||||
* after the handshake.
|
||||
*/
|
||||
#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
|
||||
|
||||
/**
|
||||
* \def MBEDTLS_SSL_HW_RECORD_ACCEL
|
||||
*
|
||||
|
|
|
@ -812,6 +812,25 @@ typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl,
|
|||
typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl );
|
||||
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) && \
|
||||
!defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
#define MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN 48
|
||||
#if defined(MBEDTLS_SHA256_C)
|
||||
#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA256
|
||||
#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 32
|
||||
#elif defined(MBEDTLS_SHA512_C)
|
||||
#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA384
|
||||
#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 48
|
||||
#elif defined(MBEDTLS_SHA1_C)
|
||||
#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE MBEDTLS_MD_SHA1
|
||||
#define MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN 20
|
||||
#else
|
||||
/* This is already checked in check_config.h, but be sure. */
|
||||
#error "Bad configuration - need SHA-1, SHA-256 or SHA-512 enabled to compute digest of peer CRT."
|
||||
#endif
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED &&
|
||||
!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
/*
|
||||
* This structure is used for storing current session data.
|
||||
*
|
||||
|
@ -835,7 +854,15 @@ struct mbedtls_ssl_session
|
|||
unsigned char master[48]; /*!< the master secret */
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
mbedtls_x509_crt *peer_cert; /*!< peer X.509 cert chain */
|
||||
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
/*! The digest of the peer's end-CRT. This must be kept to detect CRT
|
||||
* changes during renegotiation, mitigating the triple handshake attack. */
|
||||
unsigned char *peer_cert_digest;
|
||||
size_t peer_cert_digest_len;
|
||||
mbedtls_md_type_t peer_cert_digest_type;
|
||||
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
uint32_t verify_result; /*!< verification result */
|
||||
|
||||
|
@ -3230,18 +3257,34 @@ int mbedtls_ssl_get_max_out_record_payload( const mbedtls_ssl_context *ssl );
|
|||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
/**
|
||||
* \brief Return the peer certificate from the current connection
|
||||
* \brief Return the peer certificate from the current connection.
|
||||
*
|
||||
* Note: Can be NULL in case no certificate was sent during
|
||||
* the handshake. Different calls for the same connection can
|
||||
* return the same or different pointers for the same
|
||||
* certificate and even a different certificate altogether.
|
||||
* The peer cert CAN change in a single connection if
|
||||
* renegotiation is performed.
|
||||
* \param ssl The SSL context to use. This must be initialized and setup.
|
||||
*
|
||||
* \param ssl SSL context
|
||||
* \return The current peer certificate, if available.
|
||||
* The returned certificate is owned by the SSL context and
|
||||
* is valid only until the next call to the SSL API.
|
||||
* \return \c NULL if no peer certificate is available. This might
|
||||
* be because the chosen ciphersuite doesn't use CRTs
|
||||
* (PSK-based ciphersuites, for example), or because
|
||||
* #MBEDTLS_SSL_KEEP_PEER_CERTIFICATE has been disabled,
|
||||
* allowing the stack to free the peer's CRT to save memory.
|
||||
*
|
||||
* \return the current peer certificate
|
||||
* \note For one-time inspection of the peer's certificate during
|
||||
* the handshake, consider registering an X.509 CRT verification
|
||||
* callback through mbedtls_ssl_conf_verify() instead of calling
|
||||
* this function. Using mbedtls_ssl_conf_verify() also comes at
|
||||
* the benefit of allowing you to influence the verification
|
||||
* process, for example by masking expected and tolerated
|
||||
* verification failures.
|
||||
*
|
||||
* \warning You must not use the pointer returned by this function
|
||||
* after any further call to the SSL API, including
|
||||
* mbedtls_ssl_read() and mbedtls_ssl_write(); this is
|
||||
* because the pointer might change during renegotiation,
|
||||
* which happens transparently to the user.
|
||||
* If you want to use the certificate across API calls,
|
||||
* you must make a copy.
|
||||
*/
|
||||
const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ssl );
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
|
|
@ -70,7 +70,8 @@ struct mbedtls_ssl_cache_entry
|
|||
mbedtls_time_t timestamp; /*!< entry timestamp */
|
||||
#endif
|
||||
mbedtls_ssl_session session; /*!< entry session */
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
|
||||
defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
mbedtls_x509_buf peer_cert; /*!< entry peer_cert */
|
||||
#endif
|
||||
mbedtls_ssl_cache_entry *next; /*!< chain pointer */
|
||||
|
|
|
@ -486,6 +486,24 @@ static inline int mbedtls_ssl_ciphersuite_cert_req_allowed( const mbedtls_ssl_ci
|
|||
}
|
||||
}
|
||||
|
||||
static inline int mbedtls_ssl_ciphersuite_uses_srv_cert( const mbedtls_ssl_ciphersuite_t *info )
|
||||
{
|
||||
switch( info->key_exchange )
|
||||
{
|
||||
case MBEDTLS_KEY_EXCHANGE_RSA:
|
||||
case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
|
||||
case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
|
||||
case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
|
||||
case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
|
||||
case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
|
||||
case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
|
||||
return( 1 );
|
||||
|
||||
default:
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED)
|
||||
static inline int mbedtls_ssl_ciphersuite_uses_dhe( const mbedtls_ssl_ciphersuite_t *info )
|
||||
{
|
||||
|
|
|
@ -396,8 +396,13 @@ struct mbedtls_ssl_handshake_params
|
|||
ssl_ecrs_cke_ecdh_calc_secret, /*!< ClientKeyExchange: ECDH step 2 */
|
||||
ssl_ecrs_crt_vrfy_sign, /*!< CertificateVerify: pk_sign() */
|
||||
} ecrs_state; /*!< current (or last) operation */
|
||||
mbedtls_x509_crt *ecrs_peer_cert; /*!< The peer's CRT chain. */
|
||||
size_t ecrs_n; /*!< place for saving a length */
|
||||
#endif
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
|
||||
!defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
mbedtls_pk_context peer_pubkey; /*!< The public key from the peer. */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */
|
||||
unsigned int in_msg_seq; /*!< Incoming handshake sequence number */
|
||||
|
@ -989,6 +994,9 @@ int mbedtls_ssl_dtls_replay_check( mbedtls_ssl_context *ssl );
|
|||
void mbedtls_ssl_dtls_replay_update( mbedtls_ssl_context *ssl );
|
||||
#endif
|
||||
|
||||
int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
|
||||
const mbedtls_ssl_session *src );
|
||||
|
||||
/* constant-time buffer comparison */
|
||||
static inline int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n )
|
||||
{
|
||||
|
|
|
@ -70,6 +70,7 @@ typedef struct mbedtls_x509_crt
|
|||
mbedtls_x509_time valid_from; /**< Start time of certificate validity. */
|
||||
mbedtls_x509_time valid_to; /**< End time of certificate validity. */
|
||||
|
||||
mbedtls_x509_buf pk_raw;
|
||||
mbedtls_pk_context pk; /**< Container for the public key context. */
|
||||
|
||||
mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#endif
|
||||
|
||||
#include "mbedtls/ssl_cache.h"
|
||||
#include "mbedtls/ssl_internal.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
@ -92,16 +93,24 @@ int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session )
|
|||
entry->session.id_len ) != 0 )
|
||||
continue;
|
||||
|
||||
memcpy( session->master, entry->session.master, 48 );
|
||||
ret = mbedtls_ssl_session_copy( session, &entry->session );
|
||||
if( ret != 0 )
|
||||
{
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
session->verify_result = entry->session.verify_result;
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
|
||||
defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
/*
|
||||
* Restore peer certificate (without rest of the original chain)
|
||||
*/
|
||||
if( entry->peer_cert.p != NULL )
|
||||
{
|
||||
/* `session->peer_cert` is NULL after the call to
|
||||
* mbedtls_ssl_session_copy(), because cache entries
|
||||
* have the `peer_cert` field set to NULL. */
|
||||
|
||||
if( ( session->peer_cert = mbedtls_calloc( 1,
|
||||
sizeof(mbedtls_x509_crt) ) ) == NULL )
|
||||
{
|
||||
|
@ -119,7 +128,7 @@ int mbedtls_ssl_cache_get( void *data, mbedtls_ssl_session *session )
|
|||
goto exit;
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
ret = 0;
|
||||
goto exit;
|
||||
|
@ -239,9 +248,8 @@ int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session )
|
|||
#endif
|
||||
}
|
||||
|
||||
memcpy( &cur->session, session, sizeof( mbedtls_ssl_session ) );
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
|
||||
defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
/*
|
||||
* If we're reusing an entry, free its certificate first
|
||||
*/
|
||||
|
@ -250,26 +258,43 @@ int mbedtls_ssl_cache_set( void *data, const mbedtls_ssl_session *session )
|
|||
mbedtls_free( cur->peer_cert.p );
|
||||
memset( &cur->peer_cert, 0, sizeof(mbedtls_x509_buf) );
|
||||
}
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
/*
|
||||
* Store peer certificate
|
||||
*/
|
||||
if( session->peer_cert != NULL )
|
||||
/* Copy the entire session; this temporarily makes a copy of the
|
||||
* X.509 CRT structure even though we only want to store the raw CRT.
|
||||
* This inefficiency will go away as soon as we implement on-demand
|
||||
* parsing of CRTs, in which case there's no need for the `peer_cert`
|
||||
* field anymore in the first place, and we're done after this call. */
|
||||
ret = mbedtls_ssl_session_copy( &cur->session, session );
|
||||
if( ret != 0 )
|
||||
{
|
||||
cur->peer_cert.p = mbedtls_calloc( 1, session->peer_cert->raw.len );
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
|
||||
defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
/* If present, free the X.509 structure and only store the raw CRT data. */
|
||||
if( cur->session.peer_cert != NULL )
|
||||
{
|
||||
cur->peer_cert.p =
|
||||
mbedtls_calloc( 1, cur->session.peer_cert->raw.len );
|
||||
if( cur->peer_cert.p == NULL )
|
||||
{
|
||||
ret = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
memcpy( cur->peer_cert.p, session->peer_cert->raw.p,
|
||||
session->peer_cert->raw.len );
|
||||
memcpy( cur->peer_cert.p,
|
||||
cur->session.peer_cert->raw.p,
|
||||
cur->session.peer_cert->raw.len );
|
||||
cur->peer_cert.len = session->peer_cert->raw.len;
|
||||
|
||||
mbedtls_x509_crt_free( cur->session.peer_cert );
|
||||
mbedtls_free( cur->session.peer_cert );
|
||||
cur->session.peer_cert = NULL;
|
||||
}
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
ret = 0;
|
||||
|
||||
|
@ -311,9 +336,10 @@ void mbedtls_ssl_cache_free( mbedtls_ssl_cache_context *cache )
|
|||
|
||||
mbedtls_ssl_session_free( &prv->session );
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
|
||||
defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
mbedtls_free( prv->peer_cert.p );
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
mbedtls_free( prv );
|
||||
}
|
||||
|
|
|
@ -2288,6 +2288,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
|
|||
int ret;
|
||||
size_t len_bytes = ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2;
|
||||
unsigned char *p = ssl->handshake->premaster + pms_offset;
|
||||
mbedtls_pk_context * peer_pk;
|
||||
|
||||
if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN )
|
||||
{
|
||||
|
@ -2313,23 +2314,28 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
|
|||
|
||||
ssl->handshake->pmslen = 48;
|
||||
|
||||
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
peer_pk = &ssl->handshake->peer_pubkey;
|
||||
#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
if( ssl->session_negotiate->peer_cert == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
||||
/* Should never happen */
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
peer_pk = &ssl->session_negotiate->peer_cert->pk;
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
/*
|
||||
* Now write it out, encrypted
|
||||
*/
|
||||
if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk,
|
||||
MBEDTLS_PK_RSA ) )
|
||||
if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_RSA ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "certificate key type mismatch" ) );
|
||||
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_pk_encrypt( &ssl->session_negotiate->peer_cert->pk,
|
||||
if( ( ret = mbedtls_pk_encrypt( peer_pk,
|
||||
p, ssl->handshake->pmslen,
|
||||
ssl->out_msg + offset + len_bytes, olen,
|
||||
MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes,
|
||||
|
@ -2349,6 +2355,10 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
|
|||
}
|
||||
#endif
|
||||
|
||||
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
/* We don't need the peer's public key anymore. Free it. */
|
||||
mbedtls_pk_free( peer_pk );
|
||||
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED ||
|
||||
|
@ -2424,21 +2434,27 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
|
|||
{
|
||||
int ret;
|
||||
const mbedtls_ecp_keypair *peer_key;
|
||||
mbedtls_pk_context * peer_pk;
|
||||
|
||||
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
peer_pk = &ssl->handshake->peer_pubkey;
|
||||
#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
if( ssl->session_negotiate->peer_cert == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
||||
/* Should never happen */
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
peer_pk = &ssl->session_negotiate->peer_cert->pk;
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk,
|
||||
MBEDTLS_PK_ECKEY ) )
|
||||
if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECKEY ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "server key not ECDH capable" ) );
|
||||
return( MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH );
|
||||
}
|
||||
|
||||
peer_key = mbedtls_pk_ec( ssl->session_negotiate->peer_cert->pk );
|
||||
peer_key = mbedtls_pk_ec( *peer_pk );
|
||||
|
||||
if( ( ret = mbedtls_ecdh_get_params( &ssl->handshake->ecdh_ctx, peer_key,
|
||||
MBEDTLS_ECDH_THEIRS ) ) != 0 )
|
||||
|
@ -2453,6 +2469,13 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
|
|||
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
/* We don't need the peer's public key anymore. Free it,
|
||||
* so that more RAM is available for upcoming expensive
|
||||
* operations like ECDHE. */
|
||||
mbedtls_pk_free( peer_pk );
|
||||
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
|
||||
|
@ -2645,6 +2668,8 @@ start_processing:
|
|||
size_t params_len = p - params;
|
||||
void *rs_ctx = NULL;
|
||||
|
||||
mbedtls_pk_context * peer_pk;
|
||||
|
||||
/*
|
||||
* Handle the digitally-signed structure
|
||||
*/
|
||||
|
@ -2747,18 +2772,22 @@ start_processing:
|
|||
|
||||
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
|
||||
|
||||
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
peer_pk = &ssl->handshake->peer_pubkey;
|
||||
#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
if( ssl->session_negotiate->peer_cert == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "certificate required" ) );
|
||||
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE );
|
||||
return( MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE );
|
||||
/* Should never happen */
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
peer_pk = &ssl->session_negotiate->peer_cert->pk;
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
/*
|
||||
* Verify signature
|
||||
*/
|
||||
if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) )
|
||||
if( !mbedtls_pk_can_do( peer_pk, pk_alg ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad server key exchange message" ) );
|
||||
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
|
@ -2771,8 +2800,7 @@ start_processing:
|
|||
rs_ctx = &ssl->handshake->ecrs_ctx.pk;
|
||||
#endif
|
||||
|
||||
if( ( ret = mbedtls_pk_verify_restartable(
|
||||
&ssl->session_negotiate->peer_cert->pk,
|
||||
if( ( ret = mbedtls_pk_verify_restartable( peer_pk,
|
||||
md_alg, hash, hashlen, p, sig_len, rs_ctx ) ) != 0 )
|
||||
{
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
|
@ -2787,6 +2815,13 @@ start_processing:
|
|||
#endif
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
/* We don't need the peer's public key anymore. Free it,
|
||||
* so that more RAM is available for upcoming expensive
|
||||
* operations like ECDHE. */
|
||||
mbedtls_pk_free( peer_pk );
|
||||
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
|
||||
|
||||
|
@ -3306,12 +3341,7 @@ ecdh_calc_secret:
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
|
||||
#if !defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED)
|
||||
static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
|
@ -3326,11 +3356,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
return( ret );
|
||||
}
|
||||
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
|
||||
if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
|
||||
ssl->state++;
|
||||
|
@ -3340,7 +3366,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
#else
|
||||
#else /* !MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */
|
||||
static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
|
||||
|
@ -3369,11 +3395,7 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
return( ret );
|
||||
}
|
||||
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
|
||||
if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate verify" ) );
|
||||
ssl->state++;
|
||||
|
@ -3514,12 +3536,7 @@ sign:
|
|||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
static int ssl_parse_new_session_ticket( mbedtls_ssl_context *ssl )
|
||||
|
|
|
@ -2801,12 +2801,7 @@ static int ssl_write_server_hello( mbedtls_ssl_context *ssl )
|
|||
return( ret );
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
|
||||
#if !defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED)
|
||||
static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
|
@ -2814,11 +2809,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
|
|||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate request" ) );
|
||||
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
|
||||
if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
|
||||
ssl->state++;
|
||||
|
@ -2828,7 +2819,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
|
|||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
#else
|
||||
#else /* !MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */
|
||||
static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
|
||||
|
@ -2852,11 +2843,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
|
|||
#endif
|
||||
authmode = ssl->conf->authmode;
|
||||
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
|
||||
if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) ||
|
||||
authmode == MBEDTLS_SSL_VERIFY_NONE )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate request" ) );
|
||||
|
@ -2995,12 +2982,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
|
|||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \
|
||||
defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
|
||||
|
@ -4147,12 +4129,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)&& \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED)
|
||||
#if !defined(MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED)
|
||||
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
|
@ -4160,11 +4137,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
|
||||
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
|
||||
if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
|
||||
ssl->state++;
|
||||
|
@ -4174,7 +4147,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "should never happen" ) );
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
#else
|
||||
#else /* !MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */
|
||||
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
int ret = MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE;
|
||||
|
@ -4188,21 +4161,33 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
mbedtls_md_type_t md_alg;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->handshake->ciphersuite_info;
|
||||
mbedtls_pk_context * peer_pk;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate verify" ) );
|
||||
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE ||
|
||||
ssl->session_negotiate->peer_cert == NULL )
|
||||
if( !mbedtls_ssl_ciphersuite_cert_req_allowed( ciphersuite_info ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
|
||||
ssl->state++;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
if( ssl->session_negotiate->peer_cert == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
|
||||
ssl->state++;
|
||||
return( 0 );
|
||||
}
|
||||
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
if( ssl->session_negotiate->peer_cert_digest == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate verify" ) );
|
||||
ssl->state++;
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
/* Read the message without adding it to the checksum */
|
||||
ret = mbedtls_ssl_read_record( ssl, 0 /* no checksum update */ );
|
||||
if( 0 != ret )
|
||||
|
@ -4223,6 +4208,17 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
|
||||
i = mbedtls_ssl_hs_hdr_len( ssl );
|
||||
|
||||
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
peer_pk = &ssl->handshake->peer_pubkey;
|
||||
#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
if( ssl->session_negotiate->peer_cert == NULL )
|
||||
{
|
||||
/* Should never happen */
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
peer_pk = &ssl->session_negotiate->peer_cert->pk;
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
/*
|
||||
* struct {
|
||||
* SignatureAndHashAlgorithm algorithm; -- TLS 1.2 only
|
||||
|
@ -4237,8 +4233,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
hashlen = 36;
|
||||
|
||||
/* For ECDSA, use SHA-1, not MD-5 + SHA-1 */
|
||||
if( mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk,
|
||||
MBEDTLS_PK_ECDSA ) )
|
||||
if( mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_ECDSA ) )
|
||||
{
|
||||
hash_start += 16;
|
||||
hashlen -= 16;
|
||||
|
@ -4293,7 +4288,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
/*
|
||||
* Check the certificate's key type matches the signature alg
|
||||
*/
|
||||
if( ! mbedtls_pk_can_do( &ssl->session_negotiate->peer_cert->pk, pk_alg ) )
|
||||
if( !mbedtls_pk_can_do( peer_pk, pk_alg ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "sig_alg doesn't match cert key" ) );
|
||||
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY );
|
||||
|
@ -4329,7 +4324,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
ssl->handshake->calc_verify( ssl, hash, &dummy_hlen );
|
||||
}
|
||||
|
||||
if( ( ret = mbedtls_pk_verify( &ssl->session_negotiate->peer_cert->pk,
|
||||
if( ( ret = mbedtls_pk_verify( peer_pk,
|
||||
md_alg, hash_start, hashlen,
|
||||
ssl->in_msg + i, sig_len ) ) != 0 )
|
||||
{
|
||||
|
@ -4343,12 +4338,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
|||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED &&
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED */
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__CERT_REQ_ALLOWED__ENABLED */
|
||||
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
|
||||
static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
|
||||
|
|
|
@ -368,13 +368,15 @@ static unsigned int ssl_mfl_code_to_length( int mfl )
|
|||
}
|
||||
#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */
|
||||
|
||||
#if defined(MBEDTLS_SSL_CLI_C)
|
||||
static int ssl_session_copy( mbedtls_ssl_session *dst, const mbedtls_ssl_session *src )
|
||||
int mbedtls_ssl_session_copy( mbedtls_ssl_session *dst,
|
||||
const mbedtls_ssl_session *src )
|
||||
{
|
||||
mbedtls_ssl_session_free( dst );
|
||||
memcpy( dst, src, sizeof( mbedtls_ssl_session ) );
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
if( src->peer_cert != NULL )
|
||||
{
|
||||
int ret;
|
||||
|
@ -393,6 +395,21 @@ static int ssl_session_copy( mbedtls_ssl_session *dst, const mbedtls_ssl_session
|
|||
return( ret );
|
||||
}
|
||||
}
|
||||
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
if( src->peer_cert_digest != NULL )
|
||||
{
|
||||
dst->peer_cert_digest =
|
||||
mbedtls_calloc( 1, src->peer_cert_digest_len );
|
||||
if( dst->peer_cert_digest == NULL )
|
||||
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
|
||||
|
||||
memcpy( dst->peer_cert_digest, src->peer_cert_digest,
|
||||
src->peer_cert_digest_len );
|
||||
dst->peer_cert_digest_type = src->peer_cert_digest_type;
|
||||
dst->peer_cert_digest_len = src->peer_cert_digest_len;
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
|
||||
|
@ -408,7 +425,6 @@ static int ssl_session_copy( mbedtls_ssl_session *dst, const mbedtls_ssl_session
|
|||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_CLI_C */
|
||||
|
||||
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
|
||||
int (*mbedtls_ssl_hw_record_init)( mbedtls_ssl_context *ssl,
|
||||
|
@ -5973,16 +5989,33 @@ int mbedtls_ssl_send_alert_message( mbedtls_ssl_context *ssl,
|
|||
return( 0 );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
static void ssl_clear_peer_cert( mbedtls_ssl_session *session )
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
if( session->peer_cert != NULL )
|
||||
{
|
||||
mbedtls_x509_crt_free( session->peer_cert );
|
||||
mbedtls_free( session->peer_cert );
|
||||
session->peer_cert = NULL;
|
||||
}
|
||||
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
if( session->peer_cert_digest != NULL )
|
||||
{
|
||||
/* Zeroization is not necessary. */
|
||||
mbedtls_free( session->peer_cert_digest );
|
||||
session->peer_cert_digest = NULL;
|
||||
session->peer_cert_digest_type = MBEDTLS_MD_NONE;
|
||||
session->peer_cert_digest_len = 0;
|
||||
}
|
||||
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
}
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
/*
|
||||
* Handshake functions
|
||||
*/
|
||||
#if !defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \
|
||||
!defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED)
|
||||
#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
|
||||
/* No certificate support -> dummy functions */
|
||||
int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
|
@ -5990,10 +6023,7 @@ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
|
|||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
|
||||
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
|
||||
if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
|
||||
ssl->state++;
|
||||
|
@ -6010,10 +6040,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
|
|||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
|
||||
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
|
||||
if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
|
||||
ssl->state++;
|
||||
|
@ -6024,7 +6051,7 @@ int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
|
|||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
|
||||
#else
|
||||
#else /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
|
||||
/* Some certificate support -> implement write and parse */
|
||||
|
||||
int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
|
||||
|
@ -6036,10 +6063,7 @@ int mbedtls_ssl_write_certificate( mbedtls_ssl_context *ssl )
|
|||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate" ) );
|
||||
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
|
||||
if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write certificate" ) );
|
||||
ssl->state++;
|
||||
|
@ -6144,6 +6168,8 @@ write_msg:
|
|||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
|
||||
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
|
||||
unsigned char *crt_buf,
|
||||
size_t crt_buf_len )
|
||||
|
@ -6158,65 +6184,51 @@ static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
|
|||
|
||||
return( memcmp( peer_crt->raw.p, crt_buf, crt_buf_len ) );
|
||||
}
|
||||
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
static int ssl_check_peer_crt_unchanged( mbedtls_ssl_context *ssl,
|
||||
unsigned char *crt_buf,
|
||||
size_t crt_buf_len )
|
||||
{
|
||||
int ret;
|
||||
unsigned char const * const peer_cert_digest =
|
||||
ssl->session->peer_cert_digest;
|
||||
mbedtls_md_type_t const peer_cert_digest_type =
|
||||
ssl->session->peer_cert_digest_type;
|
||||
mbedtls_md_info_t const * const digest_info =
|
||||
mbedtls_md_info_from_type( peer_cert_digest_type );
|
||||
unsigned char tmp_digest[MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN];
|
||||
size_t digest_len;
|
||||
|
||||
if( peer_cert_digest == NULL || digest_info == NULL )
|
||||
return( -1 );
|
||||
|
||||
digest_len = mbedtls_md_get_size( digest_info );
|
||||
if( digest_len > MBEDTLS_SSL_PEER_CERT_DIGEST_MAX_LEN )
|
||||
return( -1 );
|
||||
|
||||
ret = mbedtls_md( digest_info, crt_buf, crt_buf_len, tmp_digest );
|
||||
if( ret != 0 )
|
||||
return( -1 );
|
||||
|
||||
return( memcmp( tmp_digest, peer_cert_digest, digest_len ) );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
|
||||
|
||||
/*
|
||||
* Once the certificate message is read, parse it into a cert chain and
|
||||
* perform basic checks, but leave actual verification to the caller
|
||||
*/
|
||||
static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl )
|
||||
static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl,
|
||||
mbedtls_x509_crt *chain )
|
||||
{
|
||||
int ret;
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
|
||||
int crt_cnt=0;
|
||||
#endif
|
||||
size_t i, n;
|
||||
uint8_t alert;
|
||||
|
||||
#if defined(MBEDTLS_SSL_SRV_C)
|
||||
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
||||
/*
|
||||
* Check if the client sent an empty certificate
|
||||
*/
|
||||
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
|
||||
ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
|
||||
{
|
||||
if( ssl->in_msglen == 2 &&
|
||||
ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT &&
|
||||
ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
|
||||
ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
|
||||
|
||||
/* The client was asked for a certificate but didn't send
|
||||
one. The client should know what's going on, so we
|
||||
don't send an alert. */
|
||||
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
|
||||
return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_PROTO_SSL3 */
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
||||
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
|
||||
ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
|
||||
{
|
||||
if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) &&
|
||||
ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
|
||||
ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE &&
|
||||
memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
|
||||
|
||||
/* The client was asked for a certificate but didn't send
|
||||
one. The client should know what's going on, so we
|
||||
don't send an alert. */
|
||||
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
|
||||
return( MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE );
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
|
||||
MBEDTLS_SSL_PROTO_TLS1_2 */
|
||||
#endif /* MBEDTLS_SSL_SRV_C */
|
||||
|
||||
if( ssl->in_msgtype != MBEDTLS_SSL_MSG_HANDSHAKE )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad certificate message" ) );
|
||||
|
@ -6253,14 +6265,6 @@ static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl )
|
|||
/* Make &ssl->in_msg[i] point to the beginning of the CRT chain. */
|
||||
i += 3;
|
||||
|
||||
/* In case we tried to reuse a session but it failed */
|
||||
if( ssl->session_negotiate->peer_cert != NULL )
|
||||
{
|
||||
mbedtls_x509_crt_free( ssl->session_negotiate->peer_cert );
|
||||
mbedtls_free( ssl->session_negotiate->peer_cert );
|
||||
ssl->session_negotiate->peer_cert = NULL;
|
||||
}
|
||||
|
||||
/* Iterate through and parse the CRTs in the provided chain. */
|
||||
while( i < ssl->in_hslen )
|
||||
{
|
||||
|
@ -6298,16 +6302,15 @@ static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl )
|
|||
}
|
||||
|
||||
/* Check if we're handling the first CRT in the chain. */
|
||||
if( ssl->session_negotiate->peer_cert == NULL )
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
|
||||
if( crt_cnt++ == 0 &&
|
||||
ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
|
||||
ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
|
||||
{
|
||||
/* During client-side renegotiation, check that the server's
|
||||
* end-CRTs hasn't changed compared to the initial handshake,
|
||||
* mitigating the triple handshake attack. On success, reuse
|
||||
* the original end-CRT instead of parsing it again. */
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION) && defined(MBEDTLS_SSL_CLI_C)
|
||||
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT &&
|
||||
ssl->renego_status == MBEDTLS_SSL_RENEGOTIATION_IN_PROGRESS )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Check that peer CRT hasn't changed during renegotiation" ) );
|
||||
if( ssl_check_peer_crt_unchanged( ssl,
|
||||
&ssl->in_msg[i],
|
||||
|
@ -6320,44 +6323,19 @@ static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl )
|
|||
return( MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE );
|
||||
}
|
||||
|
||||
/* Move CRT chain structure to new session instance. */
|
||||
ssl->session_negotiate->peer_cert = ssl->session->peer_cert;
|
||||
ssl->session->peer_cert = NULL;
|
||||
|
||||
/* Delete all remaining CRTs from the original CRT chain. */
|
||||
mbedtls_x509_crt_free(
|
||||
ssl->session_negotiate->peer_cert->next );
|
||||
mbedtls_free( ssl->session_negotiate->peer_cert->next );
|
||||
ssl->session_negotiate->peer_cert->next = NULL;
|
||||
|
||||
i += n;
|
||||
continue;
|
||||
/* Now we can safely free the original chain. */
|
||||
ssl_clear_peer_cert( ssl->session );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_RENEGOTIATION && MBEDTLS_SSL_CLI_C */
|
||||
|
||||
/* Outside of client-side renegotiation, create a fresh X.509 CRT
|
||||
* instance to parse the end-CRT into. */
|
||||
|
||||
ssl->session_negotiate->peer_cert =
|
||||
mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
|
||||
if( ssl->session_negotiate->peer_cert == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
|
||||
sizeof( mbedtls_x509_crt ) ) );
|
||||
mbedtls_ssl_send_alert_message( ssl,
|
||||
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
|
||||
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
|
||||
}
|
||||
|
||||
mbedtls_x509_crt_init( ssl->session_negotiate->peer_cert );
|
||||
|
||||
/* Intentional fall through */
|
||||
}
|
||||
|
||||
/* Parse the next certificate in the chain. */
|
||||
ret = mbedtls_x509_crt_parse_der( ssl->session_negotiate->peer_cert,
|
||||
ssl->in_msg + i, n );
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
ret = mbedtls_x509_crt_parse_der( chain, ssl->in_msg + i, n );
|
||||
#else
|
||||
/* If we don't need to store the CRT chain permanently, parse
|
||||
* it in-place from the input buffer instead of making a copy. */
|
||||
ret = mbedtls_x509_crt_parse_der_nocopy( chain, ssl->in_msg + i, n );
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
switch( ret )
|
||||
{
|
||||
case 0: /*ok*/
|
||||
|
@ -6385,100 +6363,104 @@ static int ssl_parse_certificate_chain( mbedtls_ssl_context *ssl )
|
|||
i += n;
|
||||
}
|
||||
|
||||
MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", ssl->session_negotiate->peer_cert );
|
||||
MBEDTLS_SSL_DEBUG_CRT( 3, "peer certificate", chain );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
|
||||
#if defined(MBEDTLS_SSL_SRV_C)
|
||||
static int ssl_srv_check_client_no_crt_notification( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
int ret;
|
||||
const mbedtls_ssl_ciphersuite_t * const ciphersuite_info =
|
||||
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_CLIENT )
|
||||
return( -1 );
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_SSL3)
|
||||
/*
|
||||
* Check if the client sent an empty certificate
|
||||
*/
|
||||
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_0 )
|
||||
{
|
||||
if( ssl->in_msglen == 2 &&
|
||||
ssl->in_msgtype == MBEDTLS_SSL_MSG_ALERT &&
|
||||
ssl->in_msg[0] == MBEDTLS_SSL_ALERT_LEVEL_WARNING &&
|
||||
ssl->in_msg[1] == MBEDTLS_SSL_ALERT_MSG_NO_CERT )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "SSLv3 client has no certificate" ) );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_PROTO_SSL3 */
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
||||
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
||||
if( ssl->in_hslen == 3 + mbedtls_ssl_hs_hdr_len( ssl ) &&
|
||||
ssl->in_msgtype == MBEDTLS_SSL_MSG_HANDSHAKE &&
|
||||
ssl->in_msg[0] == MBEDTLS_SSL_HS_CERTIFICATE &&
|
||||
memcmp( ssl->in_msg + mbedtls_ssl_hs_hdr_len( ssl ), "\0\0\0", 3 ) == 0 )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "TLSv1 client has no certificate" ) );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
|
||||
MBEDTLS_SSL_PROTO_TLS1_2 */
|
||||
|
||||
return( -1 );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_SRV_C */
|
||||
|
||||
/* Check if a certificate message is expected.
|
||||
* Return either
|
||||
* - SSL_CERTIFICATE_EXPECTED, or
|
||||
* - SSL_CERTIFICATE_SKIP
|
||||
* indicating whether a Certificate message is expected or not.
|
||||
*/
|
||||
#define SSL_CERTIFICATE_EXPECTED 0
|
||||
#define SSL_CERTIFICATE_SKIP 1
|
||||
static int ssl_parse_certificate_coordinate( mbedtls_ssl_context *ssl,
|
||||
int authmode )
|
||||
{
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->handshake->ciphersuite_info;
|
||||
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
|
||||
const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
|
||||
? ssl->handshake->sni_authmode
|
||||
: ssl->conf->authmode;
|
||||
|
||||
if( !mbedtls_ssl_ciphersuite_uses_srv_cert( ciphersuite_info ) )
|
||||
return( SSL_CERTIFICATE_SKIP );
|
||||
|
||||
#if defined(MBEDTLS_SSL_SRV_C)
|
||||
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER )
|
||||
{
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
|
||||
return( SSL_CERTIFICATE_SKIP );
|
||||
|
||||
if( authmode == MBEDTLS_SSL_VERIFY_NONE )
|
||||
{
|
||||
ssl->session_negotiate->verify_result =
|
||||
MBEDTLS_X509_BADCERT_SKIP_VERIFY;
|
||||
return( SSL_CERTIFICATE_SKIP );
|
||||
}
|
||||
}
|
||||
#else
|
||||
const int authmode = ssl->conf->authmode;
|
||||
#endif
|
||||
void *rs_ctx = NULL;
|
||||
((void) authmode);
|
||||
#endif /* MBEDTLS_SSL_SRV_C */
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
|
||||
|
||||
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ||
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
|
||||
ssl->state++;
|
||||
return( 0 );
|
||||
return( SSL_CERTIFICATE_EXPECTED );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_SRV_C)
|
||||
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
|
||||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
|
||||
ssl->state++;
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER &&
|
||||
authmode == MBEDTLS_SSL_VERIFY_NONE )
|
||||
{
|
||||
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_SKIP_VERIFY;
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
|
||||
|
||||
ssl->state++;
|
||||
return( 0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ssl->handshake->ecrs_enabled &&
|
||||
ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )
|
||||
{
|
||||
goto crt_verify;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
|
||||
{
|
||||
/* mbedtls_ssl_read_record may have sent an alert already. We
|
||||
let it decide whether to alert. */
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
|
||||
return( ret );
|
||||
}
|
||||
|
||||
if( ( ret = ssl_parse_certificate_chain( ssl ) ) != 0 )
|
||||
{
|
||||
#if defined(MBEDTLS_SSL_SRV_C)
|
||||
if( ret == MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE &&
|
||||
authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
ssl->state++;
|
||||
return( ret );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ssl->handshake->ecrs_enabled)
|
||||
ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
|
||||
|
||||
crt_verify:
|
||||
if( ssl->handshake->ecrs_enabled)
|
||||
rs_ctx = &ssl->handshake->ecrs_ctx;
|
||||
#endif
|
||||
|
||||
if( authmode != MBEDTLS_SSL_VERIFY_NONE )
|
||||
static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl,
|
||||
int authmode,
|
||||
mbedtls_x509_crt *chain,
|
||||
void *rs_ctx )
|
||||
{
|
||||
int ret = 0;
|
||||
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
||||
ssl->handshake->ciphersuite_info;
|
||||
mbedtls_x509_crt *ca_chain;
|
||||
mbedtls_x509_crl *ca_crl;
|
||||
|
||||
if( authmode == MBEDTLS_SSL_VERIFY_NONE )
|
||||
return( 0 );
|
||||
|
||||
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
|
||||
if( ssl->handshake->sni_ca_chain != NULL )
|
||||
{
|
||||
|
@ -6496,7 +6478,7 @@ crt_verify:
|
|||
* Main check: verify certificate
|
||||
*/
|
||||
ret = mbedtls_x509_crt_verify_restartable(
|
||||
ssl->session_negotiate->peer_cert,
|
||||
chain,
|
||||
ca_chain, ca_crl,
|
||||
ssl->conf->cert_profile,
|
||||
ssl->hostname,
|
||||
|
@ -6519,7 +6501,7 @@ crt_verify:
|
|||
|
||||
#if defined(MBEDTLS_ECP_C)
|
||||
{
|
||||
const mbedtls_pk_context *pk = &ssl->session_negotiate->peer_cert->pk;
|
||||
const mbedtls_pk_context *pk = &chain->pk;
|
||||
|
||||
/* If certificate uses an EC key, make sure the curve is OK */
|
||||
if( mbedtls_pk_can_do( pk, MBEDTLS_PK_ECKEY ) &&
|
||||
|
@ -6534,7 +6516,7 @@ crt_verify:
|
|||
}
|
||||
#endif /* MBEDTLS_ECP_C */
|
||||
|
||||
if( mbedtls_ssl_check_cert_usage( ssl->session_negotiate->peer_cert,
|
||||
if( mbedtls_ssl_check_cert_usage( chain,
|
||||
ciphersuite_info,
|
||||
! ssl->conf->endpoint,
|
||||
&ssl->session_negotiate->verify_result ) != 0 )
|
||||
|
@ -6607,21 +6589,213 @@ crt_verify:
|
|||
MBEDTLS_SSL_DEBUG_MSG( 3, ( "Certificate verification flags clear" ) );
|
||||
}
|
||||
#endif /* MBEDTLS_DEBUG_C */
|
||||
}
|
||||
|
||||
ssl->state++;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* !MBEDTLS_KEY_EXCHANGE_RSA_ENABLED
|
||||
!MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED
|
||||
!MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED
|
||||
!MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
|
||||
|
||||
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
static int ssl_remember_peer_crt_digest( mbedtls_ssl_context *ssl,
|
||||
unsigned char *start, size_t len )
|
||||
{
|
||||
int ret;
|
||||
/* Remember digest of the peer's end-CRT. */
|
||||
ssl->session_negotiate->peer_cert_digest =
|
||||
mbedtls_calloc( 1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN );
|
||||
if( ssl->session_negotiate->peer_cert_digest == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
|
||||
sizeof( MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN ) ) );
|
||||
mbedtls_ssl_send_alert_message( ssl,
|
||||
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
|
||||
|
||||
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
|
||||
}
|
||||
|
||||
ret = mbedtls_md( mbedtls_md_info_from_type(
|
||||
MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE ),
|
||||
start, len,
|
||||
ssl->session_negotiate->peer_cert_digest );
|
||||
|
||||
ssl->session_negotiate->peer_cert_digest_type =
|
||||
MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE;
|
||||
ssl->session_negotiate->peer_cert_digest_len =
|
||||
MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN;
|
||||
|
||||
return( ret );
|
||||
}
|
||||
|
||||
static int ssl_remember_peer_pubkey( mbedtls_ssl_context *ssl,
|
||||
unsigned char *start, size_t len )
|
||||
{
|
||||
unsigned char *end = start + len;
|
||||
int ret;
|
||||
|
||||
/* Make a copy of the peer's raw public key. */
|
||||
mbedtls_pk_init( &ssl->handshake->peer_pubkey );
|
||||
ret = mbedtls_pk_parse_subpubkey( &start, end,
|
||||
&ssl->handshake->peer_pubkey );
|
||||
if( ret != 0 )
|
||||
{
|
||||
/* We should have parsed the public key before. */
|
||||
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
int mbedtls_ssl_parse_certificate( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
int ret = 0;
|
||||
int crt_expected;
|
||||
#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
|
||||
const int authmode = ssl->handshake->sni_authmode != MBEDTLS_SSL_VERIFY_UNSET
|
||||
? ssl->handshake->sni_authmode
|
||||
: ssl->conf->authmode;
|
||||
#else
|
||||
const int authmode = ssl->conf->authmode;
|
||||
#endif
|
||||
void *rs_ctx = NULL;
|
||||
mbedtls_x509_crt *chain = NULL;
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse certificate" ) );
|
||||
|
||||
crt_expected = ssl_parse_certificate_coordinate( ssl, authmode );
|
||||
if( crt_expected == SSL_CERTIFICATE_SKIP )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip parse certificate" ) );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ssl->handshake->ecrs_enabled &&
|
||||
ssl->handshake->ecrs_state == ssl_ecrs_crt_verify )
|
||||
{
|
||||
chain = ssl->handshake->ecrs_peer_cert;
|
||||
ssl->handshake->ecrs_peer_cert = NULL;
|
||||
goto crt_verify;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( ( ret = mbedtls_ssl_read_record( ssl, 1 ) ) != 0 )
|
||||
{
|
||||
/* mbedtls_ssl_read_record may have sent an alert already. We
|
||||
let it decide whether to alert. */
|
||||
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SSL_SRV_C)
|
||||
if( ssl_srv_check_client_no_crt_notification( ssl ) == 0 )
|
||||
{
|
||||
ssl->session_negotiate->verify_result = MBEDTLS_X509_BADCERT_MISSING;
|
||||
|
||||
if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL )
|
||||
ret = 0;
|
||||
else
|
||||
ret = MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE;
|
||||
|
||||
goto exit;
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_SRV_C */
|
||||
|
||||
/* Clear existing peer CRT structure in case we tried to
|
||||
* reuse a session but it failed, and allocate a new one. */
|
||||
ssl_clear_peer_cert( ssl->session_negotiate );
|
||||
|
||||
chain = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
|
||||
if( chain == NULL )
|
||||
{
|
||||
MBEDTLS_SSL_DEBUG_MSG( 1, ( "alloc(%d bytes) failed",
|
||||
sizeof( mbedtls_x509_crt ) ) );
|
||||
mbedtls_ssl_send_alert_message( ssl,
|
||||
MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
||||
MBEDTLS_SSL_ALERT_MSG_INTERNAL_ERROR );
|
||||
|
||||
ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
|
||||
goto exit;
|
||||
}
|
||||
mbedtls_x509_crt_init( chain );
|
||||
|
||||
ret = ssl_parse_certificate_chain( ssl, chain );
|
||||
if( ret != 0 )
|
||||
goto exit;
|
||||
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ssl->handshake->ecrs_enabled)
|
||||
ssl->handshake->ecrs_state = ssl_ecrs_crt_verify;
|
||||
|
||||
crt_verify:
|
||||
if( ssl->handshake->ecrs_enabled)
|
||||
rs_ctx = &ssl->handshake->ecrs_ctx;
|
||||
#endif
|
||||
|
||||
ret = ssl_parse_certificate_verify( ssl, authmode,
|
||||
chain, rs_ctx );
|
||||
if( ret != 0 )
|
||||
goto exit;
|
||||
|
||||
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
{
|
||||
unsigned char *crt_start, *pk_start;
|
||||
size_t crt_len, pk_len;
|
||||
|
||||
/* We parse the CRT chain without copying, so
|
||||
* these pointers point into the input buffer,
|
||||
* and are hence still valid after freeing the
|
||||
* CRT chain. */
|
||||
|
||||
crt_start = chain->raw.p;
|
||||
crt_len = chain->raw.len;
|
||||
|
||||
pk_start = chain->pk_raw.p;
|
||||
pk_len = chain->pk_raw.len;
|
||||
|
||||
/* Free the CRT structures before computing
|
||||
* digest and copying the peer's public key. */
|
||||
mbedtls_x509_crt_free( chain );
|
||||
mbedtls_free( chain );
|
||||
chain = NULL;
|
||||
|
||||
ret = ssl_remember_peer_crt_digest( ssl, crt_start, crt_len );
|
||||
if( ret != 0 )
|
||||
goto exit;
|
||||
|
||||
ret = ssl_remember_peer_pubkey( ssl, pk_start, pk_len );
|
||||
if( ret != 0 )
|
||||
goto exit;
|
||||
}
|
||||
#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
/* Pass ownership to session structure. */
|
||||
ssl->session_negotiate->peer_cert = chain;
|
||||
chain = NULL;
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= parse certificate" ) );
|
||||
|
||||
exit:
|
||||
|
||||
if( ret == 0 )
|
||||
ssl->state++;
|
||||
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS )
|
||||
{
|
||||
ssl->handshake->ecrs_peer_cert = chain;
|
||||
chain = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( chain != NULL )
|
||||
{
|
||||
mbedtls_x509_crt_free( chain );
|
||||
mbedtls_free( chain );
|
||||
}
|
||||
|
||||
return( ret );
|
||||
}
|
||||
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED */
|
||||
|
||||
int mbedtls_ssl_write_change_cipher_spec( mbedtls_ssl_context *ssl )
|
||||
{
|
||||
|
@ -7403,6 +7577,11 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake )
|
|||
#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION)
|
||||
handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET;
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
|
||||
!defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
mbedtls_pk_init( &handshake->peer_pubkey );
|
||||
#endif
|
||||
}
|
||||
|
||||
void mbedtls_ssl_transform_init( mbedtls_ssl_transform *transform )
|
||||
|
@ -7985,7 +8164,8 @@ int mbedtls_ssl_set_session( mbedtls_ssl_context *ssl, const mbedtls_ssl_session
|
|||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
if( ( ret = ssl_session_copy( ssl->session_negotiate, session ) ) != 0 )
|
||||
if( ( ret = mbedtls_ssl_session_copy( ssl->session_negotiate,
|
||||
session ) ) != 0 )
|
||||
return( ret );
|
||||
|
||||
ssl->handshake->resume = 1;
|
||||
|
@ -8839,12 +9019,17 @@ const mbedtls_x509_crt *mbedtls_ssl_get_peer_cert( const mbedtls_ssl_context *ss
|
|||
if( ssl == NULL || ssl->session == NULL )
|
||||
return( NULL );
|
||||
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
return( ssl->session->peer_cert );
|
||||
#else
|
||||
return( NULL );
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
}
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
#if defined(MBEDTLS_SSL_CLI_C)
|
||||
int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session *dst )
|
||||
int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl,
|
||||
mbedtls_ssl_session *dst )
|
||||
{
|
||||
if( ssl == NULL ||
|
||||
dst == NULL ||
|
||||
|
@ -8854,7 +9039,7 @@ int mbedtls_ssl_get_session( const mbedtls_ssl_context *ssl, mbedtls_ssl_session
|
|||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
return( ssl_session_copy( dst, ssl->session ) );
|
||||
return( mbedtls_ssl_session_copy( dst, ssl->session ) );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_CLI_C */
|
||||
|
||||
|
@ -8918,6 +9103,12 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co
|
|||
#define SSL_SERIALIZED_SESSION_CONFIG_TICKET 0
|
||||
#endif /* MBEDTLS_SSL_SESSION_TICKETS */
|
||||
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_CRT 1
|
||||
#else
|
||||
#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_CRT 0
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
#define SSL_SERIALIZED_SESSION_CONFIG_TIME_BIT 0
|
||||
#define SSL_SERIALIZED_SESSION_CONFIG_CRT_BIT 1
|
||||
#define SSL_SERIALIZED_SESSION_CONFIG_CLIENT_TICKET_BIT 2
|
||||
|
@ -8925,6 +9116,7 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co
|
|||
#define SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT 4
|
||||
#define SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT 5
|
||||
#define SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT 6
|
||||
#define SSL_SERIALIZED_SESSION_CONFIG_KEEP_CRT_BIT 7
|
||||
|
||||
#define SSL_SERIALIZED_SESSION_CONFIG_BITFLAG \
|
||||
( (uint16_t) ( \
|
||||
|
@ -8934,7 +9126,8 @@ const mbedtls_ssl_session *mbedtls_ssl_get_session_pointer( const mbedtls_ssl_co
|
|||
( SSL_SERIALIZED_SESSION_CONFIG_MFL << SSL_SERIALIZED_SESSION_CONFIG_MFL_BIT ) | \
|
||||
( SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC << SSL_SERIALIZED_SESSION_CONFIG_TRUNC_HMAC_BIT ) | \
|
||||
( SSL_SERIALIZED_SESSION_CONFIG_ETM << SSL_SERIALIZED_SESSION_CONFIG_ETM_BIT ) | \
|
||||
( SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT ) ) )
|
||||
( SSL_SERIALIZED_SESSION_CONFIG_TICKET << SSL_SERIALIZED_SESSION_CONFIG_TICKET_BIT ) | \
|
||||
( SSL_SERIALIZED_SESSION_CONFIG_KEEP_CRT << SSL_SERIALIZED_SESSION_CONFIG_KEEP_CRT_BIT ) ) )
|
||||
|
||||
static unsigned char ssl_serialized_session_header[] = {
|
||||
MBEDTLS_VERSION_MAJOR,
|
||||
|
@ -8967,7 +9160,11 @@ static unsigned char ssl_serialized_session_header[] = {
|
|||
* opaque session_id[32];
|
||||
* opaque master[48]; // fixed length in the standard
|
||||
* uint32 verify_result;
|
||||
* opaque peer_cert<0..2^24-1>; // length 0 means no peer cert
|
||||
* select (MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) {
|
||||
* case enabled: opaque peer_cert<0..2^24-1>; // length 0 means no cert
|
||||
* case disabled: uint8_t peer_cert_digest_type;
|
||||
* opaque peer_cert_digest<0..2^8-1>;
|
||||
* }
|
||||
* opaque ticket<0..2^24-1>; // length 0 means no ticket
|
||||
* uint32 ticket_lifetime;
|
||||
* uint8 mfl_code; // up to 255 according to standard
|
||||
|
@ -8989,7 +9186,9 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session,
|
|||
uint64_t start;
|
||||
#endif
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
size_t cert_len;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -9060,6 +9259,7 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session,
|
|||
* Peer's end-entity certificate
|
||||
*/
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
if( session->peer_cert == NULL )
|
||||
cert_len = 0;
|
||||
else
|
||||
|
@ -9079,6 +9279,31 @@ int mbedtls_ssl_session_save( const mbedtls_ssl_session *session,
|
|||
p += cert_len;
|
||||
}
|
||||
}
|
||||
|
||||
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
/* Digest of peer certificate */
|
||||
if( session->peer_cert_digest != NULL )
|
||||
{
|
||||
used += 1 /* type */ + 1 /* length */ + session->peer_cert_digest_len;
|
||||
if( used <= buf_len )
|
||||
{
|
||||
*p++ = (unsigned char) session->peer_cert_digest_type;
|
||||
*p++ = (unsigned char) session->peer_cert_digest_len;
|
||||
memcpy( p, session->peer_cert_digest,
|
||||
session->peer_cert_digest_len );
|
||||
p += session->peer_cert_digest_len;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
used += 2;
|
||||
if( used <= buf_len )
|
||||
{
|
||||
*p++ = (unsigned char) MBEDTLS_MD_NONE;
|
||||
*p++ = 0;
|
||||
}
|
||||
}
|
||||
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
/*
|
||||
|
@ -9155,8 +9380,10 @@ static int ssl_session_load( mbedtls_ssl_session *session,
|
|||
uint64_t start;
|
||||
#endif
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
size_t cert_len;
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check version identifier
|
||||
|
@ -9219,7 +9446,11 @@ static int ssl_session_load( mbedtls_ssl_session *session,
|
|||
/* Immediately clear invalid pointer values that have been read, in case
|
||||
* we exit early before we replaced them with valid ones. */
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
session->peer_cert = NULL;
|
||||
#else
|
||||
session->peer_cert_digest = NULL;
|
||||
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
#endif
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
|
||||
session->ticket = NULL;
|
||||
|
@ -9229,6 +9460,7 @@ static int ssl_session_load( mbedtls_ssl_session *session,
|
|||
* Peer certificate
|
||||
*/
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
if( 3 > (size_t)( end - p ) )
|
||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
|
||||
|
@ -9264,6 +9496,36 @@ static int ssl_session_load( mbedtls_ssl_session *session,
|
|||
|
||||
p += cert_len;
|
||||
}
|
||||
#else /* defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
/* Deserialize CRT digest from the end of the ticket. */
|
||||
if( 2 > (size_t)( end - p ) )
|
||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
|
||||
session->peer_cert_digest_type = (mbedtls_md_type_t) *p++;
|
||||
session->peer_cert_digest_len = (size_t) *p++;
|
||||
|
||||
if( session->peer_cert_digest_len != 0 )
|
||||
{
|
||||
const mbedtls_md_info_t *md_info =
|
||||
mbedtls_md_info_from_type( session->peer_cert_digest_type );
|
||||
if( md_info == NULL )
|
||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
if( session->peer_cert_digest_len != mbedtls_md_get_size( md_info ) )
|
||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
|
||||
if( session->peer_cert_digest_len > (size_t)( end - p ) )
|
||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
|
||||
session->peer_cert_digest =
|
||||
mbedtls_calloc( 1, session->peer_cert_digest_len );
|
||||
if( session->peer_cert_digest == NULL )
|
||||
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
|
||||
|
||||
memcpy( session->peer_cert_digest, p,
|
||||
session->peer_cert_digest_len );
|
||||
p += session->peer_cert_digest_len;
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
/*
|
||||
|
@ -10203,8 +10465,18 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
|
|||
|
||||
#if defined(MBEDTLS_SSL__ECP_RESTARTABLE)
|
||||
mbedtls_x509_crt_restart_free( &handshake->ecrs_ctx );
|
||||
if( handshake->ecrs_peer_cert != NULL )
|
||||
{
|
||||
mbedtls_x509_crt_free( handshake->ecrs_peer_cert );
|
||||
mbedtls_free( handshake->ecrs_peer_cert );
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C) && \
|
||||
!defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
mbedtls_pk_free( &handshake->peer_pubkey );
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C && !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
#if defined(MBEDTLS_SSL_PROTO_DTLS)
|
||||
mbedtls_free( handshake->verify_cookie );
|
||||
ssl_flight_free( handshake->flight );
|
||||
|
@ -10221,11 +10493,7 @@ void mbedtls_ssl_session_free( mbedtls_ssl_session *session )
|
|||
return;
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
if( session->peer_cert != NULL )
|
||||
{
|
||||
mbedtls_x509_crt_free( session->peer_cert );
|
||||
mbedtls_free( session->peer_cert );
|
||||
}
|
||||
ssl_clear_peer_cert( session );
|
||||
#endif
|
||||
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
|
||||
|
|
|
@ -456,6 +456,9 @@ static const char *features[] = {
|
|||
#if defined(MBEDTLS_SSL_FALLBACK_SCSV)
|
||||
"MBEDTLS_SSL_FALLBACK_SCSV",
|
||||
#endif /* MBEDTLS_SSL_FALLBACK_SCSV */
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
"MBEDTLS_SSL_KEEP_PEER_CERTIFICATE",
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
|
||||
"MBEDTLS_SSL_HW_RECORD_ACCEL",
|
||||
#endif /* MBEDTLS_SSL_HW_RECORD_ACCEL */
|
||||
|
|
|
@ -990,11 +990,13 @@ static int x509_crt_parse_der_core( mbedtls_x509_crt *crt,
|
|||
/*
|
||||
* SubjectPublicKeyInfo
|
||||
*/
|
||||
crt->pk_raw.p = p;
|
||||
if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 )
|
||||
{
|
||||
mbedtls_x509_crt_free( crt );
|
||||
return( ret );
|
||||
}
|
||||
crt->pk_raw.len = p - crt->pk_raw.p;
|
||||
|
||||
/*
|
||||
* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
|
||||
|
|
|
@ -1258,6 +1258,14 @@ int query_config( const char *config )
|
|||
}
|
||||
#endif /* MBEDTLS_SSL_FALLBACK_SCSV */
|
||||
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
if( strcmp( "MBEDTLS_SSL_KEEP_PEER_CERTIFICATE", config ) == 0 )
|
||||
{
|
||||
MACRO_EXPANSION_TO_STR( MBEDTLS_SSL_KEEP_PEER_CERTIFICATE );
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL)
|
||||
if( strcmp( "MBEDTLS_SSL_HW_RECORD_ACCEL", config ) == 0 )
|
||||
{
|
||||
|
|
|
@ -494,6 +494,8 @@ static int my_send( void *ctx, const unsigned char *buf, size_t len )
|
|||
}
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
static unsigned char peer_crt_info[1024];
|
||||
|
||||
/*
|
||||
* Enabled if debug_level > 1 in code below
|
||||
*/
|
||||
|
@ -506,8 +508,14 @@ static int my_verify( void *data, mbedtls_x509_crt *crt,
|
|||
((void) data);
|
||||
|
||||
#if !defined(MBEDTLS_X509_REMOVE_INFO)
|
||||
mbedtls_printf( "\nVerify requested for (Depth %d):\n", depth );
|
||||
mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
|
||||
if( depth == 0 )
|
||||
memcpy( peer_crt_info, buf, sizeof( buf ) );
|
||||
|
||||
if( opt.debug_level == 0 )
|
||||
return( 0 );
|
||||
|
||||
mbedtls_printf( "\nVerify requested for (Depth %d):\n", depth );
|
||||
mbedtls_printf( "%s", buf );
|
||||
#else
|
||||
((void) crt);
|
||||
|
@ -1641,8 +1649,8 @@ int main( int argc, char *argv[] )
|
|||
mbedtls_ssl_conf_sig_hashes( &conf, ssl_sig_hashes_for_test );
|
||||
}
|
||||
|
||||
if( opt.debug_level > 0 )
|
||||
mbedtls_ssl_conf_verify( &conf, my_verify, NULL );
|
||||
memset( peer_crt_info, 0, sizeof( peer_crt_info ) );
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID)
|
||||
|
@ -2021,13 +2029,8 @@ int main( int argc, char *argv[] )
|
|||
mbedtls_printf( " ok\n" );
|
||||
|
||||
#if !defined(MBEDTLS_X509_REMOVE_INFO)
|
||||
if( mbedtls_ssl_get_peer_cert( &ssl ) != NULL )
|
||||
{
|
||||
mbedtls_printf( " . Peer certificate information ...\n" );
|
||||
mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ",
|
||||
mbedtls_ssl_get_peer_cert( &ssl ) );
|
||||
mbedtls_printf( "%s\n", buf );
|
||||
}
|
||||
mbedtls_printf( "%s\n", peer_crt_info );
|
||||
#endif /* !MBEDTLS_X509_REMOVE_INFO */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
|
@ -2357,6 +2360,10 @@ send_request:
|
|||
mbedtls_printf( " . Restarting connection from same port..." );
|
||||
fflush( stdout );
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
memset( peer_crt_info, 0, sizeof( peer_crt_info ) );
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n",
|
||||
|
@ -2511,6 +2518,10 @@ reconnect:
|
|||
|
||||
mbedtls_printf( " . Reconnecting with saved session..." );
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
memset( peer_crt_info, 0, sizeof( peer_crt_info ) );
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n",
|
||||
|
|
|
@ -467,9 +467,12 @@ int main( int argc, char *argv[] )
|
|||
/*
|
||||
* 5. Print the certificate
|
||||
*/
|
||||
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
mbedtls_printf( " . Peer certificate information ... skipped\n" );
|
||||
#else
|
||||
mbedtls_printf( " . Peer certificate information ...\n" );
|
||||
ret = mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ",
|
||||
ssl.session->peer_cert );
|
||||
mbedtls_ssl_get_peer_cert( &ssl ) );
|
||||
if( ret == -1 )
|
||||
{
|
||||
mbedtls_printf( " failed\n ! mbedtls_x509_crt_info returned %d\n\n", ret );
|
||||
|
@ -477,6 +480,7 @@ int main( int argc, char *argv[] )
|
|||
}
|
||||
|
||||
mbedtls_printf( "%s\n", buf );
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
mbedtls_ssl_close_notify( &ssl );
|
||||
|
||||
|
|
|
@ -885,6 +885,22 @@ component_test_no_max_fragment_length () {
|
|||
if_build_succeeded tests/ssl-opt.sh -f "Max fragment length"
|
||||
}
|
||||
|
||||
component_test_asan_remove_peer_certificate () {
|
||||
msg "build: default config with MBEDTLS_SSL_KEEP_PEER_CERTIFICATE disabled (ASan build)"
|
||||
scripts/config.pl unset MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
|
||||
CC=gcc cmake -D CMAKE_BUILD_TYPE:String=Asan .
|
||||
make
|
||||
|
||||
msg "test: !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE"
|
||||
make test
|
||||
|
||||
msg "test: ssl-opt.sh, !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE"
|
||||
if_build_succeeded tests/ssl-opt.sh
|
||||
|
||||
msg "test: compat.sh, !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE"
|
||||
if_build_succeeded tests/compat.sh
|
||||
}
|
||||
|
||||
component_test_no_max_fragment_length_small_ssl_out_content_len () {
|
||||
msg "build: no MFL extension, small SSL_OUT_CONTENT_LEN (ASan build)"
|
||||
scripts/config.pl unset MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/* BEGIN_HEADER */
|
||||
#include <mbedtls/ssl.h>
|
||||
#include <mbedtls/ssl_internal.h>
|
||||
#include <mbedtls/md.h>
|
||||
|
||||
/*
|
||||
* Helper function setting up inverse record transformations
|
||||
|
@ -287,15 +288,40 @@ static int ssl_populate_session( mbedtls_ssl_session *session,
|
|||
#if defined(MBEDTLS_X509_CRT_PARSE_C) && defined(MBEDTLS_FS_IO)
|
||||
if( strlen( crt_file ) != 0 )
|
||||
{
|
||||
mbedtls_x509_crt tmp_crt;
|
||||
int ret;
|
||||
|
||||
mbedtls_x509_crt_init( &tmp_crt );
|
||||
ret = mbedtls_x509_crt_parse_file( &tmp_crt, crt_file );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
|
||||
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
/* Calculate digest of temporary CRT. */
|
||||
session->peer_cert_digest =
|
||||
mbedtls_calloc( 1, MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN );
|
||||
if( session->peer_cert_digest == NULL )
|
||||
return( -1 );
|
||||
ret = mbedtls_md( mbedtls_md_info_from_type(
|
||||
MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE ),
|
||||
tmp_crt.raw.p, tmp_crt.raw.len,
|
||||
session->peer_cert_digest );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
session->peer_cert_digest_type =
|
||||
MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_TYPE;
|
||||
session->peer_cert_digest_len =
|
||||
MBEDTLS_SSL_PEER_CERT_DIGEST_DFL_LEN;
|
||||
#else /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
/* Move temporary CRT. */
|
||||
session->peer_cert = mbedtls_calloc( 1, sizeof( *session->peer_cert ) );
|
||||
if( session->peer_cert == NULL )
|
||||
return( -1 );
|
||||
*session->peer_cert = tmp_crt;
|
||||
memset( &tmp_crt, 0, sizeof( tmp_crt ) );
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
|
||||
ret = mbedtls_x509_crt_parse_file( session->peer_cert, crt_file );
|
||||
if( ret != 0 )
|
||||
return( ret );
|
||||
mbedtls_x509_crt_free( &tmp_crt );
|
||||
}
|
||||
#else
|
||||
(void) crt_file;
|
||||
|
@ -681,6 +707,7 @@ void ssl_serialize_session_save_load( int ticket_len, char *crt_file )
|
|||
restored.master, sizeof( original.master ) ) == 0 );
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
TEST_ASSERT( ( original.peer_cert == NULL ) ==
|
||||
( restored.peer_cert == NULL ) );
|
||||
if( original.peer_cert != NULL )
|
||||
|
@ -691,7 +718,21 @@ void ssl_serialize_session_save_load( int ticket_len, char *crt_file )
|
|||
restored.peer_cert->raw.p,
|
||||
original.peer_cert->raw.len ) == 0 );
|
||||
}
|
||||
#endif
|
||||
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
TEST_ASSERT( original.peer_cert_digest_type ==
|
||||
restored.peer_cert_digest_type );
|
||||
TEST_ASSERT( original.peer_cert_digest_len ==
|
||||
restored.peer_cert_digest_len );
|
||||
TEST_ASSERT( ( original.peer_cert_digest == NULL ) ==
|
||||
( restored.peer_cert_digest == NULL ) );
|
||||
if( original.peer_cert_digest != NULL )
|
||||
{
|
||||
TEST_ASSERT( memcmp( original.peer_cert_digest,
|
||||
restored.peer_cert_digest,
|
||||
original.peer_cert_digest_len ) == 0 );
|
||||
}
|
||||
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
TEST_ASSERT( original.verify_result == restored.verify_result );
|
||||
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
|
||||
|
|
Loading…
Reference in a new issue