Merge pull request #6680 from valeriosetti/issue6599
Allow isolation of EC J-PAKE password when used in TLS
diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h
index 3f48377..7751560 100644
--- a/include/mbedtls/ssl.h
+++ b/include/mbedtls/ssl.h
@@ -3899,6 +3899,23 @@
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 9bb9dc2..b757613 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -1863,27 +1863,55 @@
#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 @@
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 @@
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 @@
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 @@
#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 6aa295d..02ee7cf 100644
--- a/programs/ssl/ssl_client2.c
+++ b/programs/ssl/ssl_client2.c
@@ -68,6 +68,7 @@
#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 @@
#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 @@
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 @@
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 @@
#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 @@
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 @@
#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 @@
#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 00624b5..802beb2 100644
--- a/programs/ssl/ssl_server2.c
+++ b/programs/ssl/ssl_server2.c
@@ -98,6 +98,7 @@
#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 @@
#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 @@
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 @@
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 @@
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 @@
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 @@
#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 @@
#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 db46b03..cc630ce 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -1457,10 +1457,14 @@
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 1fe8bae..ea57b25 100755
--- a/tests/ssl-opt.sh
+++ b/tests/ssl-opt.sh
@@ -7986,6 +7986,8 @@
-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 @@
-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 @@
-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 a7f0501..1b5e44b 100644
--- a/tests/suites/test_suite_ssl.data
+++ b/tests/suites/test_suite_ssl.data
@@ -3539,3 +3539,11 @@
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 674e649..95fa8ef 100644
--- a/tests/suites/test_suite_ssl.function
+++ b/tests/suites/test_suite_ssl.function
@@ -2582,6 +2582,21 @@
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 @@
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 */