Merge remote-tracking branch 'public/pr/1270' into development

This commit is contained in:
Simon Butcher 2018-06-15 14:17:31 +01:00
commit 5f57f1e3cc
13 changed files with 1544 additions and 179 deletions

View file

@ -10,6 +10,9 @@ Features
* Add support for the CCM* block cipher mode as defined in IEEE Std. 802.15.4.
* Add support for the XTS block cipher mode with AES (AES-XTS).
Contributed by Aorimn in pull request #414.
* In TLS servers, support offloading private key operations to an external
cryptoprocessor. Private key operations can be asynchronous to allow
non-blocking operation of the TLS server stack.
Bugfix
* Fix the cert_write example to handle certificates signed with elliptic

View file

@ -1148,6 +1148,17 @@
*/
#define MBEDTLS_SSL_ALL_ALERT_MESSAGES
/**
* \def MBEDTLS_SSL_ASYNC_PRIVATE
*
* Enable asynchronous external private key operations in SSL. This allows
* you to configure an SSL connection to call an external cryptographic
* module to perform private key operations instead of performing the
* operation inside the library.
*
*/
#define MBEDTLS_SSL_ASYNC_PRIVATE
/**
* \def MBEDTLS_SSL_DEBUG_ALL
*

View file

@ -91,7 +91,7 @@
* MD 5 5
* HKDF 5 1 (Started from top)
* CIPHER 6 8
* SSL 6 17 (Started from top)
* SSL 6 22 (Started from top)
* SSL 7 31
*
* Module dependent error code (5 bits 0x.00.-0x.F8.)

View file

@ -120,6 +120,7 @@
#define MBEDTLS_ERR_SSL_NON_FATAL -0x6680 /**< The alert message received indicates a non-fatal error. */
#define MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH -0x6600 /**< Couldn't set the hash for verifying CertificateVerify */
#define MBEDTLS_ERR_SSL_CONTINUE_PROCESSING -0x6580 /**< Internal-only message signaling that further message-processing should be done */
#define MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS -0x6500 /**< The asynchronous operation is not completed yet. */
/*
* Various constants
@ -536,7 +537,6 @@ typedef void mbedtls_ssl_set_timer_t( void * ctx,
*/
typedef int mbedtls_ssl_get_timer_t( void * ctx );
/* Defined below */
typedef struct mbedtls_ssl_session mbedtls_ssl_session;
typedef struct mbedtls_ssl_context mbedtls_ssl_context;
@ -553,6 +553,218 @@ typedef struct mbedtls_ssl_key_cert mbedtls_ssl_key_cert;
typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item;
#endif
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
#if defined(MBEDTLS_X509_CRT_PARSE_C)
/**
* \brief Callback type: start external signature operation.
*
* This callback is called during an SSL handshake to start
* a signature decryption operation using an
* external processor. The parameter \p cert contains
* the public key; it is up to the callback function to
* determine how to access the associated private key.
*
* This function typically sends or enqueues a request, and
* does not wait for the operation to complete. This allows
* the handshake step to be non-blocking.
*
* The parameters \p ssl and \p cert are guaranteed to remain
* valid throughout the handshake. On the other hand, this
* function must save the contents of \p hash if the value
* is needed for later processing, because the \p hash buffer
* is no longer valid after this function returns.
*
* This function may call mbedtls_ssl_set_async_operation_data()
* to store an operation context for later retrieval
* by the resume or cancel callback.
*
* \note For RSA signatures, this function must produce output
* that is consistent with PKCS#1 v1.5 in the same way as
* mbedtls_rsa_pkcs1_sign(). Before the private key operation,
* apply the padding steps described in RFC 8017, section 9.2
* "EMSA-PKCS1-v1_5" as follows.
* - If \p md_alg is #MBEDTLS_MD_NONE, apply the PKCS#1 v1.5
* encoding, treating \p hash as the DigestInfo to be
* padded. In other words, apply EMSA-PKCS1-v1_5 starting
* from step 3, with `T = hash` and `tLen = hash_len`.
* - If `md_alg != MBEDTLS_MD_NONE`, apply the PKCS#1 v1.5
* encoding, treating \p hash as the hash to be encoded and
* padded. In other words, apply EMSA-PKCS1-v1_5 starting
* from step 2, with `digestAlgorithm` obtained by calling
* mbedtls_oid_get_oid_by_md() on \p md_alg.
*
* \note For ECDSA signatures, the output format is the DER encoding
* `Ecdsa-Sig-Value` defined in
* [RFC 4492 section 5.4](https://tools.ietf.org/html/rfc4492#section-5.4).
*
* \param ssl The SSL connection instance. It should not be
* modified other than via
* mbedtls_ssl_set_async_operation_data().
* \param cert Certificate containing the public key.
* In simple cases, this is one of the pointers passed to
* mbedtls_ssl_conf_own_cert() when configuring the SSL
* connection. However, if other callbacks are used, this
* property may not hold. For example, if an SNI callback
* is registered with mbedtls_ssl_conf_sni(), then
* this callback determines what certificate is used.
* \param md_alg Hash algorithm.
* \param hash Buffer containing the hash. This buffer is
* no longer valid when the function returns.
* \param hash_len Size of the \c hash buffer in bytes.
*
* \return 0 if the operation was started successfully and the SSL
* stack should call the resume callback immediately.
* \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation
* was started successfully and the SSL stack should return
* immediately without calling the resume callback yet.
* \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external
* processor does not support this key. The SSL stack will
* use the private key object instead.
* \return Any other error indicates a fatal failure and is
* propagated up the call chain. The callback should
* use \c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b>
* use \c MBEDTLS_ERR_SSL_xxx error codes except as
* directed in the documentation of this callback.
*/
typedef int mbedtls_ssl_async_sign_t( mbedtls_ssl_context *ssl,
mbedtls_x509_crt *cert,
mbedtls_md_type_t md_alg,
const unsigned char *hash,
size_t hash_len );
/**
* \brief Callback type: start external decryption operation.
*
* This callback is called during an SSL handshake to start
* an RSA decryption operation using an
* external processor. The parameter \p cert contains
* the public key; it is up to the callback function to
* determine how to access the associated private key.
*
* This function typically sends or enqueues a request, and
* does not wait for the operation to complete. This allows
* the handshake step to be non-blocking.
*
* The parameters \p ssl and \p cert are guaranteed to remain
* valid throughout the handshake. On the other hand, this
* function must save the contents of \p input if the value
* is needed for later processing, because the \p input buffer
* is no longer valid after this function returns.
*
* This function may call mbedtls_ssl_set_async_operation_data()
* to store an operation context for later retrieval
* by the resume or cancel callback.
*
* \warning RSA decryption as used in TLS is subject to a potential
* timing side channel attack first discovered by Bleichenbacher
* in 1998. This attack can be remotely exploitable
* in practice. To avoid this attack, you must ensure that
* if the callback performs an RSA decryption, the time it
* takes to execute and return the result does not depend
* on whether the RSA decryption succeeded or reported
* invalid padding.
*
* \param ssl The SSL connection instance. It should not be
* modified other than via
* mbedtls_ssl_set_async_operation_data().
* \param cert Certificate containing the public key.
* In simple cases, this is one of the pointers passed to
* mbedtls_ssl_conf_own_cert() when configuring the SSL
* connection. However, if other callbacks are used, this
* property may not hold. For example, if an SNI callback
* is registered with mbedtls_ssl_conf_sni(), then
* this callback determines what certificate is used.
* \param input Buffer containing the input ciphertext. This buffer
* is no longer valid when the function returns.
* \param input_len Size of the \p input buffer in bytes.
*
* \return 0 if the operation was started successfully and the SSL
* stack should call the resume callback immediately.
* \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation
* was started successfully and the SSL stack should return
* immediately without calling the resume callback yet.
* \return #MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH if the external
* processor does not support this key. The SSL stack will
* use the private key object instead.
* \return Any other error indicates a fatal failure and is
* propagated up the call chain. The callback should
* use \c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b>
* use \c MBEDTLS_ERR_SSL_xxx error codes except as
* directed in the documentation of this callback.
*/
typedef int mbedtls_ssl_async_decrypt_t( mbedtls_ssl_context *ssl,
mbedtls_x509_crt *cert,
const unsigned char *input,
size_t input_len );
#endif /* MBEDTLS_X509_CRT_PARSE_C */
/**
* \brief Callback type: resume external operation.
*
* This callback is called during an SSL handshake to resume
* an external operation started by the
* ::mbedtls_ssl_async_sign_t or
* ::mbedtls_ssl_async_decrypt_t callback.
*
* This function typically checks the status of a pending
* request or causes the request queue to make progress, and
* does not wait for the operation to complete. This allows
* the handshake step to be non-blocking.
*
* This function may call mbedtls_ssl_get_async_operation_data()
* to retrieve an operation context set by the start callback.
* It may call mbedtls_ssl_set_async_operation_data() to modify
* this context.
*
* Note that when this function returns a status other than
* #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, it must free any
* resources associated with the operation.
*
* \param ssl The SSL connection instance. It should not be
* modified other than via
* mbedtls_ssl_set_async_operation_data().
* \param output Buffer containing the output (signature or decrypted
* data) on success.
* \param output_len On success, number of bytes written to \p output.
* \param output_size Size of the \p output buffer in bytes.
*
* \return 0 if output of the operation is available in the
* \p output buffer.
* \return #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS if the operation
* is still in progress. Subsequent requests for progress
* on the SSL connection will call the resume callback
* again.
* \return Any other error means that the operation is aborted.
* The SSL handshake is aborted. The callback should
* use \c MBEDTLS_ERR_PK_xxx error codes, and <b>must not</b>
* use \c MBEDTLS_ERR_SSL_xxx error codes except as
* directed in the documentation of this callback.
*/
typedef int mbedtls_ssl_async_resume_t( mbedtls_ssl_context *ssl,
unsigned char *output,
size_t *output_len,
size_t output_size );
/**
* \brief Callback type: cancel external operation.
*
* This callback is called if an SSL connection is closed
* while an asynchronous operation is in progress. Note that
* this callback is not called if the
* ::mbedtls_ssl_async_resume_t callback has run and has
* returned a value other than
* #MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS, since in that case
* the asynchronous operation has already completed.
*
* This function may call mbedtls_ssl_get_async_operation_data()
* to retrieve an operation context set by the start callback.
*
* \param ssl The SSL connection instance. It should not be
* modified.
*/
typedef void mbedtls_ssl_async_cancel_t( mbedtls_ssl_context *ssl );
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
/*
* This structure is used for storing current session data.
*/
@ -669,6 +881,16 @@ struct mbedtls_ssl_config
mbedtls_x509_crl *ca_crl; /*!< trusted CAs CRLs */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_ssl_async_sign_t *f_async_sign_start; /*!< start asynchronous signature operation */
mbedtls_ssl_async_decrypt_t *f_async_decrypt_start; /*!< start asynchronous decryption operation */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
mbedtls_ssl_async_resume_t *f_async_resume; /*!< resume asynchronous operation */
mbedtls_ssl_async_cancel_t *f_async_cancel; /*!< cancel asynchronous operation */
void *p_async_config_data; /*!< Configuration data set by mbedtls_ssl_conf_async_private_cb(). */
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED)
const int *sig_hashes; /*!< allowed signature hashes */
#endif
@ -1307,6 +1529,85 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf,
void *p_export_keys );
#endif /* MBEDTLS_SSL_EXPORT_KEYS */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
/**
* \brief Configure asynchronous private key operation callbacks.
*
* \param conf SSL configuration context
* \param f_async_sign Callback to start a signature operation. See
* the description of ::mbedtls_ssl_async_sign_t
* for more information. This may be \c NULL if the
* external processor does not support any signature
* operation; in this case the private key object
* associated with the certificate will be used.
* \param f_async_decrypt Callback to start a decryption operation. See
* the description of ::mbedtls_ssl_async_decrypt_t
* for more information. This may be \c NULL if the
* external processor does not support any decryption
* operation; in this case the private key object
* associated with the certificate will be used.
* \param f_async_resume Callback to resume an asynchronous operation. See
* the description of ::mbedtls_ssl_async_resume_t
* for more information. This may not be \c NULL unless
* \p f_async_sign and \p f_async_decrypt are both
* \c NULL.
* \param f_async_cancel Callback to cancel an asynchronous operation. See
* the description of ::mbedtls_ssl_async_cancel_t
* for more information. This may be \c NULL if
* no cleanup is needed.
* \param config_data A pointer to configuration data which can be
* retrieved with
* mbedtls_ssl_conf_get_async_config_data(). The
* library stores this value without dereferencing it.
*/
void mbedtls_ssl_conf_async_private_cb( mbedtls_ssl_config *conf,
mbedtls_ssl_async_sign_t *f_async_sign,
mbedtls_ssl_async_decrypt_t *f_async_decrypt,
mbedtls_ssl_async_resume_t *f_async_resume,
mbedtls_ssl_async_cancel_t *f_async_cancel,
void *config_data );
/**
* \brief Retrieve the configuration data set by
* mbedtls_ssl_conf_async_private_cb().
*
* \param conf SSL configuration context
* \return The configuration data set by
* mbedtls_ssl_conf_async_private_cb().
*/
void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf );
/**
* \brief Retrieve the asynchronous operation user context.
*
* \note This function may only be called while a handshake
* is in progress.
*
* \param ssl The SSL context to access.
*
* \return The asynchronous operation user context that was last
* set during the current handshake. If
* mbedtls_ssl_set_async_operation_data() has not yet been
* called during the current handshake, this function returns
* \c NULL.
*/
void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl );
/**
* \brief Retrieve the asynchronous operation user context.
*
* \note This function may only be called while a handshake
* is in progress.
*
* \param ssl The SSL context to access.
* \param ctx The new value of the asynchronous operation user context.
* Call mbedtls_ssl_get_async_operation_data() later during the
* same handshake to retrieve this value.
*/
void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl,
void *ctx );
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
/**
* \brief Callback type: generate a cookie
*

View file

@ -243,6 +243,7 @@ struct mbedtls_ssl_handshake_params
mbedtls_x509_crl *sni_ca_crl; /*!< trusted CAs CRLs from SNI */
#endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_PROTO_DTLS)
unsigned int out_msg_seq; /*!< Outgoing handshake sequence number */
unsigned int in_msg_seq; /*!< Incoming handshake sequence number */
@ -307,6 +308,19 @@ struct mbedtls_ssl_handshake_params
#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET)
int extended_ms; /*!< use Extended Master Secret? */
#endif
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
unsigned int async_in_progress : 1; /*!< an asynchronous operation is in progress */
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
/** Asynchronous operation context. This field is meant for use by the
* asynchronous operation callbacks (mbedtls_ssl_config::f_async_sign_start,
* mbedtls_ssl_config::f_async_decrypt_start,
* mbedtls_ssl_config::f_async_resume, mbedtls_ssl_config::f_async_cancel).
* The library does not use it internally. */
void *user_async_ctx;
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
};
/*
@ -410,9 +424,9 @@ void mbedtls_ssl_transform_free( mbedtls_ssl_transform *transform );
* \brief Free referenced items in an SSL handshake context and clear
* memory
*
* \param handshake SSL handshake context
* \param ssl SSL context
*/
void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake );
void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl );
int mbedtls_ssl_handshake_client_step( mbedtls_ssl_context *ssl );
int mbedtls_ssl_handshake_server_step( mbedtls_ssl_context *ssl );
@ -652,9 +666,9 @@ int mbedtls_ssl_get_key_exchange_md_ssl_tls( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
unsigned char *output,
unsigned char *data, size_t data_len,
mbedtls_md_type_t md_alg );
unsigned char *hash, size_t *hashlen,
unsigned char *data, size_t data_len,
mbedtls_md_type_t md_alg );
#endif /* MBEDTLS_SSL_PROTO_TLS1 || MBEDTLS_SSL_PROTO_TLS1_1 || \
MBEDTLS_SSL_PROTO_TLS1_2 */

