From 862cde5b8e728c78e52767b642d6783e22ec3dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Wed, 17 May 2017 11:56:15 +0200 Subject: [PATCH] Add restart support for ECDSA client auth --- include/mbedtls/ssl_internal.h | 6 +++++- library/ssl_cli.c | 34 +++++++++++++++++++++++++++++++--- library/ssl_tls.c | 8 ++++++++ tests/ssl-opt.sh | 30 ++++++++++++++++++++---------- 4 files changed, 64 insertions(+), 14 deletions(-) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index 20e443630..af8728d5c 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -88,7 +88,7 @@ #endif /* MBEDTLS_SSL_PROTO_TLS1_1 */ #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ -/* Shorthand for restartable */ +/* Shorthand for restartable ECC */ #if defined(MBEDTLS_ECP_RESTARTABLE) && \ defined(MBEDTLS_SSL_CLI_C) && \ defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ @@ -227,10 +227,14 @@ struct mbedtls_ssl_handshake_params #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + int ec_restart_enabled; /*!< Handshake supports EC restart? */ + mbedtls_ecdsa_restart_ctx rs_ctx; /*!< ECDSA restart context */ enum { ssl_ecrs_init = 0, /*!< just getting started */ ssl_ecrs_ecdh_public_done, /*!< wrote ECDHE public share */ ssl_ecrs_ecdh_completed, /*!< completed ECDHE key exchange */ + ssl_ecrs_keys_derived, /*!< ssl_derive_keys() done */ + ssl_ecrs_pk_sign_done, /*!< done writing CertificateVerify */ } ecrs_state; /*!< state for restartable ECC */ size_t ecrs_n; /*!< place for seving a length */ #endif diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 8d7bc45ce..77d376beb 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -1715,6 +1715,14 @@ static int ssl_parse_server_hello( mbedtls_ssl_context *ssl ) } } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( suite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) + { + ssl->handshake->ec_restart_enabled = 1; + } +#endif + if( comp != MBEDTLS_SSL_COMPRESS_NULL #if defined(MBEDTLS_ZLIB_SUPPORT) && comp != MBEDTLS_SSL_COMPRESS_DEFLATE @@ -3114,15 +3122,26 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) unsigned char *hash_start = hash; mbedtls_md_type_t md_alg = MBEDTLS_MD_NONE; unsigned int hashlen; + void *rs_ctx = NULL; MBEDTLS_SSL_DEBUG_MSG( 2, ( "=> write certificate verify" ) ); +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ecrs_state == ssl_ecrs_keys_derived ) + goto keys_derived; +#endif + if( ( ret = mbedtls_ssl_derive_keys( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_derive_keys", ret ); return( ret ); } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + ssl->handshake->ecrs_state++; + +keys_derived: +#endif if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK || @@ -3226,14 +3245,24 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } - if( ( ret = mbedtls_pk_sign( mbedtls_ssl_own_key( ssl ), md_alg, hash_start, hashlen, +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + if( ssl->handshake->ec_restart_enabled ) + rs_ctx = &ssl->handshake->rs_ctx; +#endif + + if( ( ret = mbedtls_pk_sign_restartable( mbedtls_ssl_own_key( ssl ), + md_alg, hash_start, hashlen, ssl->out_msg + 6 + offset, &n, - ssl->conf->f_rng, ssl->conf->p_rng ) ) != 0 ) + ssl->conf->f_rng, ssl->conf->p_rng, rs_ctx ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_pk_sign", ret ); return( ret ); } +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + ssl->handshake->ecrs_state++; +#endif + ssl->out_msg[4 + offset] = (unsigned char)( n >> 8 ); ssl->out_msg[5 + offset] = (unsigned char)( n ); @@ -3242,7 +3271,6 @@ static int ssl_write_certificate_verify( mbedtls_ssl_context *ssl ) ssl->out_msg[0] = MBEDTLS_SSL_HS_CERTIFICATE_VERIFY; ssl->state++; - if( ( ret = mbedtls_ssl_write_record( ssl ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_write_record", ret ); diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 661ae7065..50222c375 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -5472,6 +5472,10 @@ static void ssl_handshake_params_init( mbedtls_ssl_handshake_params *handshake ) #endif #endif +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + mbedtls_ecdsa_restart_init( &handshake->rs_ctx ); +#endif + #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) handshake->sni_authmode = MBEDTLS_SSL_VERIFY_UNSET; #endif @@ -7304,6 +7308,10 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_handshake_params *handshake ) } #endif /* MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#if defined(MBEDTLS_SSL__ECP_RESTARTABLE) + mbedtls_ecdsa_restart_free( &handshake->rs_ctx ); +#endif + #if defined(MBEDTLS_SSL_PROTO_DTLS) mbedtls_free( handshake->verify_cookie ); mbedtls_free( handshake->hs_msg ); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 05e882249..b960df099 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -3445,43 +3445,53 @@ run_test "Large packet TLS 1.2 AEAD shorter tag" \ requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, default" \ - "$P_SRV" \ + "$P_SRV auth_mode=required" \ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1" \ 0 \ - -C "mbedtls_ecdh_make_public.*4b80" + -C "mbedtls_ecdh_make_public.*4b80" \ + -C "mbedtls_pk_sign.*4b80" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, max_ops=0" \ - "$P_SRV" \ + "$P_SRV auth_mode=required" \ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=0" \ 0 \ - -C "mbedtls_ecdh_make_public.*4b80" + -C "mbedtls_ecdh_make_public.*4b80" \ + -C "mbedtls_pk_sign.*4b80" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, max_ops=65535" \ - "$P_SRV" \ + "$P_SRV auth_mode=required" \ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=65535" \ 0 \ - -C "mbedtls_ecdh_make_public.*4b80" + -C "mbedtls_ecdh_make_public.*4b80" \ + -C "mbedtls_pk_sign.*4b80" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: TLS, max_ops=1000" \ - "$P_SRV" \ + "$P_SRV auth_mode=required" \ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ debug_level=1 ec_max_ops=1000" \ 0 \ - -c "mbedtls_ecdh_make_public.*4b80" + -c "mbedtls_ecdh_make_public.*4b80" \ + -c "mbedtls_pk_sign.*4b80" requires_config_enabled MBEDTLS_ECP_RESTARTABLE run_test "EC restart: DTLS, max_ops=1000" \ - "$P_SRV dtls=1" \ + "$P_SRV auth_mode=required dtls=1" \ "$P_CLI force_ciphersuite=TLS-ECDHE-ECDSA-WITH-AES-128-GCM-SHA256 \ + key_file=data_files/server5.key crt_file=data_files/server5.crt \ dtls=1 debug_level=1 ec_max_ops=1000" \ 0 \ - -c "mbedtls_ecdh_make_public.*4b80" + -c "mbedtls_ecdh_make_public.*4b80" \ + -c "mbedtls_pk_sign.*4b80" # Tests for DTLS HelloVerifyRequest