From 807d74a062f79eb7196f56c967357ccaf9d663b4 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Mon, 30 Apr 2018 10:30:49 +0200 Subject: [PATCH] SSL async callback: cert is not always from mbedtls_ssl_conf_own_cert The certificate passed to async callbacks may not be the one set by mbedtls_ssl_conf_own_cert. For example, when using an SNI callback, it's whatever the callback is using. Document this, and add a test case (and code sample) with SNI. --- include/mbedtls/ssl.h | 14 ++++++++++---- programs/ssl/ssl_server2.c | 25 ++++++++++++++++++++++--- tests/ssl-opt.sh | 14 ++++++++++++++ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 097b86a3c..b199e2ea6 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -601,9 +601,12 @@ typedef struct mbedtls_ssl_flight_item mbedtls_ssl_flight_item; * \param ssl The SSL connection instance. It should not be * modified other than via mbedtls_ssl_async_set_data(). * \param cert Certificate containing the public key. - * This is one of the pointers passed to + * In simple cases, this is one of the pointers passed to * mbedtls_ssl_conf_own_cert() when configuring the SSL - * connection. + * 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. @@ -665,9 +668,12 @@ typedef int mbedtls_ssl_async_sign_t( mbedtls_ssl_context *ssl, * \param ssl The SSL connection instance. It should not be * modified other than via mbedtls_ssl_async_set_data(). * \param cert Certificate containing the public key. - * This is one of the pointers passed to + * In simple cases, this is one of the pointers passed to * mbedtls_ssl_conf_own_cert() when configuring the SSL - * connection. + * 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. diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 838f41d7c..b1f2382cb 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -204,7 +204,7 @@ int main( void ) #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\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)" @@ -897,7 +897,7 @@ typedef enum { typedef struct { - ssl_async_key_slot_t slots[2]; + ssl_async_key_slot_t slots[3]; /* key, key2, sni */ size_t slots_used; ssl_async_inject_error_t inject_error; int (*f_rng)(void *, unsigned char *, size_t); @@ -965,7 +965,9 @@ static int ssl_async_start( mbedtls_ssl_context *ssl, for( slot = 0; slot < config_data->slots_used; slot++ ) { - if( config_data->slots[slot].cert == cert ) + if( memcmp( &config_data->slots[slot].cert->pk, + &cert->pk, + sizeof( cert->pk ) ) == 0 ) break; } if( slot == config_data->slots_used ) @@ -2376,7 +2378,24 @@ int main( int argc, char *argv[] ) #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 ) + { + ret = ssl_async_set_key( &ssl_async_keys, + sni_info->cert, sni_info->key, + opt.async_private_delay2 ); + if( ret < 0 ) + { + mbedtls_printf( " Test error: ssl_async_set_key failed (%d)\n", + ret ); + goto exit; + } + sni_info->key = NULL; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + } #endif #if defined(MBEDTLS_ECP_C) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 597a5f1c1..6afca2d12 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -4112,6 +4112,20 @@ run_test "SSL async private: sign, RSA, TLS 1.1" \ -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 \