View file

@ -501,6 +501,8 @@ void mbedtls_strerror( int ret, char *buf, size_t buflen )
mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" );
if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) )
mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" );
if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) )
mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" );
#endif /* MBEDTLS_SSL_TLS_C */
#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C)

View file

@ -2544,10 +2544,9 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( md_alg != MBEDTLS_MD_NONE )
{
/* Info from md_alg will be used instead */
hashlen = 0;
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, params,
params_len, md_alg );
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen,
params, params_len,
md_alg );
if( ret != 0 )
return( ret );
}
@ -2559,8 +2558,7 @@ static int ssl_parse_server_key_exchange( mbedtls_ssl_context *ssl )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
(unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) );
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
if( ssl->session_negotiate->peer_cert == NULL )
{

View file

@ -709,7 +709,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
cur->cert );
if( ! mbedtls_pk_can_do( cur->key, pk_alg ) )
if( ! mbedtls_pk_can_do( &cur->cert->pk, pk_alg ) )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) );
continue;
@ -733,7 +733,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_ECDSA_C)
if( pk_alg == MBEDTLS_PK_ECDSA &&
ssl_check_key_curve( cur->key, ssl->handshake->curves ) != 0 )
ssl_check_key_curve( &cur->cert->pk, ssl->handshake->curves ) != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) );
continue;
@ -2828,54 +2828,56 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED */
static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \
defined(MBEDTLS_SSL_ASYNC_PRIVATE)
static int ssl_resume_server_key_exchange( mbedtls_ssl_context *ssl,
size_t *signature_len )
{
/* Append the signature to ssl->out_msg, leaving 2 bytes for the
* signature length which will be added in ssl_write_server_key_exchange
* after the call to ssl_prepare_server_key_exchange.
* ssl_write_server_key_exchange also takes care of incrementing
* ssl->out_msglen. */
unsigned char *sig_start = ssl->out_msg + ssl->out_msglen + 2;
size_t sig_max_len = ( ssl->out_buf + MBEDTLS_SSL_MAX_CONTENT_LEN
- sig_start );
int ret = ssl->conf->f_async_resume( ssl,
sig_start, signature_len, sig_max_len );
if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
{
ssl->handshake->async_in_progress = 0;
mbedtls_ssl_set_async_operation_data( ssl, NULL );
}
MBEDTLS_SSL_DEBUG_RET( 2, "ssl_resume_server_key_exchange", ret );
return( ret );
}
#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) &&
defined(MBEDTLS_SSL_ASYNC_PRIVATE) */
/* Prepare the ServerKeyExchange message, up to and including
* calculating the signature if any, but excluding formatting the
* signature and sending the message. */
static int ssl_prepare_server_key_exchange( mbedtls_ssl_context *ssl,
size_t *signature_len )
{
int ret;
size_t n = 0;
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED)
unsigned char *p = ssl->out_msg + 4;
size_t len;
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
unsigned char *dig_signed = p;
size_t dig_signed_len = 0;
unsigned char *dig_signed = NULL;
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
(void) ciphersuite_info; /* unused in some configurations */
#if !defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
(void) signature_len;
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */
/*
*
* Part 1: Extract static ECDH parameters and abort
* if ServerKeyExchange not needed.
*
*/
/* For suites involving ECDH, extract DH parameters
* from certificate at this point. */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED)
if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
{
ssl_get_ecdh_params_from_cert( ssl );
}
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */
/* Key exchanges not involving ephemeral keys don't use
* ServerKeyExchange, so end here. */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
ssl->state++;
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE__NON_PFS__ENABLED */
/*
*
* Part 2: Provide key exchange parameters for chosen ciphersuite.
* Part 1: Provide key exchange parameters for chosen ciphersuite.
*
*/
@ -2885,18 +2887,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
{
const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
int ret;
size_t len;
ret = mbedtls_ecjpake_write_round_two( &ssl->handshake->ecjpake_ctx,
p, end - p, &len, ssl->conf->f_rng, ssl->conf->p_rng );
ret = mbedtls_ecjpake_write_round_two(
&ssl->handshake->ecjpake_ctx,
ssl->out_msg + ssl->out_msglen,
MBEDTLS_SSL_MAX_CONTENT_LEN - ssl->out_msglen, &len,
ssl->conf->f_rng, ssl->conf->p_rng );
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret );
return( ret );
}
p += len;
n += len;
ssl->out_msglen += len;
}
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
@ -2910,10 +2915,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK )
{
*(p++) = 0x00;
*(p++) = 0x00;
n += 2;
ssl->out_msg[ssl->out_msglen++] = 0x00;
ssl->out_msg[ssl->out_msglen++] = 0x00;
}
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED ||
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
@ -2924,6 +2927,9 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED)
if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) )
{
int ret;
size_t len;
if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) );
@ -2947,21 +2953,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
return( ret );
}
if( ( ret = mbedtls_dhm_make_params( &ssl->handshake->dhm_ctx,
(int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
p, &len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
if( ( ret = mbedtls_dhm_make_params(
&ssl->handshake->dhm_ctx,
(int) mbedtls_mpi_size( &ssl->handshake->dhm_ctx.P ),
ssl->out_msg + ssl->out_msglen, &len,
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret );
return( ret );
}
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
dig_signed = p;
dig_signed_len = len;
dig_signed = ssl->out_msg + ssl->out_msglen;
#endif
p += len;
n += len;
ssl->out_msglen += len;
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: X ", &ssl->handshake->dhm_ctx.X );
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P );
@ -2986,6 +2992,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
*/
const mbedtls_ecp_curve_info **curve = NULL;
const mbedtls_ecp_group_id *gid;
int ret;
size_t len;
/* Match our preference list against the offered curves */
for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ )
@ -3009,21 +3017,21 @@ curve_matching_done:
return( ret );
}
if( ( ret = mbedtls_ecdh_make_params( &ssl->handshake->ecdh_ctx, &len,
p, MBEDTLS_SSL_MAX_CONTENT_LEN - n,
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
if( ( ret = mbedtls_ecdh_make_params(
&ssl->handshake->ecdh_ctx, &len,
ssl->out_msg + ssl->out_msglen,
MBEDTLS_SSL_MAX_CONTENT_LEN - ssl->out_msglen,
ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret );
return( ret );
}
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
dig_signed = p;
dig_signed_len = len;
dig_signed = ssl->out_msg + ssl->out_msglen;
#endif
p += len;
n += len;
ssl->out_msglen += len;
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q );
}
@ -3031,19 +3039,20 @@ curve_matching_done:
/*
*
* Part 3: For key exchanges involving the server signing the
* Part 2: For key exchanges involving the server signing the
* exchange parameters, compute and add the signature here.
*
*/
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) )
{
size_t signature_len = 0;
unsigned int hashlen = 0;
unsigned char hash[64];
size_t dig_signed_len = ssl->out_msg + ssl->out_msglen - dig_signed;
size_t hashlen = 0;
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
int ret;
/*
* 3.1: Choose hash algorithm:
* 2.1: Choose hash algorithm:
* A: For TLS 1.2, obey signature-hash-algorithm extension
* to choose appropriate hash.
* B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1
@ -3090,7 +3099,7 @@ curve_matching_done:
MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) );
/*
* 3.2: Compute the hash to be signed
* 2.2: Compute the hash to be signed
*/
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1)
@ -3110,9 +3119,7 @@ curve_matching_done:
defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( md_alg != MBEDTLS_MD_NONE )
{
/* Info from md_alg will be used instead */
hashlen = 0;
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash,
ret = mbedtls_ssl_get_key_exchange_md_tls1_2( ssl, hash, &hashlen,
dig_signed,
dig_signed_len,
md_alg );
@ -3127,18 +3134,11 @@ curve_matching_done:
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
}
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen != 0 ? hashlen :
(unsigned int) ( mbedtls_md_get_size( mbedtls_md_info_from_type( md_alg ) ) ) );
MBEDTLS_SSL_DEBUG_BUF( 3, "parameters hash", hash, hashlen );
/*
* 3.3: Compute and add the signature
* 2.3: Compute and add the signature
*/
if( mbedtls_ssl_own_key( ssl ) == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) );
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
}
#if defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
{
@ -3158,33 +3158,150 @@ curve_matching_done:
*
*/
*(p++) = mbedtls_ssl_hash_from_md_alg( md_alg );
*(p++) = mbedtls_ssl_sig_from_pk_alg( sig_alg );
n += 2;
ssl->out_msg[ssl->out_msglen++] =
mbedtls_ssl_hash_from_md_alg( md_alg );
ssl->out_msg[ssl->out_msglen++] =
mbedtls_ssl_sig_from_pk_alg( sig_alg );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_2 */
if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash, hashlen,
p + 2 , &signature_len, ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( ssl->conf->f_async_sign_start != NULL )
{
ret = ssl->conf->f_async_sign_start( ssl,
mbedtls_ssl_own_cert( ssl ),
md_alg, hash, hashlen );
switch( ret )
{
case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
/* act as if f_async_sign was null */
break;
case 0:
ssl->handshake->async_in_progress = 1;
return( ssl_resume_server_key_exchange( ssl, signature_len ) );
case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
ssl->handshake->async_in_progress = 1;
return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
default:
MBEDTLS_SSL_DEBUG_RET( 1, "f_async_sign_start", ret );
return( ret );
}
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
if( mbedtls_ssl_own_key( ssl ) == NULL )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key" ) );
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
}
/* Append the signature to ssl->out_msg, leaving 2 bytes for the
* signature length which will be added in ssl_write_server_key_exchange
* after the call to ssl_prepare_server_key_exchange.
* ssl_write_server_key_exchange also takes care of incrementing
* ssl->out_msglen. */
if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ),
md_alg, hash, hashlen,
ssl->out_msg + ssl->out_msglen + 2,
signature_len,
ssl->conf->f_rng,
ssl->conf->p_rng ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
return( ret );
}
*(p++) = (unsigned char)( signature_len >> 8 );
*(p++) = (unsigned char)( signature_len );
n += 2;
MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len );
n += signature_len;
}
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
/* Done with actual work; add header and send. */
return( 0 );
}
ssl->out_msglen = 4 + n;
/* Prepare the ServerKeyExchange message and send it. For ciphersuites
* that do not include a ServerKeyExchange message, do nothing. Either
* way, if successful, move on to the next step in the SSL state
* machine. */
static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
{
int ret;
size_t signature_len = 0;
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
ssl->transform_negotiate->ciphersuite_info;
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED)
/* Extract static ECDH parameters and abort if ServerKeyExchange
* is not needed. */
if( mbedtls_ssl_ciphersuite_no_pfs( ciphersuite_info ) )
{
/* For suites involving ECDH, extract DH parameters
* from certificate at this point. */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED)
if( mbedtls_ssl_ciphersuite_uses_ecdh( ciphersuite_info ) )
{
ssl_get_ecdh_params_from_cert( ssl );
}
#endif /* MBEDTLS_KEY_EXCHANGE__SOME__ECDH_ENABLED */
/* Key exchanges not involving ephemeral keys don't use
* ServerKeyExchange, so end here. */
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
ssl->state++;
return( 0 );
}
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_NON_PFS__ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) && \
defined(MBEDTLS_SSL_ASYNC_PRIVATE)
/* If we have already prepared the message and there is an ongoing
* signature operation, resume signing. */
if( ssl->handshake->async_in_progress != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming signature operation" ) );
ret = ssl_resume_server_key_exchange( ssl, &signature_len );
}
else
#endif /* defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED) &&
defined(MBEDTLS_SSL_ASYNC_PRIVATE) */
{
/* ServerKeyExchange is needed. Prepare the message. */
ret = ssl_prepare_server_key_exchange( ssl, &signature_len );
}
if( ret != 0 )
{
/* If we're starting to write a new message, set ssl->out_msglen
* to 0. But if we're resuming after an asynchronous message,
* out_msglen is the amount of data written so far and mst be
* preserved. */
if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange (pending)" ) );
else
ssl->out_msglen = 0;
return( ret );
}
/* If there is a signature, write its length.
* ssl_prepare_server_key_exchange already wrote the signature
* itself at its proper place in the output buffer. */
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
if( signature_len != 0 )
{
ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len >> 8 );
ssl->out_msg[ssl->out_msglen++] = (unsigned char)( signature_len );
MBEDTLS_SSL_DEBUG_BUF( 3, "my signature",
ssl->out_msg + ssl->out_msglen,
signature_len );
/* Skip over the already-written signature */
ssl->out_msglen += signature_len;
}
#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
/* Add header and send. */
ssl->out_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE;
@ -3197,7 +3314,6 @@ curve_matching_done:
}
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
return( 0 );
}
@ -3272,28 +3388,50 @@ static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char *
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
const unsigned char *p,
const unsigned char *end,
size_t pms_offset )
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
static int ssl_resume_decrypt_pms( mbedtls_ssl_context *ssl,
unsigned char *peer_pms,
size_t *peer_pmslen,
size_t peer_pmssize )
{
int ret = ssl->conf->f_async_resume( ssl,
peer_pms, peer_pmslen, peer_pmssize );
if( ret != MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
{
ssl->handshake->async_in_progress = 0;
mbedtls_ssl_set_async_operation_data( ssl, NULL );
}
MBEDTLS_SSL_DEBUG_RET( 2, "ssl_decrypt_encrypted_pms", ret );
return( ret );
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
const unsigned char *p,
const unsigned char *end,
unsigned char *peer_pms,
size_t *peer_pmslen,
size_t peer_pmssize )
{
int ret;
size_t len = mbedtls_pk_get_len( mbedtls_ssl_own_key( ssl ) );
unsigned char *pms = ssl->handshake->premaster + pms_offset;
unsigned char ver[2];
unsigned char fake_pms[48], peer_pms[48];
unsigned char mask;
size_t i, peer_pmslen;
unsigned int diff;
mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk;
size_t len = mbedtls_pk_get_len( public_key );
if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) )
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
/* If we have already started decoding the message and there is an ongoing
* decryption operation, resume signing. */
if( ssl->handshake->async_in_progress != 0 )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
MBEDTLS_SSL_DEBUG_MSG( 2, ( "resuming decryption operation" ) );
return( ssl_resume_decrypt_pms( ssl,
peer_pms, peer_pmslen, peer_pmssize ) );
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
/*
* Decrypt the premaster using own private RSA key
* Prepare to decrypt the premaster using own private RSA key
*/
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
@ -3314,30 +3452,120 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
}
/*
* Decrypt the premaster secret
*/
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( ssl->conf->f_async_decrypt_start != NULL )
{
ret = ssl->conf->f_async_decrypt_start( ssl,
mbedtls_ssl_own_cert( ssl ),
p, len );
switch( ret )
{
case MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH:
/* act as if f_async_decrypt_start was null */
break;
case 0:
ssl->handshake->async_in_progress = 1;
return( ssl_resume_decrypt_pms( ssl,
peer_pms,
peer_pmslen,
peer_pmssize ) );
case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
ssl->handshake->async_in_progress = 1;
return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
default:
MBEDTLS_SSL_DEBUG_RET( 1, "f_async_decrypt_start", ret );
return( ret );
}
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
}
ret = mbedtls_pk_decrypt( private_key, p, len,
peer_pms, peer_pmslen, peer_pmssize,
ssl->conf->f_rng, ssl->conf->p_rng );
return( ret );
}
static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
const unsigned char *p,
const unsigned char *end,
size_t pms_offset )
{
int ret;
unsigned char *pms = ssl->handshake->premaster + pms_offset;
unsigned char ver[2];
unsigned char fake_pms[48], peer_pms[48];
unsigned char mask;
size_t i, peer_pmslen;
unsigned int diff;
/* In case of a failure in decryption, the decryption may write less than
* 2 bytes of output, but we always read the first two bytes. It doesn't
* matter in the end because diff will be nonzero in that case due to
* peer_pmslen being less than 48, and we only care whether diff is 0.
* But do initialize peer_pms for robustness anyway. This also makes
* memory analyzers happy (don't access uninitialized memory, even
* if it's an unsigned char). */
peer_pms[0] = peer_pms[1] = ~0;
ret = ssl_decrypt_encrypted_pms( ssl, p, end,
peer_pms,
&peer_pmslen,
sizeof( peer_pms ) );
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if ( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS )
return( ret );
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
mbedtls_ssl_write_version( ssl->handshake->max_major_ver,
ssl->handshake->max_minor_ver,
ssl->conf->transport, ver );
ssl->handshake->max_minor_ver,
ssl->conf->transport, ver );
/* Avoid data-dependent branches while checking for invalid
* padding, to protect against timing-based Bleichenbacher-type
* attacks. */
diff = (unsigned int) ret;
diff |= peer_pmslen ^ 48;
diff |= peer_pms[0] ^ ver[0];
diff |= peer_pms[1] ^ ver[1];
/* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
/* MSVC has a warning about unary minus on unsigned, but this is
* well-defined and precisely what we want to do here */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
/*
* Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
* must not cause the connection to end immediately; instead, send a
* bad_record_mac later in the handshake.
* Also, avoid data-dependant branches here to protect against
* timing-based variants.
* To protect against timing-based variants of the attack, we must
* not have any branch that depends on whether the decryption was
* successful. In particular, always generate the fake premaster secret,
* regardless of whether it will ultimately influence the output or not.
*/
ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) );
if( ret != 0 )
{
/* It's ok to abort on an RNG failure, since this does not reveal
* anything about the RSA decryption. */
return( ret );
ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len,
peer_pms, &peer_pmslen,
sizeof( peer_pms ),
ssl->conf->f_rng, ssl->conf->p_rng );
diff = (unsigned int) ret;
diff |= peer_pmslen ^ 48;
diff |= peer_pms[0] ^ ver[0];
diff |= peer_pms[1] ^ ver[1];
}
#if defined(MBEDTLS_SSL_DEBUG_ALL)
if( diff != 0 )
@ -3352,18 +3580,8 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
}
ssl->handshake->pmslen = 48;
/* mask = diff ? 0xff : 0x00 using bit operations to avoid branches */
/* MSVC has a warning about unary minus on unsigned, but this is
* well-defined and precisely what we want to do here */
#if defined(_MSC_VER)
#pragma warning( push )
#pragma warning( disable : 4146 )
#endif
mask = - ( ( diff | - diff ) >> ( sizeof( unsigned int ) * 8 - 1 ) );
#if defined(_MSC_VER)
#pragma warning( pop )
#endif
/* Set pms to either the true or the fake PMS, without
* data-dependent branches. */
for( i = 0; i < ssl->handshake->pmslen; i++ )
pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] );
@ -3445,6 +3663,20 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) && \
( defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) )
if( ( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ||
ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA ) &&
( ssl->handshake->async_in_progress != 0 ) )
{
/* We've already read a record and there is an asynchronous
* operation in progress to decrypt it. So skip reading the
* record. */
MBEDTLS_SSL_DEBUG_MSG( 3, ( "will resume decryption of previously-read record" ) );
}
else
#endif
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
@ -3557,6 +3789,19 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
{
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if ( ssl->handshake->async_in_progress != 0 )
{
/* There is an asynchronous operation in progress to
* decrypt the encrypted premaster secret, so skip
* directly to resuming this operation. */
MBEDTLS_SSL_DEBUG_MSG( 3, ( "PSK identity already parsed" ) );
/* Update p to skip the PSK identity. ssl_parse_encrypted_pms
* won't actually use it, but maintain p anyway for robustness. */
p += ssl->conf->psk_identity_len + 2;
}
else
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );

