diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 3f48377b6..7751560f2 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -3899,6 +3899,23 @@ void mbedtls_ssl_conf_sni( mbedtls_ssl_config *conf, int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, const unsigned char *pw, size_t pw_len ); + +/** + * \brief Set the EC J-PAKE opaque password for current handshake. + * + * \note The key must remain valid until the handshake is over. + * + * \note The SSL context needs to be already set up. The right place + * to call this function is between \c mbedtls_ssl_setup() or + * \c mbedtls_ssl_reset() and \c mbedtls_ssl_handshake(). + * + * \param ssl SSL context + * \param pwd EC J-PAKE opaque password + * + * \return 0 on success, or a negative error code. + */ +int mbedtls_ssl_set_hs_ecjpake_password_opaque( mbedtls_ssl_context *ssl, + mbedtls_svc_key_id_t pwd ); #endif /*MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 9bb9dc23c..b75761317 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1863,27 +1863,55 @@ void mbedtls_ssl_set_verify( mbedtls_ssl_context *ssl, #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) -/* - * Set EC J-PAKE password for current handshake - */ -#if defined(MBEDTLS_USE_PSA_CRYPTO) -int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, - const unsigned char *pw, - size_t pw_len ) -{ - psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); - psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; - psa_pake_role_t psa_role; - psa_status_t status; - if( ssl->handshake == NULL || ssl->conf == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static psa_status_t mbedtls_ssl_set_hs_ecjpake_password_common( + mbedtls_ssl_context *ssl, + mbedtls_svc_key_id_t pwd ) +{ + psa_status_t status; + psa_pake_role_t psa_role; + psa_pake_cipher_suite_t cipher_suite = psa_pake_cipher_suite_init(); + + psa_pake_cs_set_algorithm( &cipher_suite, PSA_ALG_JPAKE ); + psa_pake_cs_set_primitive( &cipher_suite, + PSA_PAKE_PRIMITIVE( PSA_PAKE_PRIMITIVE_TYPE_ECC, + PSA_ECC_FAMILY_SECP_R1, + 256) ); + psa_pake_cs_set_hash( &cipher_suite, PSA_ALG_SHA_256 ); + + status = psa_pake_setup( &ssl->handshake->psa_pake_ctx, &cipher_suite ); + if( status != PSA_SUCCESS ) + return status; if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) psa_role = PSA_PAKE_ROLE_SERVER; else psa_role = PSA_PAKE_ROLE_CLIENT; + status = psa_pake_set_role( &ssl->handshake->psa_pake_ctx, psa_role ); + if( status != PSA_SUCCESS ) + return status; + + status = psa_pake_set_password_key( &ssl->handshake->psa_pake_ctx, pwd ); + if( status != PSA_SUCCESS ) + return status; + + ssl->handshake->psa_pake_ctx_is_ok = 1; + + return ( PSA_SUCCESS ); +} + +int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, + const unsigned char *pw, + size_t pw_len ) +{ + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_status_t status; + + if( ssl->handshake == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + /* Empty password is not valid */ if( ( pw == NULL) || ( pw_len == 0 ) ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); @@ -1897,21 +1925,8 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, if( status != PSA_SUCCESS ) return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - psa_pake_cs_set_algorithm( &cipher_suite, PSA_ALG_JPAKE ); - psa_pake_cs_set_primitive( &cipher_suite, - PSA_PAKE_PRIMITIVE( PSA_PAKE_PRIMITIVE_TYPE_ECC, - PSA_ECC_FAMILY_SECP_R1, - 256) ); - psa_pake_cs_set_hash( &cipher_suite, PSA_ALG_SHA_256 ); - - status = psa_pake_setup( &ssl->handshake->psa_pake_ctx, &cipher_suite ); - if( status != PSA_SUCCESS ) - { - psa_destroy_key( ssl->handshake->psa_pake_password ); - return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); - } - - status = psa_pake_set_role( &ssl->handshake->psa_pake_ctx, psa_role ); + status = mbedtls_ssl_set_hs_ecjpake_password_common( ssl, + ssl->handshake->psa_pake_password ); if( status != PSA_SUCCESS ) { psa_destroy_key( ssl->handshake->psa_pake_password ); @@ -1919,17 +1934,27 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); } - psa_pake_set_password_key( &ssl->handshake->psa_pake_ctx, - ssl->handshake->psa_pake_password ); + return( 0 ); +} + +int mbedtls_ssl_set_hs_ecjpake_password_opaque( mbedtls_ssl_context *ssl, + mbedtls_svc_key_id_t pwd ) +{ + psa_status_t status; + + if( ssl->handshake == NULL || ssl->conf == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + if( mbedtls_svc_key_id_is_null( pwd ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + status = mbedtls_ssl_set_hs_ecjpake_password_common( ssl, pwd ); if( status != PSA_SUCCESS ) { - psa_destroy_key( ssl->handshake->psa_pake_password ); psa_pake_abort( &ssl->handshake->psa_pake_ctx ); return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); } - ssl->handshake->psa_pake_ctx_is_ok = 1; - return( 0 ); } #else /* MBEDTLS_USE_PSA_CRYPTO */ @@ -1942,6 +1967,10 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, if( ssl->handshake == NULL || ssl->conf == NULL ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + /* Empty password is not valid */ + if( ( pw == NULL) || ( pw_len == 0 ) ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( ssl->conf->endpoint == MBEDTLS_SSL_IS_SERVER ) role = MBEDTLS_ECJPAKE_SERVER; else @@ -3996,7 +4025,15 @@ void mbedtls_ssl_handshake_free( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_pake_abort( &handshake->psa_pake_ctx ); - psa_destroy_key( handshake->psa_pake_password ); + /* + * Opaque keys are not stored in the handshake's data and it's the user + * responsibility to destroy them. Clear ones, instead, are created by + * the TLS library and should be destroyed at the same level + */ + if( ! mbedtls_svc_key_id_is_null( handshake->psa_pake_password ) ) + { + psa_destroy_key( handshake->psa_pake_password ); + } handshake->psa_pake_password = MBEDTLS_SVC_KEY_ID_INIT; #else mbedtls_ecjpake_free( &handshake->ecjpake_ctx ); diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 6aa295d66..02ee7cf69 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -68,6 +68,7 @@ int main( void ) #define DFL_PSK_OPAQUE 0 #define DFL_PSK_IDENTITY "Client_identity" #define DFL_ECJPAKE_PW NULL +#define DFL_ECJPAKE_PW_OPAQUE 0 #define DFL_EC_MAX_OPS -1 #define DFL_FORCE_CIPHER 0 #define DFL_TLS1_3_KEX_MODES MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL @@ -318,11 +319,17 @@ int main( void ) #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) #define USAGE_ECJPAKE \ - " ecjpake_pw=%%s default: none (disabled)\n" -#else + " ecjpake_pw=%%s default: none (disabled)\n" \ + " ecjpake_pw_opaque=%%d default: 0 (disabled)\n" +#else /* MBEDTLS_USE_PSA_CRYPTO */ +#define USAGE_ECJPAKE \ + " ecjpake_pw=%%s default: none (disabled)\n" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#else /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #define USAGE_ECJPAKE "" -#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_ECP_RESTARTABLE) #define USAGE_ECRESTART \ @@ -492,6 +499,9 @@ struct options const char *psk; /* the pre-shared key */ const char *psk_identity; /* the pre-shared key identity */ const char *ecjpake_pw; /* the EC J-PAKE password */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + int ecjpake_pw_opaque; /* set to 1 to use the opaque method for setting the password */ +#endif int ec_max_ops; /* EC consecutive operations limit */ int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) @@ -824,6 +834,10 @@ int main( int argc, char *argv[] ) MBEDTLS_TLS_SRTP_UNSET }; #endif /* MBEDTLS_SSL_DTLS_SRTP */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_svc_key_id_t ecjpake_pw_slot = MBEDTLS_SVC_KEY_ID_INIT; /* ecjpake password key slot */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) ); @@ -919,6 +933,9 @@ int main( int argc, char *argv[] ) #endif opt.psk_identity = DFL_PSK_IDENTITY; opt.ecjpake_pw = DFL_ECJPAKE_PW; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + opt.ecjpake_pw_opaque = DFL_ECJPAKE_PW_OPAQUE; +#endif opt.ec_max_ops = DFL_EC_MAX_OPS; opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) @@ -1094,6 +1111,10 @@ int main( int argc, char *argv[] ) opt.psk_identity = q; else if( strcmp( p, "ecjpake_pw" ) == 0 ) opt.ecjpake_pw = q; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + else if( strcmp( p, "ecjpake_pw_opaque" ) == 0 ) + opt.ecjpake_pw_opaque = atoi( q ); +#endif else if( strcmp( p, "ec_max_ops" ) == 0 ) opt.ec_max_ops = atoi( q ); else if( strcmp( p, "force_ciphersuite" ) == 0 ) @@ -2166,16 +2187,46 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if( opt.ecjpake_pw != DFL_ECJPAKE_PW ) { - if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl, - (const unsigned char *) opt.ecjpake_pw, - strlen( opt.ecjpake_pw ) ) ) != 0 ) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ( opt.ecjpake_pw_opaque != DFL_ECJPAKE_PW_OPAQUE ) { - mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", - ret ); - goto exit; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE ); + psa_set_key_algorithm( &attributes, PSA_ALG_JPAKE ); + psa_set_key_type( &attributes, PSA_KEY_TYPE_PASSWORD ); + + status = psa_import_key( &attributes, + (const unsigned char *) opt.ecjpake_pw, + strlen( opt.ecjpake_pw ), + &ecjpake_pw_slot ); + if( status != PSA_SUCCESS ) + { + mbedtls_printf( " failed\n ! psa_import_key returned %d\n\n", + status ); + goto exit; + } + if( ( ret = mbedtls_ssl_set_hs_ecjpake_password_opaque( &ssl, + ecjpake_pw_slot ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password_opaque returned %d\n\n", ret ); + goto exit; + } + mbedtls_printf( "using opaque password\n"); + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { + if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl, + (const unsigned char *) opt.ecjpake_pw, + strlen( opt.ecjpake_pw ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret ); + goto exit; + } } } -#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) if( opt.context_crt_cb == 1 ) @@ -3276,6 +3327,31 @@ exit: #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED && MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + /* + * In case opaque keys it's the user responsibility to keep the key valid + * for the duration of the handshake and destroy it at the end + */ + if( ( opt.ecjpake_pw_opaque != DFL_ECJPAKE_PW_OPAQUE ) ) + { + psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT; + + /* Verify that the key is still valid before destroying it */ + if( psa_get_key_attributes( ecjpake_pw_slot, &check_attributes ) != + PSA_SUCCESS ) + { + if( ret == 0 ) + ret = 1; + mbedtls_printf( "The EC J-PAKE password key has unexpectedly been already destroyed\n" ); + } + else + { + psa_destroy_key( ecjpake_pw_slot ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO */ + #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) const char* message = mbedtls_test_helper_is_psa_leaking(); if( message ) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 00624b565..802beb2f4 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -98,6 +98,7 @@ int main( void ) #define DFL_PSK_LIST_OPAQUE 0 #define DFL_PSK_IDENTITY "Client_identity" #define DFL_ECJPAKE_PW NULL +#define DFL_ECJPAKE_PW_OPAQUE 0 #define DFL_PSK_LIST NULL #define DFL_FORCE_CIPHER 0 #define DFL_TLS1_3_KEX_MODES MBEDTLS_SSL_TLS1_3_KEY_EXCHANGE_MODE_ALL @@ -419,11 +420,17 @@ int main( void ) #endif #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) #define USAGE_ECJPAKE \ - " ecjpake_pw=%%s default: none (disabled)\n" -#else + " ecjpake_pw=%%s default: none (disabled)\n" \ + " ecjpake_pw_opaque=%%d default: 0 (disabled)\n" +#else /* MBEDTLS_USE_PSA_CRYPTO */ +#define USAGE_ECJPAKE \ + " ecjpake_pw=%%s default: none (disabled)\n" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#else /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #define USAGE_ECJPAKE "" -#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_EARLY_DATA) #define USAGE_EARLY_DATA \ @@ -631,6 +638,9 @@ struct options const char *psk_identity; /* the pre-shared key identity */ char *psk_list; /* list of PSK id/key pairs for callback */ const char *ecjpake_pw; /* the EC J-PAKE password */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + int ecjpake_pw_opaque; /* set to 1 to use the opaque method for setting the password */ +#endif int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */ #if defined(MBEDTLS_SSL_PROTO_TLS1_3) int tls13_kex_modes; /* supported TLS 1.3 key exchange modes */ @@ -1517,6 +1527,10 @@ int main( int argc, char *argv[] ) unsigned char *context_buf = NULL; size_t context_buf_len = 0; #endif +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + mbedtls_svc_key_id_t ecjpake_pw_slot = MBEDTLS_SVC_KEY_ID_INIT; /* ecjpake password key slot */ +#endif /* MBEDTLS_USE_PSA_CRYPTO && MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_HANDSHAKE_WITH_CERT_ENABLED) uint16_t sig_alg_list[SIG_ALG_LIST_SIZE]; @@ -1675,6 +1689,9 @@ int main( int argc, char *argv[] ) opt.psk_identity = DFL_PSK_IDENTITY; opt.psk_list = DFL_PSK_LIST; opt.ecjpake_pw = DFL_ECJPAKE_PW; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + opt.ecjpake_pw_opaque = DFL_ECJPAKE_PW_OPAQUE; +#endif opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; #if defined(MBEDTLS_SSL_PROTO_TLS1_3) opt.tls13_kex_modes = DFL_TLS1_3_KEX_MODES; @@ -1879,6 +1896,10 @@ int main( int argc, char *argv[] ) opt.psk_list = q; else if( strcmp( p, "ecjpake_pw" ) == 0 ) opt.ecjpake_pw = q; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + else if( strcmp( p, "ecjpake_pw_opaque" ) == 0 ) + opt.ecjpake_pw_opaque = atoi( q ); +#endif else if( strcmp( p, "force_ciphersuite" ) == 0 ) { opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q ); @@ -3528,15 +3549,46 @@ reset: #if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) if( opt.ecjpake_pw != DFL_ECJPAKE_PW ) { - if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl, - (const unsigned char *) opt.ecjpake_pw, - strlen( opt.ecjpake_pw ) ) ) != 0 ) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if ( opt.ecjpake_pw_opaque != DFL_ECJPAKE_PW_OPAQUE ) { - mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret ); - goto exit; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE ); + psa_set_key_algorithm( &attributes, PSA_ALG_JPAKE ); + psa_set_key_type( &attributes, PSA_KEY_TYPE_PASSWORD ); + + status = psa_import_key( &attributes, + (const unsigned char *) opt.ecjpake_pw, + strlen( opt.ecjpake_pw ), + &ecjpake_pw_slot ); + if( status != PSA_SUCCESS ) + { + mbedtls_printf( " failed\n ! psa_import_key returned %d\n\n", + status ); + goto exit; + } + if( ( ret = mbedtls_ssl_set_hs_ecjpake_password_opaque( &ssl, + ecjpake_pw_slot ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password_opaque returned %d\n\n", ret ); + goto exit; + } + mbedtls_printf( "using opaque password\n"); + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + { + if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl, + (const unsigned char *) opt.ecjpake_pw, + strlen( opt.ecjpake_pw ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret ); + goto exit; + } } } -#endif +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) #if defined(MBEDTLS_KEY_EXCHANGE_CERT_REQ_ALLOWED_ENABLED) @@ -4422,6 +4474,31 @@ exit: #endif /* MBEDTLS_SSL_HANDSHAKE_WITH_PSK_ENABLED && MBEDTLS_USE_PSA_CRYPTO */ +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + /* + * In case opaque keys it's the user responsibility to keep the key valid + * for the duration of the handshake and destroy it at the end + */ + if( ( opt.ecjpake_pw_opaque != DFL_ECJPAKE_PW_OPAQUE ) ) + { + psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT; + + /* Verify that the key is still valid before destroying it */ + if( psa_get_key_attributes( ecjpake_pw_slot, &check_attributes ) != + PSA_SUCCESS ) + { + if( ret == 0 ) + ret = 1; + mbedtls_printf( "The EC J-PAKE password key has unexpectedly been already destroyed\n" ); + } + else + { + psa_destroy_key( ecjpake_pw_slot ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED && MBEDTLS_USE_PSA_CRYPTO */ + #if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_SSL_PROTO_TLS1_3) const char* message = mbedtls_test_helper_is_psa_leaking(); if( message ) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index db46b0387..cc630cef0 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1457,10 +1457,14 @@ component_test_tls1_2_ecjpake_compatibility() { make -C programs ssl/ssl_server2 ssl/ssl_client2 make -C programs test/udp_proxy test/query_compile_time_config - msg "test: server w/o USE_PSA - client w/ USE_PSA" - P_SRV=../s2_no_use_psa tests/ssl-opt.sh -f ECJPAKE - msg "test: client w/o USE_PSA - server w/ USE_PSA" - P_CLI=../c2_no_use_psa tests/ssl-opt.sh -f ECJPAKE + msg "test: server w/o USE_PSA - client w/ USE_PSA, text password" + P_SRV=../s2_no_use_psa tests/ssl-opt.sh -f "ECJPAKE: working, TLS" + msg "test: server w/o USE_PSA - client w/ USE_PSA, opaque password" + P_SRV=../s2_no_use_psa tests/ssl-opt.sh -f "ECJPAKE: opaque password client only, working, TLS" + msg "test: client w/o USE_PSA - server w/ USE_PSA, text password" + P_CLI=../c2_no_use_psa tests/ssl-opt.sh -f "ECJPAKE: working, TLS" + msg "test: client w/o USE_PSA - server w/ USE_PSA, opaque password" + P_CLI=../c2_no_use_psa tests/ssl-opt.sh -f "ECJPAKE: opaque password server only, working, TLS" rm s2_no_use_psa c2_no_use_psa } diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 1fe8baeb6..ea57b2599 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -7986,6 +7986,8 @@ run_test "ECJPAKE: server not configured" \ -C "found ecjpake_kkpp extension" \ -s "SSL - The handshake negotiation failed" +# Note: if the name of this test is changed, then please adjust the corresponding +# filtering label in "test_tls1_2_ecjpake_compatibility" (in "all.sh") requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "ECJPAKE: working, TLS" \ @@ -8004,6 +8006,73 @@ run_test "ECJPAKE: working, TLS" \ -S "SSL - The handshake negotiation failed" \ -S "SSL - Verification of the message MAC failed" +requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "ECJPAKE: opaque password client+server, working, TLS" \ + "$P_SRV debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1" \ + "$P_CLI debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1\ + force_ciphersuite=TLS-ECJPAKE-WITH-AES-128-CCM-8" \ + 0 \ + -c "add ciphersuite: c0ff" \ + -c "adding ecjpake_kkpp extension" \ + -c "using opaque password" \ + -s "using opaque password" \ + -C "re-using cached ecjpake parameters" \ + -s "found ecjpake kkpp extension" \ + -S "skip ecjpake kkpp extension" \ + -S "ciphersuite mismatch: ecjpake not configured" \ + -s "server hello, ecjpake kkpp extension" \ + -c "found ecjpake_kkpp extension" \ + -S "SSL - The handshake negotiation failed" \ + -S "SSL - Verification of the message MAC failed" + +# Note: if the name of this test is changed, then please adjust the corresponding +# filtering label in "test_tls1_2_ecjpake_compatibility" (in "all.sh") +requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "ECJPAKE: opaque password client only, working, TLS" \ + "$P_SRV debug_level=3 ecjpake_pw=bla" \ + "$P_CLI debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1\ + force_ciphersuite=TLS-ECJPAKE-WITH-AES-128-CCM-8" \ + 0 \ + -c "add ciphersuite: c0ff" \ + -c "adding ecjpake_kkpp extension" \ + -c "using opaque password" \ + -S "using opaque password" \ + -C "re-using cached ecjpake parameters" \ + -s "found ecjpake kkpp extension" \ + -S "skip ecjpake kkpp extension" \ + -S "ciphersuite mismatch: ecjpake not configured" \ + -s "server hello, ecjpake kkpp extension" \ + -c "found ecjpake_kkpp extension" \ + -S "SSL - The handshake negotiation failed" \ + -S "SSL - Verification of the message MAC failed" + +# Note: if the name of this test is changed, then please adjust the corresponding +# filtering label in "test_tls1_2_ecjpake_compatibility" (in "all.sh") +requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "ECJPAKE: opaque password server only, working, TLS" \ + "$P_SRV debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1" \ + "$P_CLI debug_level=3 ecjpake_pw=bla\ + force_ciphersuite=TLS-ECJPAKE-WITH-AES-128-CCM-8" \ + 0 \ + -c "add ciphersuite: c0ff" \ + -c "adding ecjpake_kkpp extension" \ + -C "using opaque password" \ + -s "using opaque password" \ + -C "re-using cached ecjpake parameters" \ + -s "found ecjpake kkpp extension" \ + -S "skip ecjpake kkpp extension" \ + -S "ciphersuite mismatch: ecjpake not configured" \ + -s "server hello, ecjpake kkpp extension" \ + -c "found ecjpake_kkpp extension" \ + -S "SSL - The handshake negotiation failed" \ + -S "SSL - Verification of the message MAC failed" + server_needs_more_time 1 requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 @@ -8015,6 +8084,20 @@ run_test "ECJPAKE: password mismatch, TLS" \ -C "re-using cached ecjpake parameters" \ -s "SSL - Verification of the message MAC failed" +server_needs_more_time 1 +requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "ECJPAKE_OPAQUE_PW: opaque password mismatch, TLS" \ + "$P_SRV debug_level=3 ecjpake_pw=bla ecjpake_pw_opaque=1" \ + "$P_CLI debug_level=3 ecjpake_pw=bad ecjpake_pw_opaque=1 \ + force_ciphersuite=TLS-ECJPAKE-WITH-AES-128-CCM-8" \ + 1 \ + -c "using opaque password" \ + -s "using opaque password" \ + -C "re-using cached ecjpake parameters" \ + -s "SSL - Verification of the message MAC failed" + requires_config_enabled MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 run_test "ECJPAKE: working, DTLS" \ diff --git a/tests/suites/test_suite_ssl.data b/tests/suites/test_suite_ssl.data index a7f050131..1b5e44baa 100644 --- a/tests/suites/test_suite_ssl.data +++ b/tests/suites/test_suite_ssl.data @@ -3539,3 +3539,11 @@ cookie_parsing:"16fefd0000000000000000002F010000de000000000000011efefd7b72727272 TLS 1.3 srv Certificate msg - wrong vector lengths tls13_server_certificate_msg_invalid_vector_len + +EC-JPAKE set password +depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED +ssl_ecjpake_set_password:0 + +EC-JPAKE set opaque password +depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED:MBEDTLS_USE_PSA_CRYPTO +ssl_ecjpake_set_password:1 diff --git a/tests/suites/test_suite_ssl.function b/tests/suites/test_suite_ssl.function index 674e6496e..95fa8ef85 100644 --- a/tests/suites/test_suite_ssl.function +++ b/tests/suites/test_suite_ssl.function @@ -2582,6 +2582,21 @@ int tweak_tls13_certificate_msg_vector_len( return( 0 ); } #endif /* MBEDTLS_TEST_HOOKS */ + +#define ECJPAKE_TEST_PWD "bla" + +#if defined( MBEDTLS_USE_PSA_CRYPTO ) +#define ECJPAKE_TEST_SET_PASSWORD( exp_ret_val ) \ + ret = ( use_opaque_arg ) ? \ + mbedtls_ssl_set_hs_ecjpake_password_opaque( &ssl, pwd_slot ) : \ + mbedtls_ssl_set_hs_ecjpake_password( &ssl, pwd_string, pwd_len ); \ + TEST_EQUAL( ret, exp_ret_val ) +#else +#define ECJPAKE_TEST_SET_PASSWORD( exp_ret_val ) \ + ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl, \ + pwd_string, pwd_len ); \ + TEST_EQUAL( ret, exp_ret_val ) +#endif /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -5997,3 +6012,85 @@ exit: USE_PSA_DONE( ); } /* END_CASE */ + +/* BEGIN_CASE depends_on:MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ +void ssl_ecjpake_set_password( int use_opaque_arg ) +{ + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; +#if defined( MBEDTLS_USE_PSA_CRYPTO ) + mbedtls_svc_key_id_t pwd_slot = MBEDTLS_SVC_KEY_ID_INIT; +#else /* MBEDTLS_USE_PSA_CRYPTO */ + (void) use_opaque_arg; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + unsigned char pwd_string[ sizeof(ECJPAKE_TEST_PWD) ] = ""; + size_t pwd_len = 0; + int ret; + + USE_PSA_INIT( ); + + mbedtls_ssl_init( &ssl ); + + /* test with uninitalized SSL context */ + ECJPAKE_TEST_SET_PASSWORD( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + mbedtls_ssl_config_init( &conf ); + + TEST_EQUAL( mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_STREAM, + MBEDTLS_SSL_PRESET_DEFAULT ), 0 ); + + TEST_EQUAL( mbedtls_ssl_setup( &ssl, &conf ), 0 ); + + /* test with empty password or unitialized password key (depending on use_opaque_arg) */ + ECJPAKE_TEST_SET_PASSWORD( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + pwd_len = strlen( ECJPAKE_TEST_PWD ); + memcpy( pwd_string, ECJPAKE_TEST_PWD, pwd_len ); + +#if defined( MBEDTLS_USE_PSA_CRYPTO ) + if( use_opaque_arg ) + { + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_attributes_t check_attributes = PSA_KEY_ATTRIBUTES_INIT; + + /* First try with an invalid usage */ + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH ); + psa_set_key_algorithm( &attributes, PSA_ALG_JPAKE ); + psa_set_key_type( &attributes, PSA_KEY_TYPE_PASSWORD ); + + PSA_ASSERT( psa_import_key( &attributes, pwd_string, + pwd_len, &pwd_slot ) ); + + ECJPAKE_TEST_SET_PASSWORD( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + + /* check that the opaque key is still valid after failure */ + TEST_EQUAL( psa_get_key_attributes( pwd_slot, &check_attributes ), + PSA_SUCCESS ); + + psa_destroy_key( pwd_slot ); + + /* Then set the correct usage */ + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_DERIVE ); + + PSA_ASSERT( psa_import_key( &attributes, pwd_string, + pwd_len, &pwd_slot ) ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + /* final check which should work without errors */ + ECJPAKE_TEST_SET_PASSWORD( 0 ); + +#if defined( MBEDTLS_USE_PSA_CRYPTO ) + if( use_opaque_arg ) + { + psa_destroy_key( pwd_slot ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + + USE_PSA_DONE( ); +} +/* END_CASE */