|
@@ -91,6 +91,13 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
|
|
|
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) );
|
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) );
|
|
|
|
|
|
|
|
+ if( len < 2 )
|
|
|
|
+ {
|
|
|
|
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
|
|
|
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
|
|
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
|
|
|
+ }
|
|
servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
|
|
servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
|
|
if( servername_list_size + 2 != len )
|
|
if( servername_list_size + 2 != len )
|
|
{
|
|
{
|
|
@@ -101,7 +108,7 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl,
|
|
}
|
|
}
|
|
|
|
|
|
p = buf + 2;
|
|
p = buf + 2;
|
|
- while( servername_list_size > 0 )
|
|
|
|
|
|
+ while( servername_list_size > 2 )
|
|
{
|
|
{
|
|
hostname_len = ( ( p[1] << 8 ) | p[2] );
|
|
hostname_len = ( ( p[1] << 8 ) | p[2] );
|
|
if( hostname_len + 3 > servername_list_size )
|
|
if( hostname_len + 3 > servername_list_size )
|
|
@@ -205,6 +212,12 @@ static int ssl_parse_signature_algorithms_ext( mbedtls_ssl_context *ssl,
|
|
mbedtls_md_type_t md_cur;
|
|
mbedtls_md_type_t md_cur;
|
|
mbedtls_pk_type_t sig_cur;
|
|
mbedtls_pk_type_t sig_cur;
|
|
|
|
|
|
|
|
+ if ( len < 2 ) {
|
|
|
|
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
|
|
|
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
|
|
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
|
|
|
+ }
|
|
sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
|
|
sig_alg_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
|
|
if( sig_alg_list_size + 2 != len ||
|
|
if( sig_alg_list_size + 2 != len ||
|
|
sig_alg_list_size % 2 != 0 )
|
|
sig_alg_list_size % 2 != 0 )
|
|
@@ -273,6 +286,12 @@ static int ssl_parse_supported_elliptic_curves( mbedtls_ssl_context *ssl,
|
|
const unsigned char *p;
|
|
const unsigned char *p;
|
|
const mbedtls_ecp_curve_info *curve_info, **curves;
|
|
const mbedtls_ecp_curve_info *curve_info, **curves;
|
|
|
|
|
|
|
|
+ if ( len < 2 ) {
|
|
|
|
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
|
|
|
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
|
|
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
|
|
|
+ }
|
|
list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
|
|
list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
|
|
if( list_size + 2 != len ||
|
|
if( list_size + 2 != len ||
|
|
list_size % 2 != 0 )
|
|
list_size % 2 != 0 )
|
|
@@ -332,14 +351,14 @@ static int ssl_parse_supported_point_formats( mbedtls_ssl_context *ssl,
|
|
size_t list_size;
|
|
size_t list_size;
|
|
const unsigned char *p;
|
|
const unsigned char *p;
|
|
|
|
|
|
- list_size = buf[0];
|
|
|
|
- if( list_size + 1 != len )
|
|
|
|
|
|
+ if( len == 0 || (size_t)( buf[0] + 1 ) != len )
|
|
{
|
|
{
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
|
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
|
}
|
|
}
|
|
|
|
+ list_size = buf[0];
|
|
|
|
|
|
p = buf + 1;
|
|
p = buf + 1;
|
|
while( list_size > 0 )
|
|
while( list_size > 0 )
|
|
@@ -709,7 +728,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
|
|
MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
|
|
MBEDTLS_SSL_DEBUG_CRT( 3, "candidate certificate chain, certificate",
|
|
cur->cert );
|
|
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" ) );
|
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: key type" ) );
|
|
continue;
|
|
continue;
|
|
@@ -733,7 +752,7 @@ static int ssl_pick_cert( mbedtls_ssl_context *ssl,
|
|
|
|
|
|
#if defined(MBEDTLS_ECDSA_C)
|
|
#if defined(MBEDTLS_ECDSA_C)
|
|
if( pk_alg == MBEDTLS_PK_ECDSA &&
|
|
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" ) );
|
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "certificate mismatch: elliptic curve" ) );
|
|
continue;
|
|
continue;
|
|
@@ -1303,7 +1322,7 @@ read_record_header:
|
|
else
|
|
else
|
|
#endif
|
|
#endif
|
|
{
|
|
{
|
|
- if( msg_len > MBEDTLS_SSL_MAX_CONTENT_LEN )
|
|
|
|
|
|
+ if( msg_len > MBEDTLS_SSL_IN_CONTENT_LEN )
|
|
{
|
|
{
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
|
@@ -1656,10 +1675,16 @@ read_record_header:
|
|
|
|
|
|
while( ext_len != 0 )
|
|
while( ext_len != 0 )
|
|
{
|
|
{
|
|
- unsigned int ext_id = ( ( ext[0] << 8 )
|
|
|
|
- | ( ext[1] ) );
|
|
|
|
- unsigned int ext_size = ( ( ext[2] << 8 )
|
|
|
|
- | ( ext[3] ) );
|
|
|
|
|
|
+ unsigned int ext_id;
|
|
|
|
+ unsigned int ext_size;
|
|
|
|
+ if ( ext_len < 4 ) {
|
|
|
|
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client hello message" ) );
|
|
|
|
+ mbedtls_ssl_send_alert_message( ssl, MBEDTLS_SSL_ALERT_LEVEL_FATAL,
|
|
|
|
+ MBEDTLS_SSL_ALERT_MSG_DECODE_ERROR );
|
|
|
|
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO );
|
|
|
|
+ }
|
|
|
|
+ ext_id = ( ( ext[0] << 8 ) | ( ext[1] ) );
|
|
|
|
+ ext_size = ( ( ext[2] << 8 ) | ( ext[3] ) );
|
|
|
|
|
|
if( ext_size + 4 > ext_len )
|
|
if( ext_size + 4 > ext_len )
|
|
{
|
|
{
|
|
@@ -2235,7 +2260,7 @@ static void ssl_write_ecjpake_kkpp_ext( mbedtls_ssl_context *ssl,
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
unsigned char *p = buf;
|
|
unsigned char *p = buf;
|
|
- const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
|
|
|
|
|
+ const unsigned char *end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
|
size_t kkpp_len;
|
|
size_t kkpp_len;
|
|
|
|
|
|
*olen = 0;
|
|
*olen = 0;
|
|
@@ -2342,7 +2367,7 @@ static int ssl_write_hello_verify_request( mbedtls_ssl_context *ssl )
|
|
cookie_len_byte = p++;
|
|
cookie_len_byte = p++;
|
|
|
|
|
|
if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie,
|
|
if( ( ret = ssl->conf->f_cookie_write( ssl->conf->p_cookie,
|
|
- &p, ssl->out_buf + MBEDTLS_SSL_BUFFER_LEN,
|
|
|
|
|
|
+ &p, ssl->out_buf + MBEDTLS_SSL_OUT_BUFFER_LEN,
|
|
ssl->cli_id, ssl->cli_id_len ) ) != 0 )
|
|
ssl->cli_id, ssl->cli_id_len ) ) != 0 )
|
|
{
|
|
{
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret );
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "f_cookie_write", ret );
|
|
@@ -2638,7 +2663,7 @@ static int ssl_write_certificate_request( mbedtls_ssl_context *ssl )
|
|
size_t dn_size, total_dn_size; /* excluding length bytes */
|
|
size_t dn_size, total_dn_size; /* excluding length bytes */
|
|
size_t ct_len, sa_len; /* including length bytes */
|
|
size_t ct_len, sa_len; /* including length bytes */
|
|
unsigned char *buf, *p;
|
|
unsigned char *buf, *p;
|
|
- const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN;
|
|
|
|
|
|
+ const unsigned char * const end = ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN;
|
|
const mbedtls_x509_crt *crt;
|
|
const mbedtls_x509_crt *crt;
|
|
int authmode;
|
|
int authmode;
|
|
|
|
|
|
@@ -2828,54 +2853,56 @@ static int ssl_get_ecdh_params_from_cert( mbedtls_ssl_context *ssl )
|
|
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
|
|
#endif /* MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) ||
|
|
MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_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_OUT_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 =
|
|
const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
|
ssl->transform_negotiate->ciphersuite_info;
|
|
ssl->transform_negotiate->ciphersuite_info;
|
|
-
|
|
|
|
#if defined(MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED)
|
|
#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)
|
|
#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__WITH_SERVER_SIGNATURE__ENABLED */
|
|
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */
|
|
#endif /* MBEDTLS_KEY_EXCHANGE__SOME_PFS__ENABLED */
|
|
|
|
|
|
- MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write server key exchange" ) );
|
|
|
|
-
|
|
|
|
- /*
|
|
|
|
- *
|
|
|
|
- * 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 */
|
|
|
|
|
|
+ (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 */
|
|
|
|
|
|
- /* 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 */
|
|
|
|
|
|
+ ssl->out_msglen = 4; /* header (type:1, length:3) to be written later */
|
|
|
|
|
|
/*
|
|
/*
|
|
*
|
|
*
|
|
- * Part 2: Provide key exchange parameters for chosen ciphersuite.
|
|
|
|
|
|
+ * Part 1: Provide key exchange parameters for chosen ciphersuite.
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
|
|
|
|
@@ -2885,18 +2912,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
|
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
|
#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
|
|
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE )
|
|
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 = 0;
|
|
|
|
|
|
- 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_OUT_CONTENT_LEN - ssl->out_msglen, &len,
|
|
|
|
+ ssl->conf->f_rng, ssl->conf->p_rng );
|
|
if( ret != 0 )
|
|
if( ret != 0 )
|
|
{
|
|
{
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret );
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecjpake_write_round_two", ret );
|
|
return( ret );
|
|
return( ret );
|
|
}
|
|
}
|
|
|
|
|
|
- p += len;
|
|
|
|
- n += len;
|
|
|
|
|
|
+ ssl->out_msglen += len;
|
|
}
|
|
}
|
|
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
|
|
#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
|
|
|
|
|
|
@@ -2910,10 +2940,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
|
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ||
|
|
if( 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_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 ||
|
|
#endif /* MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED ||
|
|
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
|
|
MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED */
|
|
@@ -2924,6 +2952,9 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
|
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED)
|
|
#if defined(MBEDTLS_KEY_EXCHANGE__SOME__DHE_ENABLED)
|
|
if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) )
|
|
if( mbedtls_ssl_ciphersuite_uses_dhe( ciphersuite_info ) )
|
|
{
|
|
{
|
|
|
|
+ int ret;
|
|
|
|
+ size_t len = 0;
|
|
|
|
+
|
|
if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL )
|
|
if( ssl->conf->dhm_P.p == NULL || ssl->conf->dhm_G.p == NULL )
|
|
{
|
|
{
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) );
|
|
MBEDTLS_SSL_DEBUG_MSG( 1, ( "no DH parameters set" ) );
|
|
@@ -2947,21 +2978,21 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
|
return( ret );
|
|
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 );
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_dhm_make_params", ret );
|
|
return( ret );
|
|
return( ret );
|
|
}
|
|
}
|
|
|
|
|
|
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
|
|
#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
|
|
#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: X ", &ssl->handshake->dhm_ctx.X );
|
|
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P );
|
|
MBEDTLS_SSL_DEBUG_MPI( 3, "DHM: P ", &ssl->handshake->dhm_ctx.P );
|
|
@@ -2986,6 +3017,8 @@ static int ssl_write_server_key_exchange( mbedtls_ssl_context *ssl )
|
|
*/
|
|
*/
|
|
const mbedtls_ecp_curve_info **curve = NULL;
|
|
const mbedtls_ecp_curve_info **curve = NULL;
|
|
const mbedtls_ecp_group_id *gid;
|
|
const mbedtls_ecp_group_id *gid;
|
|
|
|
+ int ret;
|
|
|
|
+ size_t len = 0;
|
|
|
|
|
|
/* Match our preference list against the offered curves */
|
|
/* Match our preference list against the offered curves */
|
|
for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ )
|
|
for( gid = ssl->conf->curve_list; *gid != MBEDTLS_ECP_DP_NONE; gid++ )
|
|
@@ -3009,21 +3042,21 @@ curve_matching_done:
|
|
return( ret );
|
|
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_OUT_CONTENT_LEN - ssl->out_msglen,
|
|
|
|
+ ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 )
|
|
{
|
|
{
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret );
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ecdh_make_params", ret );
|
|
return( ret );
|
|
return( ret );
|
|
}
|
|
}
|
|
|
|
|
|
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
|
|
#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
|
|
#endif
|
|
|
|
|
|
- p += len;
|
|
|
|
- n += len;
|
|
|
|
|
|
+ ssl->out_msglen += len;
|
|
|
|
|
|
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q );
|
|
MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Q ", &ssl->handshake->ecdh_ctx.Q );
|
|
}
|
|
}
|
|
@@ -3031,19 +3064,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.
|
|
* exchange parameters, compute and add the signature here.
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
|
|
#if defined(MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED)
|
|
if( mbedtls_ssl_ciphersuite_uses_server_signature( ciphersuite_info ) )
|
|
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
|
|
* A: For TLS 1.2, obey signature-hash-algorithm extension
|
|
* to choose appropriate hash.
|
|
* to choose appropriate hash.
|
|
* B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1
|
|
* B: For SSL3, TLS1.0, TLS1.1 and ECDHE_ECDSA, use SHA1
|
|
@@ -3090,7 +3124,7 @@ curve_matching_done:
|
|
MBEDTLS_SSL_DEBUG_MSG( 3, ( "pick hash algorithm %d for signing", md_alg ) );
|
|
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) || \
|
|
#if defined(MBEDTLS_SSL_PROTO_SSL3) || defined(MBEDTLS_SSL_PROTO_TLS1) || \
|
|
defined(MBEDTLS_SSL_PROTO_TLS1_1)
|
|
defined(MBEDTLS_SSL_PROTO_TLS1_1)
|
|
@@ -3110,9 +3144,7 @@ curve_matching_done:
|
|
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
|
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
|
if( md_alg != MBEDTLS_MD_NONE )
|
|
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,
|
|
dig_signed_len,
|
|
dig_signed_len,
|
|
md_alg );
|
|
md_alg );
|
|
@@ -3127,18 +3159,11 @@ curve_matching_done:
|
|
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
|
|
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 defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
|
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
|
|
if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 )
|
|
{
|
|
{
|
|
@@ -3158,33 +3183,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 */
|
|
#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 );
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret );
|
|
return( ret );
|
|
return( ret );
|
|
}
|
|
}
|
|
|
|
+ }
|
|
|
|
+#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
|
|
|
|
+
|
|
|
|
+ return( 0 );
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* 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 */
|
|
|
|
|
|
- *(p++) = (unsigned char)( signature_len >> 8 );
|
|
|
|
- *(p++) = (unsigned char)( signature_len );
|
|
|
|
- n += 2;
|
|
|
|
|
|
+ /* 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 */
|
|
|
|
|
|
- MBEDTLS_SSL_DEBUG_BUF( 3, "my signature", p, signature_len );
|
|
|
|
|
|
+#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 );
|
|
|
|
+ }
|
|
|
|
|
|
- n += 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 );
|
|
}
|
|
}
|
|
-#endif /* MBEDTLS_KEY_EXCHANGE__WITH_SERVER_SIGNATURE__ENABLED */
|
|
|
|
|
|
|
|
- /* Done with actual work; add header and send. */
|
|
|
|
|
|
+ /* 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 );
|
|
|
|
|
|
- ssl->out_msglen = 4 + n;
|
|
|
|
|
|
+ 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_msgtype = MBEDTLS_SSL_MSG_HANDSHAKE;
|
|
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE;
|
|
ssl->out_msg[0] = MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE;
|
|
|
|
|
|
@@ -3197,7 +3339,6 @@ curve_matching_done:
|
|
}
|
|
}
|
|
|
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "<= write server key exchange" ) );
|
|
-
|
|
|
|
return( 0 );
|
|
return( 0 );
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3272,33 +3413,59 @@ static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char *
|
|
|
|
|
|
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
|
|
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
|
|
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_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;
|
|
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) || \
|
|
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
|
|
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
|
defined(MBEDTLS_SSL_PROTO_TLS1_2)
|
|
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
|
|
if( ssl->minor_ver != MBEDTLS_SSL_MINOR_VERSION_0 )
|
|
{
|
|
{
|
|
|
|
+ if ( p + 2 > end ) {
|
|
|
|
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange message" ) );
|
|
|
|
+ return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
|
|
|
|
+ }
|
|
if( *p++ != ( ( len >> 8 ) & 0xFF ) ||
|
|
if( *p++ != ( ( len >> 8 ) & 0xFF ) ||
|
|
*p++ != ( ( len ) & 0xFF ) )
|
|
*p++ != ( ( len ) & 0xFF ) )
|
|
{
|
|
{
|
|
@@ -3314,30 +3481,120 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
|
|
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
|
|
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,
|
|
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
|
|
* Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
|
|
* must not cause the connection to end immediately; instead, send a
|
|
* must not cause the connection to end immediately; instead, send a
|
|
* bad_record_mac later in the handshake.
|
|
* 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 ) );
|
|
ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) );
|
|
if( ret != 0 )
|
|
if( ret != 0 )
|
|
|
|
+ {
|
|
|
|
+ /* It's ok to abort on an RNG failure, since this does not reveal
|
|
|
|
+ * anything about the RSA decryption. */
|
|
return( ret );
|
|
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 defined(MBEDTLS_SSL_DEBUG_ALL)
|
|
if( diff != 0 )
|
|
if( diff != 0 )
|
|
@@ -3352,18 +3609,8 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
|
|
}
|
|
}
|
|
ssl->handshake->pmslen = 48;
|
|
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++ )
|
|
for( i = 0; i < ssl->handshake->pmslen; i++ )
|
|
pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] );
|
|
pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] );
|
|
|
|
|
|
@@ -3445,6 +3692,20 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
|
|
|
|
|
|
MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> parse client key exchange" ) );
|
|
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 )
|
|
if( ( ret = mbedtls_ssl_read_record( ssl ) ) != 0 )
|
|
{
|
|
{
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_read_record", ret );
|
|
@@ -3557,6 +3818,19 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl )
|
|
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
|
|
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
|
|
if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK )
|
|
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 )
|
|
if( ( ret = ssl_parse_client_psk_identity( ssl, &p, end ) ) != 0 )
|
|
{
|
|
{
|
|
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
|
|
MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_client_psk_identity" ), ret );
|
|
@@ -3926,7 +4200,7 @@ static int ssl_write_new_session_ticket( mbedtls_ssl_context *ssl )
|
|
if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket,
|
|
if( ( ret = ssl->conf->f_ticket_write( ssl->conf->p_ticket,
|
|
ssl->session_negotiate,
|
|
ssl->session_negotiate,
|
|
ssl->out_msg + 10,
|
|
ssl->out_msg + 10,
|
|
- ssl->out_msg + MBEDTLS_SSL_MAX_CONTENT_LEN,
|
|
|
|
|
|
+ ssl->out_msg + MBEDTLS_SSL_OUT_CONTENT_LEN,
|
|
&tlen, &lifetime ) ) != 0 )
|
|
&tlen, &lifetime ) ) != 0 )
|
|
{
|
|
{
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret );
|
|
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_ticket_write", ret );
|