View file

@ -5202,7 +5202,7 @@ static void ssl_handshake_wrapup_free_hs_transform( mbedtls_ssl_context *ssl )
/*
* Free our handshake params
*/
mbedtls_ssl_handshake_free( ssl->handshake );
mbedtls_ssl_handshake_free( ssl );
mbedtls_free( ssl->handshake );
ssl->handshake = NULL;
@ -5557,7 +5557,7 @@ static int ssl_handshake_init( mbedtls_ssl_context *ssl )
if( ssl->session_negotiate )
mbedtls_ssl_session_free( ssl->session_negotiate );
if( ssl->handshake )
mbedtls_ssl_handshake_free( ssl->handshake );
mbedtls_ssl_handshake_free( ssl );
/*
* Either the pointers are now NULL or cleared properly and can be freed.
@ -6480,6 +6480,43 @@ void mbedtls_ssl_conf_export_keys_cb( mbedtls_ssl_config *conf,
}
#endif
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
void mbedtls_ssl_conf_async_private_cb(
mbedtls_ssl_config *conf,
mbedtls_ssl_async_sign_t *f_async_sign,
mbedtls_ssl_async_decrypt_t *f_async_decrypt,
mbedtls_ssl_async_resume_t *f_async_resume,
mbedtls_ssl_async_cancel_t *f_async_cancel,
void *async_config_data )
{
conf->f_async_sign_start = f_async_sign;
conf->f_async_decrypt_start = f_async_decrypt;
conf->f_async_resume = f_async_resume;
conf->f_async_cancel = f_async_cancel;
conf->p_async_config_data = async_config_data;
}
void *mbedtls_ssl_conf_get_async_config_data( const mbedtls_ssl_config *conf )
{
return( conf->p_async_config_data );
}
void *mbedtls_ssl_get_async_operation_data( const mbedtls_ssl_context *ssl )
{
if( ssl->handshake == NULL )
return( NULL );
else
return( ssl->handshake->user_async_ctx );
}
void mbedtls_ssl_set_async_operation_data( mbedtls_ssl_context *ssl,
void *ctx )
{
if( ssl->handshake != NULL )
ssl->handshake->user_async_ctx = ctx;
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
/*
* SSL get accessors
*/
@ -7387,11 +7424,21 @@ static void ssl_key_cert_free( mbedtls_ssl_key_cert *key_cert )
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake )
void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl )
{
mbedtls_ssl_handshake_params *handshake = ssl->handshake;
if( handshake == NULL )
return;
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( ssl->conf->f_async_cancel != NULL && handshake->async_in_progress != 0 )
{
ssl->conf->f_async_cancel( ssl );
handshake->async_in_progress = 0;
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_1)
mbedtls_md5_free( &handshake->fin_md5 );
@ -7522,7 +7569,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl )
if( ssl->handshake )
{
mbedtls_ssl_handshake_free( ssl->handshake );
mbedtls_ssl_handshake_free( ssl );
mbedtls_ssl_transform_free( ssl->transform_negotiate );
mbedtls_ssl_session_free( ssl->session_negotiate );
@ -8289,13 +8336,14 @@ exit:
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
unsigned char *output,
unsigned char *data, size_t data_len,
mbedtls_md_type_t md_alg )
unsigned char *hash, size_t *hashlen,
unsigned char *data, size_t data_len,
mbedtls_md_type_t md_alg )
{
int ret = 0;
mbedtls_md_context_t ctx;
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
*hashlen = mbedtls_md_get_size( md_info );
mbedtls_md_init( &ctx );
@ -8326,7 +8374,7 @@ int mbedtls_ssl_get_key_exchange_md_tls1_2( mbedtls_ssl_context *ssl,
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_update", ret );
goto exit;
}
if( ( ret = mbedtls_md_finish( &ctx, output ) ) != 0 )
if( ( ret = mbedtls_md_finish( &ctx, hash ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_md_finish", ret );
goto exit;

View file

@ -411,6 +411,9 @@ static const char *features[] = {
#if defined(MBEDTLS_SSL_ALL_ALERT_MESSAGES)
"MBEDTLS_SSL_ALL_ALERT_MESSAGES",
#endif /* MBEDTLS_SSL_ALL_ALERT_MESSAGES */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
"MBEDTLS_SSL_ASYNC_PRIVATE",
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#if defined(MBEDTLS_SSL_DEBUG_ALL)
"MBEDTLS_SSL_DEBUG_ALL",
#endif /* MBEDTLS_SSL_DEBUG_ALL */

View file

@ -109,6 +109,10 @@ int main( void )
#define DFL_KEY_FILE ""
#define DFL_CRT_FILE2 ""
#define DFL_KEY_FILE2 ""
#define DFL_ASYNC_OPERATIONS "-"
#define DFL_ASYNC_PRIVATE_DELAY1 ( -1 )
#define DFL_ASYNC_PRIVATE_DELAY2 ( -1 )
#define DFL_ASYNC_PRIVATE_ERROR ( 0 )
#define DFL_PSK ""
#define DFL_PSK_IDENTITY "Client_identity"
#define DFL_ECJPAKE_PW NULL
@ -196,6 +200,18 @@ int main( void )
#define USAGE_IO ""
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
#define USAGE_SSL_ASYNC \
" async_operations=%%c... d=decrypt, s=sign (default: -=off)\n" \
" async_private_delay1=%%d Asynchronous delay for key_file or preloaded key\n" \
" async_private_delay2=%%d Asynchronous delay for key_file2 and sni\n" \
" default: -1 (not asynchronous)\n" \
" async_private_error=%%d Async callback error injection (default=0=none,\n" \
" 1=start, 2=cancel, 3=resume, negative=first time only)"
#else
#define USAGE_SSL_ASYNC ""
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
#define USAGE_PSK \
" psk=%%s default: \"\" (in hex, without 0x)\n" \
@ -346,6 +362,7 @@ int main( void )
" cert_req_ca_list=%%d default: 1 (send ca list)\n" \
" options: 1 (send ca list), 0 (don't send)\n" \
USAGE_IO \
USAGE_SSL_ASYNC \
USAGE_SNI \
"\n" \
USAGE_PSK \
@ -410,6 +427,10 @@ struct options
const char *key_file; /* the file with the server key */
const char *crt_file2; /* the file with the 2nd server certificate */
const char *key_file2; /* the file with the 2nd server key */
const char *async_operations; /* supported SSL asynchronous operations */
int async_private_delay1; /* number of times f_async_resume needs to be called for key 1, or -1 for no async */
int async_private_delay2; /* number of times f_async_resume needs to be called for key 2, or -1 for no async */
int async_private_error; /* inject error in async private callback */
const char *psk; /* the pre-shared key */
const char *psk_identity; /* the pre-shared key identity */
char *psk_list; /* list of PSK id/key pairs for callback */
@ -841,6 +862,243 @@ static int ssl_sig_hashes_for_test[] = {
};
#endif /* MBEDTLS_X509_CRT_PARSE_C */
/** Return true if \p ret is a status code indicating that there is an
* operation in progress on an SSL connection, and false if it indicates
* success or a fatal error.
*
* The possible operations in progress are:
*
* - A read, when the SSL input buffer does not contain a full message.
* - A write, when the SSL output buffer contains some data that has not
* been sent over the network yet.
* - An asynchronous callback that has not completed yet. */
static int mbedtls_status_is_ssl_in_progress( int ret )
{
return( ret == MBEDTLS_ERR_SSL_WANT_READ ||
ret == MBEDTLS_ERR_SSL_WANT_WRITE ||
ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
}
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
typedef struct
{
mbedtls_x509_crt *cert; /*!< Certificate corresponding to the key */
mbedtls_pk_context *pk; /*!< Private key */
unsigned delay; /*!< Number of resume steps to go through */
unsigned pk_owned : 1; /*!< Whether to free the pk object on exit */
} ssl_async_key_slot_t;
typedef enum {
SSL_ASYNC_INJECT_ERROR_NONE = 0, /*!< Let the callbacks succeed */
SSL_ASYNC_INJECT_ERROR_START, /*!< Inject error during start */
SSL_ASYNC_INJECT_ERROR_CANCEL, /*!< Close the connection after async start */
SSL_ASYNC_INJECT_ERROR_RESUME, /*!< Inject error during resume */
#define SSL_ASYNC_INJECT_ERROR_MAX SSL_ASYNC_INJECT_ERROR_RESUME
} ssl_async_inject_error_t;
typedef struct
{
ssl_async_key_slot_t slots[4]; /* key, key2, sni1, sni2 */
size_t slots_used;
ssl_async_inject_error_t inject_error;
int (*f_rng)(void *, unsigned char *, size_t);
void *p_rng;
} ssl_async_key_context_t;
int ssl_async_set_key( ssl_async_key_context_t *ctx,
mbedtls_x509_crt *cert,
mbedtls_pk_context *pk,
int pk_take_ownership,
unsigned delay )
{
if( ctx->slots_used >= sizeof( ctx->slots ) / sizeof( *ctx->slots ) )
return( -1 );
ctx->slots[ctx->slots_used].cert = cert;
ctx->slots[ctx->slots_used].pk = pk;
ctx->slots[ctx->slots_used].delay = delay;
ctx->slots[ctx->slots_used].pk_owned = pk_take_ownership;
++ctx->slots_used;
return( 0 );
}
#define SSL_ASYNC_INPUT_MAX_SIZE 512
typedef enum
{
ASYNC_OP_SIGN,
ASYNC_OP_DECRYPT,
} ssl_async_operation_type_t;
/* Note that the enum above and the array below need to be kept in sync!
* `ssl_async_operation_names[op]` is the name of op for each value `op`
* of type `ssl_async_operation_type_t`. */
static const char *const ssl_async_operation_names[] =
{
"sign",
"decrypt",
};
typedef struct
{
unsigned slot;
ssl_async_operation_type_t operation_type;
mbedtls_md_type_t md_alg;
unsigned char input[SSL_ASYNC_INPUT_MAX_SIZE];
size_t input_len;
unsigned remaining_delay;
} ssl_async_operation_context_t;
static int ssl_async_start( mbedtls_ssl_context *ssl,
mbedtls_x509_crt *cert,
ssl_async_operation_type_t op_type,
mbedtls_md_type_t md_alg,
const unsigned char *input,
size_t input_len )
{
ssl_async_key_context_t *config_data =
mbedtls_ssl_conf_get_async_config_data( ssl->conf );
unsigned slot;
ssl_async_operation_context_t *ctx = NULL;
const char *op_name = ssl_async_operation_names[op_type];
{
char dn[100];
mbedtls_x509_dn_gets( dn, sizeof( dn ), &cert->subject );
mbedtls_printf( "Async %s callback: looking for DN=%s\n", op_name, dn );
}
/* Look for a private key that matches the public key in cert.
* Since this test code has the private key inside Mbed TLS,
* we call mbedtls_pk_check_pair to match a private key with the
* public key. */
for( slot = 0; slot < config_data->slots_used; slot++ )
{
if( mbedtls_pk_check_pair( &cert->pk,
config_data->slots[slot].pk ) == 0 )
break;
}
if( slot == config_data->slots_used )
{
mbedtls_printf( "Async %s callback: no key matches this certificate.\n",
op_name );
return( MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH );
}
mbedtls_printf( "Async %s callback: using key slot %u, delay=%u.\n",
op_name, slot, config_data->slots[slot].delay );
if( config_data->inject_error == SSL_ASYNC_INJECT_ERROR_START )
{
mbedtls_printf( "Async %s callback: injected error\n", op_name );
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
}
if( input_len > SSL_ASYNC_INPUT_MAX_SIZE )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
ctx = mbedtls_calloc( 1, sizeof( *ctx ) );
if( ctx == NULL )
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
ctx->slot = slot;
ctx->operation_type = op_type;
ctx->md_alg = md_alg;
memcpy( ctx->input, input, input_len );
ctx->input_len = input_len;
ctx->remaining_delay = config_data->slots[slot].delay;
mbedtls_ssl_set_async_operation_data( ssl, ctx );
if( ctx->remaining_delay == 0 )
return( 0 );
else
return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
}
static int ssl_async_sign( mbedtls_ssl_context *ssl,
mbedtls_x509_crt *cert,
mbedtls_md_type_t md_alg,
const unsigned char *hash,
size_t hash_len )
{
return( ssl_async_start( ssl, cert,
ASYNC_OP_SIGN, md_alg,
hash, hash_len ) );
}
static int ssl_async_decrypt( mbedtls_ssl_context *ssl,
mbedtls_x509_crt *cert,
const unsigned char *input,
size_t input_len )
{
return( ssl_async_start( ssl, cert,
ASYNC_OP_DECRYPT, MBEDTLS_MD_NONE,
input, input_len ) );
}
static int ssl_async_resume( mbedtls_ssl_context *ssl,
unsigned char *output,
size_t *output_len,
size_t output_size )
{
ssl_async_operation_context_t *ctx = mbedtls_ssl_get_async_operation_data( ssl );
ssl_async_key_context_t *config_data =
mbedtls_ssl_conf_get_async_config_data( ssl->conf );
ssl_async_key_slot_t *key_slot = &config_data->slots[ctx->slot];
int ret;
const char *op_name;
if( ctx->remaining_delay > 0 )
{
--ctx->remaining_delay;
mbedtls_printf( "Async resume (slot %u): call %u more times.\n",
ctx->slot, ctx->remaining_delay );
return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS );
}
switch( ctx->operation_type )
{
case ASYNC_OP_DECRYPT:
ret = mbedtls_pk_decrypt( key_slot->pk,
ctx->input, ctx->input_len,
output, output_len, output_size,
config_data->f_rng, config_data->p_rng );
break;
case ASYNC_OP_SIGN:
ret = mbedtls_pk_sign( key_slot->pk,
ctx->md_alg,
ctx->input, ctx->input_len,
output, output_len,
config_data->f_rng, config_data->p_rng );
break;
default:
mbedtls_printf( "Async resume (slot %u): unknown operation type %ld. This shouldn't happen.\n",
ctx->slot, (long) ctx->operation_type );
mbedtls_free( ctx );
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
break;
}
op_name = ssl_async_operation_names[ctx->operation_type];
if( config_data->inject_error == SSL_ASYNC_INJECT_ERROR_RESUME )
{
mbedtls_printf( "Async resume callback: %s done but injected error\n",
op_name );
mbedtls_free( ctx );
return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
}
mbedtls_printf( "Async resume (slot %u): %s done, status=%d.\n",
ctx->slot, op_name, ret );
mbedtls_free( ctx );
return( ret );
}
static void ssl_async_cancel( mbedtls_ssl_context *ssl )
{
ssl_async_operation_context_t *ctx = mbedtls_ssl_get_async_operation_data( ssl );
mbedtls_printf( "Async cancel callback.\n" );
mbedtls_free( ctx );
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
/*
* Wait for an event from the underlying transport or the timer
* (Used in event-driven IO mode).
@ -929,7 +1187,10 @@ int main( int argc, char *argv[] )
mbedtls_x509_crt srvcert2;
mbedtls_pk_context pkey2;
int key_cert_init = 0, key_cert_init2 = 0;
#endif
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
ssl_async_key_context_t ssl_async_keys;
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO)
mbedtls_dhm_context dhm;
#endif
@ -975,6 +1236,9 @@ int main( int argc, char *argv[] )
mbedtls_pk_init( &pkey );
mbedtls_x509_crt_init( &srvcert2 );
mbedtls_pk_init( &pkey2 );
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
memset( &ssl_async_keys, 0, sizeof( ssl_async_keys ) );
#endif
#endif
#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO)
mbedtls_dhm_init( &dhm );
@ -1032,6 +1296,10 @@ int main( int argc, char *argv[] )
opt.key_file = DFL_KEY_FILE;
opt.crt_file2 = DFL_CRT_FILE2;
opt.key_file2 = DFL_KEY_FILE2;
opt.async_operations = DFL_ASYNC_OPERATIONS;
opt.async_private_delay1 = DFL_ASYNC_PRIVATE_DELAY1;
opt.async_private_delay2 = DFL_ASYNC_PRIVATE_DELAY2;
opt.async_private_error = DFL_ASYNC_PRIVATE_ERROR;
opt.psk = DFL_PSK;
opt.psk_identity = DFL_PSK_IDENTITY;
opt.psk_list = DFL_PSK_LIST;
@ -1124,6 +1392,25 @@ int main( int argc, char *argv[] )
opt.key_file2 = q;
else if( strcmp( p, "dhm_file" ) == 0 )
opt.dhm_file = q;
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
else if( strcmp( p, "async_operations" ) == 0 )
opt.async_operations = q;
else if( strcmp( p, "async_private_delay1" ) == 0 )
opt.async_private_delay1 = atoi( q );
else if( strcmp( p, "async_private_delay2" ) == 0 )
opt.async_private_delay2 = atoi( q );
else if( strcmp( p, "async_private_error" ) == 0 )
{
int n = atoi( q );
if( n < -SSL_ASYNC_INJECT_ERROR_MAX ||
n > SSL_ASYNC_INJECT_ERROR_MAX )
{
ret = 2;
goto usage;
}
opt.async_private_error = n;
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
else if( strcmp( p, "psk" ) == 0 )
opt.psk = q;
else if( strcmp( p, "psk_identity" ) == 0 )
@ -2018,22 +2305,109 @@ int main( int argc, char *argv[] )
mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
}
if( key_cert_init )
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 )
{
mbedtls_pk_context *pk = &pkey;
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( opt.async_private_delay1 >= 0 )
{
ret = ssl_async_set_key( &ssl_async_keys, &srvcert, pk, 0,
opt.async_private_delay1 );
if( ret < 0 )
{
mbedtls_printf( " Test error: ssl_async_set_key failed (%d)\n",
ret );
goto exit;
}
pk = NULL;
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, pk ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
goto exit;
}
}
if( key_cert_init2 )
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert2, &pkey2 ) ) != 0 )
{
mbedtls_pk_context *pk = &pkey2;
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( opt.async_private_delay2 >= 0 )
{
ret = ssl_async_set_key( &ssl_async_keys, &srvcert2, pk, 0,
opt.async_private_delay2 );
if( ret < 0 )
{
mbedtls_printf( " Test error: ssl_async_set_key failed (%d)\n",
ret );
goto exit;
}
pk = NULL;
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert2, pk ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
goto exit;
}
#endif
}
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( opt.async_operations[0] != '-' )
{
mbedtls_ssl_async_sign_t *sign = NULL;
mbedtls_ssl_async_decrypt_t *decrypt = NULL;
const char *r;
for( r = opt.async_operations; *r; r++ )
{
switch( *r )
{
case 'd':
decrypt = ssl_async_decrypt;
break;
case 's':
sign = ssl_async_sign;
break;
}
}
ssl_async_keys.inject_error = ( opt.async_private_error < 0 ?
- opt.async_private_error :
opt.async_private_error );
ssl_async_keys.f_rng = mbedtls_ctr_drbg_random;
ssl_async_keys.p_rng = &ctr_drbg;
mbedtls_ssl_conf_async_private_cb( &conf,
sign,
decrypt,
ssl_async_resume,
ssl_async_cancel,
&ssl_async_keys );
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(SNI_OPTION)
if( opt.sni != NULL )
{
mbedtls_ssl_conf_sni( &conf, sni_callback, sni_info );
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( opt.async_private_delay2 >= 0 )
{
sni_entry *cur;
for( cur = sni_info; cur != NULL; cur = cur->next )
{
ret = ssl_async_set_key( &ssl_async_keys,
cur->cert, cur->key, 1,
opt.async_private_delay2 );
if( ret < 0 )
{
mbedtls_printf( " Test error: ssl_async_set_key failed (%d)\n",
ret );
goto exit;
}
cur->key = NULL;
}
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
}
#endif
#if defined(MBEDTLS_ECP_C)
@ -2205,8 +2579,16 @@ handshake:
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
{
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS &&
ssl_async_keys.inject_error == SSL_ASYNC_INJECT_ERROR_CANCEL )
{
mbedtls_printf( " cancelling on injected error\n" );
break;
}
#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */
if( ! mbedtls_status_is_ssl_in_progress( ret ) )
break;
/* For event-driven IO, wait for socket to become available */
@ -2244,6 +2626,11 @@ handshake:
}
#endif
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
if( opt.async_private_error < 0 )
/* Injected error only the first time round, to test reset */
ssl_async_keys.inject_error = SSL_ASYNC_INJECT_ERROR_NONE;
#endif
goto reset;
}
else /* ret == 0 */
@ -2324,8 +2711,7 @@ data_exchange:
memset( buf, 0, sizeof( buf ) );
ret = mbedtls_ssl_read( &ssl, buf, len );
if( ret == MBEDTLS_ERR_SSL_WANT_READ ||
ret == MBEDTLS_ERR_SSL_WANT_WRITE )
if( mbedtls_status_is_ssl_in_progress( ret ) )
{
if( opt.event == 1 /* level triggered IO */ )
{
@ -2425,7 +2811,7 @@ data_exchange:
len = sizeof( buf ) - 1;
memset( buf, 0, sizeof( buf ) );
while( 1 )
do
{
/* Without the call to `mbedtls_ssl_check_pending`, it might
* happen that the client sends application data in the same
@ -2455,10 +2841,8 @@ data_exchange:
* it can happen that the subsequent call to `mbedtls_ssl_read`
* returns `MBEDTLS_ERR_SSL_WANT_READ`, because the pending messages
* might be discarded (e.g. because they are retransmissions). */
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
break;
}
while( mbedtls_status_is_ssl_in_progress( ret ) );
if( ret <= 0 )
{
@ -2493,8 +2877,7 @@ data_exchange:
while( ( ret = mbedtls_ssl_renegotiate( &ssl ) ) != 0 )
{
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
if( ! mbedtls_status_is_ssl_in_progress( ret ) )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", ret );
goto reset;
@ -2537,8 +2920,7 @@ data_exchange:
goto reset;
}
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
if( ! mbedtls_status_is_ssl_in_progress( ret ) )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
goto reset;
@ -2562,8 +2944,7 @@ data_exchange:
{
ret = mbedtls_ssl_write( &ssl, buf, len );
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
if( ! mbedtls_status_is_ssl_in_progress( ret ) )
break;
/* For event-driven IO, wait for socket to become available */
@ -2641,6 +3022,17 @@ exit:
mbedtls_x509_crt_free( &srvcert2 );
mbedtls_pk_free( &pkey2 );
#endif
#if defined(MBEDTLS_SSL_ASYNC_PRIVATE)
for( i = 0; (size_t) i < ssl_async_keys.slots_used; i++ )
{
if( ssl_async_keys.slots[i].pk_owned )
{
mbedtls_pk_free( ssl_async_keys.slots[i].pk );
mbedtls_free( ssl_async_keys.slots[i].pk );
ssl_async_keys.slots[i].pk = NULL;
}
}
#endif
#if defined(SNI_OPTION)
sni_free( sni_info );
#endif

View file

@ -531,8 +531,8 @@ make
msg "test: main suites (full config)" # ~ 5s
make test
msg "test: ssl-opt.sh default (full config)" # ~ 1s
if_build_succeeded tests/ssl-opt.sh -f Default
msg "test: ssl-opt.sh default, ECJPAKE (full config)" # ~ 1s
if_build_succeeded tests/ssl-opt.sh -f 'Default\|ECJPAKE'
msg "test: compat.sh RC4, DES & NULL (full config)" # ~ 2 min
if_build_succeeded env OPENSSL_CMD="$OPENSSL_LEGACY" GNUTLS_CLI="$GNUTLS_LEGACY_CLI" GNUTLS_SERV="$GNUTLS_LEGACY_SERV" tests/compat.sh -e '3DES\|DES-CBC3' -f 'NULL\|DES\|RC4\|ARCFOUR'

View file

@ -4067,6 +4067,354 @@ run_test "Large packet TLS 1.2 AEAD shorter tag" \
-c "16384 bytes written in 1 fragments" \
-s "Read from client: 16384 bytes read"
# Tests of asynchronous private key support in SSL
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: sign, delay=0" \
"$P_SRV \
async_operations=s async_private_delay1=0 async_private_delay2=0" \
"$P_CLI" \
0 \
-s "Async sign callback: using key slot " \
-s "Async resume (slot [0-9]): sign done, status=0"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: sign, delay=1" \
"$P_SRV \
async_operations=s async_private_delay1=1 async_private_delay2=1" \
"$P_CLI" \
0 \
-s "Async sign callback: using key slot " \
-s "Async resume (slot [0-9]): call 0 more times." \
-s "Async resume (slot [0-9]): sign done, status=0"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: sign, delay=2" \
"$P_SRV \
async_operations=s async_private_delay1=2 async_private_delay2=2" \
"$P_CLI" \
0 \
-s "Async sign callback: using key slot " \
-U "Async sign callback: using key slot " \
-s "Async resume (slot [0-9]): call 1 more times." \
-s "Async resume (slot [0-9]): call 0 more times." \
-s "Async resume (slot [0-9]): sign done, status=0"
# Test that the async callback correctly signs the 36-byte hash of TLS 1.0/1.1
# with RSA PKCS#1v1.5 as used in TLS 1.0/1.1.
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_1
run_test "SSL async private: sign, RSA, TLS 1.1" \
"$P_SRV key_file=data_files/server2.key crt_file=data_files/server2.crt \
async_operations=s async_private_delay1=0 async_private_delay2=0" \
"$P_CLI force_version=tls1_1" \
0 \
-s "Async sign callback: using key slot " \
-s "Async resume (slot [0-9]): sign done, status=0"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: sign, SNI" \
"$P_SRV debug_level=3 \
async_operations=s async_private_delay1=0 async_private_delay2=0 \
crt_file=data_files/server5.crt key_file=data_files/server5.key \
sni=localhost,data_files/server2.crt,data_files/server2.key,-,-,-,polarssl.example,data_files/server1-nospace.crt,data_files/server1.key,-,-,-" \
"$P_CLI server_name=polarssl.example" \
0 \
-s "Async sign callback: using key slot " \
-s "Async resume (slot [0-9]): sign done, status=0" \
-s "parse ServerName extension" \
-c "issuer name *: C=NL, O=PolarSSL, CN=PolarSSL Test CA" \
-c "subject name *: C=NL, O=PolarSSL, CN=polarssl.example"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: decrypt, delay=0" \
"$P_SRV \
async_operations=d async_private_delay1=0 async_private_delay2=0" \
"$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
0 \
-s "Async decrypt callback: using key slot " \
-s "Async resume (slot [0-9]): decrypt done, status=0"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: decrypt, delay=1" \
"$P_SRV \
async_operations=d async_private_delay1=1 async_private_delay2=1" \
"$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
0 \
-s "Async decrypt callback: using key slot " \
-s "Async resume (slot [0-9]): call 0 more times." \
-s "Async resume (slot [0-9]): decrypt done, status=0"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: decrypt RSA-PSK, delay=0" \
"$P_SRV psk=abc123 \
async_operations=d async_private_delay1=0 async_private_delay2=0" \
"$P_CLI psk=abc123 \
force_ciphersuite=TLS-RSA-PSK-WITH-AES-128-CBC-SHA256" \
0 \
-s "Async decrypt callback: using key slot " \
-s "Async resume (slot [0-9]): decrypt done, status=0"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: decrypt RSA-PSK, delay=1" \
"$P_SRV psk=abc123 \
async_operations=d async_private_delay1=1 async_private_delay2=1" \
"$P_CLI psk=abc123 \
force_ciphersuite=TLS-RSA-PSK-WITH-AES-128-CBC-SHA256" \
0 \
-s "Async decrypt callback: using key slot " \
-s "Async resume (slot [0-9]): call 0 more times." \
-s "Async resume (slot [0-9]): decrypt done, status=0"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: sign callback not present" \
"$P_SRV \
async_operations=d async_private_delay1=1 async_private_delay2=1" \
"$P_CLI; [ \$? -eq 1 ] &&
$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
0 \
-S "Async sign callback" \
-s "! mbedtls_ssl_handshake returned" \
-s "The own private key or pre-shared key is not set, but needed" \
-s "Async resume (slot [0-9]): decrypt done, status=0" \
-s "Successful connection"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: decrypt callback not present" \
"$P_SRV debug_level=1 \
async_operations=s async_private_delay1=1 async_private_delay2=1" \
"$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA;
[ \$? -eq 1 ] && $P_CLI" \
0 \
-S "Async decrypt callback" \
-s "! mbedtls_ssl_handshake returned" \
-s "got no RSA private key" \
-s "Async resume (slot [0-9]): sign done, status=0" \
-s "Successful connection"
# key1: ECDSA, key2: RSA; use key1 from slot 0
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: slot 0 used with key1" \
"$P_SRV \
async_operations=s async_private_delay1=1 \
key_file=data_files/server5.key crt_file=data_files/server5.crt \
key_file2=data_files/server2.key crt_file2=data_files/server2.crt" \
"$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256" \
0 \
-s "Async sign callback: using key slot 0," \
-s "Async resume (slot 0): call 0 more times." \
-s "Async resume (slot 0): sign done, status=0"
# key1: ECDSA, key2: RSA; use key2 from slot 0
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: slot 0 used with key2" \
"$P_SRV \
async_operations=s async_private_delay2=1 \
key_file=data_files/server5.key crt_file=data_files/server5.crt \
key_file2=data_files/server2.key crt_file2=data_files/server2.crt" \
"$P_CLI force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256" \
0 \
-s "Async sign callback: using key slot 0," \
-s "Async resume (slot 0): call 0 more times." \
-s "Async resume (slot 0): sign done, status=0"
# key1: ECDSA, key2: RSA; use key2 from slot 1
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: slot 1 used with key2" \
"$P_SRV \
async_operations=s async_private_delay1=1 async_private_delay2=1 \
key_file=data_files/server5.key crt_file=data_files/server5.crt \
key_file2=data_files/server2.key crt_file2=data_files/server2.crt" \
"$P_CLI force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256" \
0 \
-s "Async sign callback: using key slot 1," \
-s "Async resume (slot 1): call 0 more times." \
-s "Async resume (slot 1): sign done, status=0"
# key1: ECDSA, key2: RSA; use key2 directly
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: fall back to transparent key" \
"$P_SRV \
async_operations=s async_private_delay1=1 \
key_file=data_files/server5.key crt_file=data_files/server5.crt \
key_file2=data_files/server2.key crt_file2=data_files/server2.crt " \
"$P_CLI force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256" \
0 \
-s "Async sign callback: no key matches this certificate."
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: sign, error in start" \
"$P_SRV \
async_operations=s async_private_delay1=1 async_private_delay2=1 \
async_private_error=1" \
"$P_CLI" \
1 \
-s "Async sign callback: injected error" \
-S "Async resume" \
-S "Async cancel" \
-s "! mbedtls_ssl_handshake returned"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: sign, cancel after start" \
"$P_SRV \
async_operations=s async_private_delay1=1 async_private_delay2=1 \
async_private_error=2" \
"$P_CLI" \
1 \
-s "Async sign callback: using key slot " \
-S "Async resume" \
-s "Async cancel"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: sign, error in resume" \
"$P_SRV \
async_operations=s async_private_delay1=1 async_private_delay2=1 \
async_private_error=3" \
"$P_CLI" \
1 \
-s "Async sign callback: using key slot " \
-s "Async resume callback: sign done but injected error" \
-S "Async cancel" \
-s "! mbedtls_ssl_handshake returned"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: decrypt, error in start" \
"$P_SRV \
async_operations=d async_private_delay1=1 async_private_delay2=1 \
async_private_error=1" \
"$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
1 \
-s "Async decrypt callback: injected error" \
-S "Async resume" \
-S "Async cancel" \
-s "! mbedtls_ssl_handshake returned"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: decrypt, cancel after start" \
"$P_SRV \
async_operations=d async_private_delay1=1 async_private_delay2=1 \
async_private_error=2" \
"$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
1 \
-s "Async decrypt callback: using key slot " \
-S "Async resume" \
-s "Async cancel"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: decrypt, error in resume" \
"$P_SRV \
async_operations=d async_private_delay1=1 async_private_delay2=1 \
async_private_error=3" \
"$P_CLI force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
1 \
-s "Async decrypt callback: using key slot " \
-s "Async resume callback: decrypt done but injected error" \
-S "Async cancel" \
-s "! mbedtls_ssl_handshake returned"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: cancel after start then operate correctly" \
"$P_SRV \
async_operations=s async_private_delay1=1 async_private_delay2=1 \
async_private_error=-2" \
"$P_CLI; [ \$? -eq 1 ] && $P_CLI" \
0 \
-s "Async cancel" \
-s "! mbedtls_ssl_handshake returned" \
-s "Async resume" \
-s "Successful connection"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: error in resume then operate correctly" \
"$P_SRV \
async_operations=s async_private_delay1=1 async_private_delay2=1 \
async_private_error=-3" \
"$P_CLI; [ \$? -eq 1 ] && $P_CLI" \
0 \
-s "! mbedtls_ssl_handshake returned" \
-s "Async resume" \
-s "Successful connection"
# key1: ECDSA, key2: RSA; use key1 through async, then key2 directly
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: cancel after start then fall back to transparent key" \
"$P_SRV \
async_operations=s async_private_delay1=1 async_private_error=-2 \
key_file=data_files/server5.key crt_file=data_files/server5.crt \
key_file2=data_files/server2.key crt_file2=data_files/server2.crt" \
"$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256;
[ \$? -eq 1 ] &&
$P_CLI force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256" \
0 \
-s "Async sign callback: using key slot 0" \
-S "Async resume" \
-s "Async cancel" \
-s "! mbedtls_ssl_handshake returned" \
-s "Async sign callback: no key matches this certificate." \
-s "Successful connection"
# key1: ECDSA, key2: RSA; use key1 through async, then key2 directly
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
run_test "SSL async private: sign, error in resume then fall back to transparent key" \
"$P_SRV \
async_operations=s async_private_delay1=1 async_private_error=-3 \
key_file=data_files/server5.key crt_file=data_files/server5.crt \
key_file2=data_files/server2.key crt_file2=data_files/server2.crt" \
"$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-CBC-SHA256;
[ \$? -eq 1 ] &&
$P_CLI force_ciphersuite=TLS-ECDHE-RSA-WITH-AES-128-CBC-SHA256" \
0 \
-s "Async resume" \
-s "! mbedtls_ssl_handshake returned" \
-s "Async sign callback: no key matches this certificate." \
-s "Successful connection"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
run_test "SSL async private: renegotiation: client-initiated; sign" \
"$P_SRV \
async_operations=s async_private_delay1=1 async_private_delay2=1 \
exchanges=2 renegotiation=1" \
"$P_CLI exchanges=2 renegotiation=1 renegotiate=1" \
0 \
-s "Async sign callback: using key slot " \
-s "Async resume (slot [0-9]): sign done, status=0"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
run_test "SSL async private: renegotiation: server-initiated; sign" \
"$P_SRV \
async_operations=s async_private_delay1=1 async_private_delay2=1 \
exchanges=2 renegotiation=1 renegotiate=1" \
"$P_CLI exchanges=2 renegotiation=1" \
0 \
-s "Async sign callback: using key slot " \
-s "Async resume (slot [0-9]): sign done, status=0"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
run_test "SSL async private: renegotiation: client-initiated; decrypt" \
"$P_SRV \
async_operations=d async_private_delay1=1 async_private_delay2=1 \
exchanges=2 renegotiation=1" \
"$P_CLI exchanges=2 renegotiation=1 renegotiate=1 \
force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
0 \
-s "Async decrypt callback: using key slot " \
-s "Async resume (slot [0-9]): decrypt done, status=0"
requires_config_enabled MBEDTLS_SSL_ASYNC_PRIVATE
requires_config_enabled MBEDTLS_SSL_RENEGOTIATION
run_test "SSL async private: renegotiation: server-initiated; decrypt" \
"$P_SRV \
async_operations=d async_private_delay1=1 async_private_delay2=1 \
exchanges=2 renegotiation=1 renegotiate=1" \
"$P_CLI exchanges=2 renegotiation=1 \
force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
0 \
-s "Async decrypt callback: using key slot " \
-s "Async resume (slot [0-9]): decrypt done, status=0"
# Tests for DTLS HelloVerifyRequest
run_test "DTLS cookie: enabled" \