From 19b80f8151c861138461e5ea31841d15d968f5c4 Mon Sep 17 00:00:00 2001 From: Przemek Stekiel Date: Thu, 14 Apr 2022 08:29:31 +0200 Subject: [PATCH] Enable support for psa opaque ECDHE-PSK key exchange on the client side Signed-off-by: Przemek Stekiel --- library/ssl_tls.c | 30 ++++++++++++++-------- library/ssl_tls12_client.c | 52 +++++++++++++++++++++----------------- programs/ssl/ssl_client2.c | 8 +++--- 3 files changed, 54 insertions(+), 36 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index df6a793cf..c60a8562c 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -5093,11 +5093,13 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, } #endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ - ( defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) ) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + ( defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) ) if( ( handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK || - handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) && + handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK || + handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) && ssl_use_opaque_psk( ssl ) == 1 ) { /* Perform PSK-to-MS expansion in a single step. */ @@ -5120,15 +5122,23 @@ static int ssl_compute_master( mbedtls_ssl_handshake_params *handshake, size_t other_secret_len = 0; unsigned char* other_secret = NULL; - if ( handshake->ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) + switch( handshake->ciphersuite_info->key_exchange ) { - /* Provide other key as other secret. - * For RSA-PKS other key length is always 48 bytes. + /* Provide other secret. * Other secret is stored in premaster, where first 2 bytes hold the - * length of the other key. Skip them. + * length of the other key. */ - other_secret_len = 48; - other_secret = handshake->premaster + 2; + case MBEDTLS_KEY_EXCHANGE_RSA_PSK: + /* For RSA-PKS other key length is always 48 bytes. */ + other_secret_len = 48; + other_secret = handshake->premaster + 2; + break; + case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK: + other_secret_len = MBEDTLS_GET_UINT16_BE(handshake->premaster, 0); + other_secret = handshake->premaster + 2; + break; + default: + break; } status = setup_psa_key_derivation( &derivation, psk, alg, diff --git a/library/ssl_tls12_client.c b/library/ssl_tls12_client.c index aaffcd33f..2868a84dc 100644 --- a/library/ssl_tls12_client.c +++ b/library/ssl_tls12_client.c @@ -2959,10 +2959,6 @@ ecdh_calc_secret: * ciphersuites we offered, so this should never happen. */ return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - /* Opaque PSKs are currently only supported for PSK-only suites. */ - if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) - return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); - /* uint16 to store content length */ const size_t content_len_size = 2; @@ -3068,30 +3064,40 @@ ecdh_calc_secret: MBEDTLS_PUT_UINT16_BE( zlen, pms, 0 ); pms += zlen_size + zlen; - const unsigned char *psk = NULL; - size_t psk_len = 0; + /* In case of opaque psk skip writting psk to pms. + * Opaque key will be handled later. */ + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 1 ) + { + const unsigned char *psk = NULL; + size_t psk_len = 0; - if( mbedtls_ssl_get_psk( ssl, &psk, &psk_len ) - == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ) - /* - * This should never happen because the existence of a PSK is always - * checked before calling this function - */ - return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); + if( mbedtls_ssl_get_psk( ssl, &psk, &psk_len ) + == MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ) + /* + * This should never happen because the existence of a PSK is always + * checked before calling this function + */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); - /* opaque psk<0..2^16-1>; */ - if( (size_t)( pms_end - pms ) < ( 2 + psk_len ) ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + /* opaque psk<0..2^16-1>; */ + if( (size_t)( pms_end - pms ) < ( 2 + psk_len ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - /* Write the PSK length as uint16 */ - MBEDTLS_PUT_UINT16_BE( psk_len, pms, 0 ); - pms += 2; + /* Write the PSK length as uint16 */ + MBEDTLS_PUT_UINT16_BE( psk_len, pms, 0 ); + pms += 2; - /* Write the PSK itself */ - memcpy( pms, psk, psk_len ); - pms += psk_len; + /* Write the PSK itself */ + memcpy( pms, psk, psk_len ); + pms += psk_len; - ssl->handshake->pmslen = pms - ssl->handshake->premaster; + ssl->handshake->pmslen = pms - ssl->handshake->premaster; + } + else + { + MBEDTLS_SSL_DEBUG_MSG( 1, + ( "skip PMS generation for opaque ECDHE-PSK" ) ); + } } else #endif /* MBEDTLS_USE_PSA_CRYPTO && diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 66cf622aa..5ab13bee7 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -1406,11 +1406,13 @@ int main( int argc, char *argv[] ) #if defined (MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED) if( opt.psk_opaque != 0 ) { - /* Ensure that the chosen ciphersuite is PSK-only or rsa-psk; we must know - * the ciphersuite in advance to set the correct policy for the + /* Ensure that the chosen ciphersuite is PSK-only, rsa-psk + or ecdhe-psk; we must know the ciphersuite in + advance to set the correct policy for the * PSK key slot. This limitation might go away in the future. */ 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_RSA_PSK && + ciphersuite_info->key_exchange != MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) || opt.min_version != MBEDTLS_SSL_MINOR_VERSION_3 ) { mbedtls_printf( "opaque PSKs are only supported in conjunction \