mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-25 16:55:43 +01:00
Merge remote-tracking branch 'public/pr/2421' into development
* public/pr/2421: (68 commits) Fix unused variable warning in ssl_parse_certificate_coordinate() Add missing compile time guard in ssl_client2 Update programs/ssl/query_config.c ssl_client2: Reset peer CRT info string on reconnect Add further debug statements on assertion failures Fix typo in documentation of ssl_parse_certificate_chain() Add debug output in case of assertion failure Fix typo in SSL ticket documentation Add config sanity check for !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE ssl_client2: Zeroize peer CRT info buffer when reconnecting Reintroduce numerous ssl-opt.sh tests if !MBEDTLS_SSL_KEEP_PEER_CERT ssl_client2: Extract peer CRT info from verification callback Improve documentation of mbedtls_ssl_get_peer_cert() Improve documentation of MBEDTLS_SSL_KEEP_PEER_CERTIFICATE Fix indentation of Doxygen comment in ssl_internal.h Set peer CRT length only after successful allocation Remove question in comment about verify flags on cli vs. server Remove misleading and redundant guard around restartable ECC field Add test for !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE to all.sh Free peer CRT chain immediately after verifying it ...
This commit is contained in:
commit
535ee4a35b
@ -16,6 +16,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
|
||||
* Fix a compilation issue with mbedtls_ecp_restart_ctx not being defined
|
||||
|
@ -280,6 +280,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 requires MBEDTLS_SHA512_C, MBEDTLS_SHA256_C or MBEDTLS_SHA1_C"
|
||||
#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"
|
||||
|
@ -1374,6 +1374,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
|
||||
*
|
||||
|
@ -787,6 +787,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.
|
||||
*/
|
||||
@ -802,7 +821,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 */
|
||||
|
||||
@ -2972,18 +2999,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 )
|
||||
{
|
||||
|
@ -331,8 +331,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 */
|
||||
@ -766,6 +771,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 );
|
||||
}
|
||||
|
@ -2265,6 +2265,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 )
|
||||
{
|
||||
@ -2290,23 +2291,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,
|
||||
@ -2326,6 +2332,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 ||
|
||||
@ -2401,21 +2411,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 )
|
||||
@ -2430,6 +2446,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) ||
|
||||
@ -2640,6 +2663,8 @@ start_processing:
|
||||
size_t params_len = p - params;
|
||||
void *rs_ctx = NULL;
|
||||
|
||||
mbedtls_pk_context * peer_pk;
|
||||
|
||||
/*
|
||||
* Handle the digitally-signed structure
|
||||
*/
|
||||
@ -2742,18 +2767,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,
|
||||
@ -2766,8 +2795,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)
|
||||
@ -2782,6 +2810,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 */
|
||||
|
||||
@ -3456,12 +3491,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 =
|
||||
@ -3476,11 +3506,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++;
|
||||
@ -3490,7 +3516,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;
|
||||
@ -3519,11 +3545,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++;
|
||||
@ -3666,12 +3688,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 )
|
||||
|
@ -2680,12 +2680,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 =
|
||||
@ -2693,11 +2688,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++;
|
||||
@ -2707,7 +2698,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;
|
||||
@ -2731,11 +2722,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" ) );
|
||||
@ -2874,12 +2861,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)
|
||||
@ -4048,12 +4030,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 =
|
||||
@ -4061,11 +4038,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++;
|
||||
@ -4075,7 +4048,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;
|
||||
@ -4089,21 +4062,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->transform_negotiate->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 )
|
||||
@ -4124,6 +4109,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
|
||||
@ -4138,8 +4134,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;
|
||||
@ -4194,7 +4189,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 );
|
||||
@ -4227,7 +4222,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl )
|
||||
/* Calculate hash and verify signature */
|
||||
ssl->handshake->calc_verify( ssl, hash );
|
||||
|
||||
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 )
|
||||
{
|
||||
@ -4241,12 +4236,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 )
|
||||
|
@ -187,9 +187,16 @@ int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx,
|
||||
|
||||
/*
|
||||
* Serialize a session in the following format:
|
||||
*
|
||||
* - If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is enabled:
|
||||
* 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session)
|
||||
* n . n+2 peer_cert length = m (0 if no certificate)
|
||||
* n+3 . n+2+m peer cert ASN.1
|
||||
*
|
||||
* - If MBEDTLS_SSL_KEEP_PEER_CERTIFICATE is disabled:
|
||||
* 0 . n-1 session structure, n = sizeof(mbedtls_ssl_session)
|
||||
* n . n length of peer certificate digest = k (0 if no digest)
|
||||
* n+1 . n+k peer certificate digest (digest type encoded in session)
|
||||
*/
|
||||
static int ssl_save_session( const mbedtls_ssl_session *session,
|
||||
unsigned char *buf, size_t buf_len,
|
||||
@ -198,17 +205,25 @@ static int ssl_save_session( const mbedtls_ssl_session *session,
|
||||
unsigned char *p = buf;
|
||||
size_t left = buf_len;
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
size_t cert_len;
|
||||
#else
|
||||
size_t cert_digest_len;
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
if( left < sizeof( mbedtls_ssl_session ) )
|
||||
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
|
||||
|
||||
/* This also copies the values of pointer fields in the
|
||||
* session to be serialized, but they'll be ignored when
|
||||
* loading the session through ssl_load_session(). */
|
||||
memcpy( p, session, sizeof( mbedtls_ssl_session ) );
|
||||
p += sizeof( mbedtls_ssl_session );
|
||||
left -= sizeof( mbedtls_ssl_session );
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
if( session->peer_cert == NULL )
|
||||
cert_len = 0;
|
||||
else
|
||||
@ -220,11 +235,31 @@ static int ssl_save_session( const mbedtls_ssl_session *session,
|
||||
*p++ = (unsigned char)( ( cert_len >> 16 ) & 0xFF );
|
||||
*p++ = (unsigned char)( ( cert_len >> 8 ) & 0xFF );
|
||||
*p++ = (unsigned char)( ( cert_len ) & 0xFF );
|
||||
left -= 3;
|
||||
|
||||
if( session->peer_cert != NULL )
|
||||
memcpy( p, session->peer_cert->raw.p, cert_len );
|
||||
|
||||
p += cert_len;
|
||||
left -= cert_len;
|
||||
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
if( session->peer_cert_digest != NULL )
|
||||
cert_digest_len = 0;
|
||||
else
|
||||
cert_digest_len = session->peer_cert_digest_len;
|
||||
|
||||
if( left < 1 + cert_digest_len )
|
||||
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
|
||||
|
||||
*p++ = (unsigned char) cert_digest_len;
|
||||
left--;
|
||||
|
||||
if( session->peer_cert_digest != NULL )
|
||||
memcpy( p, session->peer_cert_digest, cert_digest_len );
|
||||
|
||||
p += cert_digest_len;
|
||||
left -= cert_digest_len;
|
||||
#endif /* !MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
*olen = p - buf;
|
||||
@ -241,7 +276,11 @@ static int ssl_load_session( mbedtls_ssl_session *session,
|
||||
const unsigned char *p = buf;
|
||||
const unsigned char * const end = buf + len;
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
size_t cert_len;
|
||||
#else
|
||||
size_t cert_digest_len;
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
if( sizeof( mbedtls_ssl_session ) > (size_t)( end - p ) )
|
||||
@ -250,18 +289,29 @@ static int ssl_load_session( mbedtls_ssl_session *session,
|
||||
memcpy( session, p, sizeof( mbedtls_ssl_session ) );
|
||||
p += sizeof( mbedtls_ssl_session );
|
||||
|
||||
/* Non-NULL pointer fields of `session` are meaningless
|
||||
* and potentially harmful. Zeroize them for safety. */
|
||||
#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 /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
#if defined(MBEDTLS_SSL_SESSION_TICKETS) && defined(MBEDTLS_SSL_CLI_C)
|
||||
session->ticket = NULL;
|
||||
#endif /* MBEDTLS_SSL_SESSION_TICKETS && MBEDTLS_SSL_CLI_C */
|
||||
|
||||
#if defined(MBEDTLS_X509_CRT_PARSE_C)
|
||||
#if defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
|
||||
/* Deserialize CRT from the end of the ticket. */
|
||||
if( 3 > (size_t)( end - p ) )
|
||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
|
||||
cert_len = ( p[0] << 16 ) | ( p[1] << 8 ) | p[2];
|
||||
p += 3;
|
||||
|
||||
if( cert_len == 0 )
|
||||
{
|
||||
session->peer_cert = NULL;
|
||||
}
|
||||
else
|
||||
if( cert_len != 0 )
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -286,6 +336,30 @@ static int ssl_load_session( mbedtls_ssl_session *session,
|
||||
|
||||
p += cert_len;
|
||||
}
|
||||
#else /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
/* Deserialize CRT digest from the end of the ticket. */
|
||||
if( 1 > (size_t)( end - p ) )
|
||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
|
||||
cert_digest_len = (size_t) p[0];
|
||||
p++;
|
||||
|
||||
if( cert_digest_len != 0 )
|
||||
{
|
||||
if( cert_digest_len > (size_t)( end - p ) ||
|
||||
cert_digest_len != session->peer_cert_digest_len )
|
||||
{
|
||||
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
|
||||
}
|
||||
|
||||
session->peer_cert_digest = mbedtls_calloc( 1, cert_digest_len );
|
||||
if( session->peer_cert_digest == NULL )
|
||||
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
|
||||
|
||||
memcpy( session->peer_cert_digest, p, cert_digest_len );
|
||||
p += cert_digest_len;
|
||||
}
|
||||
#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */
|
||||
#endif /* MBEDTLS_X509_CRT_PARSE_C */
|
||||
|
||||
if( p != end )
|
||||
|
@ -279,13 +279,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;
|
||||
@ -304,6 +306,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)
|
||||
@ -319,7 +336,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,
|
||||
@ -5554,16 +5570,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 )
|
||||
{
|
||||
@ -5571,10 +5604,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++;
|
||||
@ -5591,10 +5621,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++;
|
||||
@ -5605,7 +5632,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 )
|
||||
@ -5617,10 +5644,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++;
|
||||
@ -5725,6 +5749,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 )
|
||||
@ -5739,65 +5765,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" ) );
|
||||
@ -5834,14 +5846,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 )
|
||||
{
|
||||
@ -5879,16 +5883,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],
|
||||
@ -5901,44 +5904,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*/
|
||||
@ -5966,100 +5944,103 @@ 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 );
|
||||
}
|
||||
|
||||
return( -1 );
|
||||
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
|
||||
MBEDTLS_SSL_PROTO_TLS1_2 */
|
||||
}
|
||||
#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->transform_negotiate->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->transform_negotiate->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 )
|
||||
{
|
||||
@ -6077,7 +6058,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,
|
||||
@ -6100,7 +6081,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 ) &&
|
||||
@ -6115,7 +6096,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 )
|
||||
@ -6188,21 +6169,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 )
|
||||
{
|
||||
@ -7065,6 +7238,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
|
||||
}
|
||||
|
||||
static void ssl_transform_init( mbedtls_ssl_transform *transform )
|
||||
@ -7614,7 +7792,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;
|
||||
@ -8533,12 +8712,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 ||
|
||||
@ -8548,7 +8732,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 */
|
||||
|
||||
@ -9402,8 +9586,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 );
|
||||
@ -9425,11 +9619,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)
|
||||
|
@ -459,6 +459,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 */
|
||||
|
@ -996,11 +996,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,
|
||||
|
@ -1266,6 +1266,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 )
|
||||
{
|
||||
|
@ -478,6 +478,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
|
||||
*/
|
||||
@ -487,8 +489,14 @@ static int my_verify( void *data, mbedtls_x509_crt *crt,
|
||||
char buf[1024];
|
||||
((void) data);
|
||||
|
||||
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 );
|
||||
|
||||
if ( ( *flags ) == 0 )
|
||||
@ -1503,8 +1511,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( opt.auth_mode != DFL_AUTH_MODE )
|
||||
@ -1833,13 +1841,8 @@ int main( int argc, char *argv[] )
|
||||
else
|
||||
mbedtls_printf( " ok\n" );
|
||||
|
||||
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_CRT_PARSE_C */
|
||||
|
||||
#if defined(MBEDTLS_SSL_RENEGOTIATION)
|
||||
@ -2144,6 +2147,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",
|
||||
@ -2215,6 +2222,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 );
|
||||
|
||||
|
@ -968,6 +968,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
|
||||
|
Loading…
Reference in New Issue
Block a user