From 0228304b5ff927f4c8497453599c0873e259b263 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 22 Oct 2018 15:28:02 +0100 Subject: [PATCH 01/26] Add API for configuration of opaque PSK This commit adds two public API functions mbedtls_ssl_conf_psk_opaque() mbedtls_ssl_set_hs_psk_opaque() which allow to configure the use of opaque, PSA-maintained PSKs at configuration time or run time. --- include/mbedtls/ssl.h | 130 +++++++++++++++++++++++++++++++++--------- 1 file changed, 104 insertions(+), 26 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 55b206fae..5008950a0 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2057,68 +2057,146 @@ int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) /** - * \brief Set the Pre Shared Key (PSK) and the expected identity name + * \brief Configure a pre-shared key (PSK) and identity + * to be used in PSK-based ciphersuites. * * \note This is mainly useful for clients. Servers will usually * want to use \c mbedtls_ssl_conf_psk_cb() instead. * - * \note Currently clients can only register one pre-shared key. - * In other words, the servers' identity hint is ignored. + * \warning Currently, clients can only register a single pre-shared key. + * Calling this function or mbedtls_ssl_conf_opaque_psk() more + * than once will overwrite values configured in previous calls. * Support for setting multiple PSKs on clients and selecting - * one based on the identity hint is not a planned feature but - * feedback is welcomed. + * one based on the identity hint is not a planned feature, + * but feedback is welcomed. * - * \param conf SSL configuration - * \param psk pointer to the pre-shared key - * \param psk_len pre-shared key length - * \param psk_identity pointer to the pre-shared key identity - * \param psk_identity_len identity key length + * \param conf The SSL configuration to register the PSK with. + * \param psk The pointer to the pre-shared key to use. + * \param psk_len The length of the pre-shared key in bytes. + * \param psk_identity The pointer to the pre-shared key identity. + * \param psk_identity_len The length of the pre-shared key identity + * in bytes. * - * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED + * \note The PSK and its identity are copied internally and + * hence need not be preserved by the caller for the lifetime + * of the SSL configuration. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. */ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, const unsigned char *psk, size_t psk_len, const unsigned char *psk_identity, size_t psk_identity_len ); +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Configure an opaque pre-shared key (PSK) and identity + * to be used in PSK-based ciphersuites. + * + * \note This is mainly useful for clients. Servers will usually + * want to use \c mbedtls_ssl_conf_psk_cb() instead. + * + * \warning Currently, clients can only register a single pre-shared key. + * Calling this function or mbedtls_ssl_conf_psk() more than + * once will overwrite values configured in previous calls. + * Support for setting multiple PSKs on clients and selecting + * one based on the identity hint is not a planned feature, + * but feedback is welcomed. + * + * \param conf The SSL configuration to register the PSK with. + * \param psk The identifier of the key slot holding the PSK. + * Until \p conf is destroyed or this function is successfully + * again, the key slot \p psk must be populated with a key of + * type #PSA_ALG_CATEGORY_KEY_DERIVATION whose policy allows + * its use for the key derivation algorithm applied in the + * handshake. + * \param psk_identity The pointer to the pre-shared key identity. + * \param psk_identity_len The length of the pre-shared key identity + * in bytes. + * + * \note The PSK identity hint is copied internally and hence need + * not be preserved by the caller for the lifetime of the + * SSL configuration. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + */ +int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf, + psa_key_slot_t psk, + const unsigned char *psk_identity, + size_t psk_identity_len ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ /** - * \brief Set the Pre Shared Key (PSK) for the current handshake + * \brief Set the pre-shared Key (PSK) for the current handshake. * * \note This should only be called inside the PSK callback, - * ie the function passed to \c mbedtls_ssl_conf_psk_cb(). + * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb(). * - * \param ssl SSL context - * \param psk pointer to the pre-shared key - * \param psk_len pre-shared key length + * \param ssl The SSL context to configure a PSK for. + * \param psk The pointer to the pre-shared key. + * \param psk_len The length of the pre-shared key in bytes. * - * \return 0 if successful or MBEDTLS_ERR_SSL_ALLOC_FAILED + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. */ int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, const unsigned char *psk, size_t psk_len ); +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Set an opaque pre-shared Key (PSK) for the current handshake. + * + * \note This should only be called inside the PSK callback, + * i.e. the function passed to \c mbedtls_ssl_conf_psk_cb(). + * + * \param ssl The SSL context to configure a PSK for. + * \param psk The identifier of the key slot holding the PSK. + * For the duration of the current handshake, the key slot + * must be populated with a key of type + * #PSA_ALG_CATEGORY_KEY_DERIVATION whose policy allows its + * use for the key derivation algorithm + * applied in the handshake. + * + * \return \c 0 if successful. + * \return An \c MBEDTLS_ERR_SSL_XXX error code on failure. + */ +int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl, + psa_key_slot_t psk ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + /** * \brief Set the PSK callback (server-side only). * * If set, the PSK callback is called for each - * handshake where a PSK ciphersuite was negotiated. + * handshake where a PSK-based ciphersuite was negotiated. * The caller provides the identity received and wants to * receive the actual PSK data and length. * - * The callback has the following parameters: (void *parameter, - * mbedtls_ssl_context *ssl, const unsigned char *psk_identity, - * size_t identity_len) + * The callback has the following parameters: + * - \c void*: The opaque pointer \p p_psk. + * - \c mbedtls_ssl_context*: The SSL context to which + * the operation applies. + * - \c const unsigned char*: The PSK identity + * selected by the client. + * - \c size_t: The length of the PSK identity + * selected by the client. + * * If a valid PSK identity is found, the callback should use - * \c mbedtls_ssl_set_hs_psk() on the ssl context to set the - * correct PSK and return 0. + * \c mbedtls_ssl_set_hs_psk() or + * \c mbedtls_ssl_set_hs_psk_opaque() + * on the SSL context to set the correct PSK and return \c 0. * Any other return value will result in a denied PSK identity. * * \note If you set a PSK callback using this function, then you * don't need to set a PSK key and identity using * \c mbedtls_ssl_conf_psk(). * - * \param conf SSL configuration - * \param f_psk PSK identity function - * \param p_psk PSK identity parameter + * \param conf The SSL configuration to register the callback with. + * \param f_psk The callback for selecting and setting the PSK based + * in the PSK identity chosen by the client. + * \param p_psk A pointer to an opaque structure to be passed to + * the callback, for example a PSK store. */ void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, From d9f7d43b5f74d0a2e59255db5f71792d693183f8 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 22 Oct 2018 15:29:46 +0100 Subject: [PATCH 02/26] Add opaque PSK identifier to mbedtls_ssl_handshake_params This commit adds a field `psk_opaque` to the handshake parameter struct `mbedtls_ssl_handshake_params` which indicates if the user has configured the use of an opaque PSK. --- include/mbedtls/ssl_internal.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/ssl_internal.h b/include/mbedtls/ssl_internal.h index 97abb9f90..318d13fd8 100644 --- a/include/mbedtls/ssl_internal.h +++ b/include/mbedtls/ssl_internal.h @@ -283,9 +283,12 @@ struct mbedtls_ssl_handshake_params const mbedtls_ecp_curve_info **curves; /*!< Supported elliptic curves */ #endif #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_slot_t psk_opaque; /*!< Opaque PSK from the callback */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ unsigned char *psk; /*!< PSK from the callback */ size_t psk_len; /*!< Length of PSK from callback */ -#endif +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_ssl_key_cert *key_cert; /*!< chosen key/cert pair (server) */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) From 4363313976c79c3b18d84c235bfc5df6891d5d62 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 22 Oct 2018 15:31:03 +0100 Subject: [PATCH 03/26] Add opaque PSK identifier to SSL configuration --- include/mbedtls/ssl.h | 48 +++++++++++++++++++++++++++++++------------ 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 5008950a0..171803f75 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -65,6 +65,10 @@ #include "platform_time.h" #endif +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + /* * SSL Error codes */ @@ -923,19 +927,37 @@ struct mbedtls_ssl_config #endif #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - unsigned char *psk; /*!< pre-shared key. This field should - only be set via - mbedtls_ssl_conf_psk() */ - size_t psk_len; /*!< length of the pre-shared key. This - field should only be set via - mbedtls_ssl_conf_psk() */ - unsigned char *psk_identity; /*!< identity for PSK negotiation. This - field should only be set via - mbedtls_ssl_conf_psk() */ - size_t psk_identity_len;/*!< length of identity. This field should - only be set via - mbedtls_ssl_conf_psk() */ -#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_slot_t psk_opaque; /*!< PSA key slot holding opaque PSK. + * This field should only be set via + * mbedtls_ssl_conf_psk_opaque(). + * If either no PSK or a raw PSK have + * been configured, this has value \c 0. */ +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + unsigned char *psk; /*!< The raw pre-shared key. This field should + * only be set via mbedtls_ssl_conf_psk(). + * If either no PSK or an opaque PSK + * have been configured, this has value NULL. */ + size_t psk_len; /*!< The length of the raw pre-shared key. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * Its value is non-zero if and only if + * \c psk is not \c NULL. */ + + unsigned char *psk_identity; /*!< The PSK identity for PSK negotiation. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * This is set if and only if either + * \c psk or \c psk_opaque are set. */ + size_t psk_identity_len;/*!< The length of PSK identity. + * This field should only be set via + * mbedtls_ssl_conf_psk(). + * Its value is non-zero if and only if + * \c psk is not \c NULL or \c psk_opaque + * is not \c 0. */ +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ #if defined(MBEDTLS_SSL_ALPN) const char **alpn_list; /*!< ordered list of protocols */ From d20a8ca7338e8054db6189c15efca20b8afb2fdb Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 22 Oct 2018 15:31:26 +0100 Subject: [PATCH 04/26] Implement API for configuration of opaque PSKs This commit adds implementations of the two new API functions mbedtls_ssl_conf_psk_opaque() mbedtls_ssl_set_hs_psk_opaque(). --- library/ssl_tls.c | 116 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 95 insertions(+), 21 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 82e65251f..2150c03d1 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -7326,6 +7326,37 @@ int mbedtls_ssl_set_hs_ecjpake_password( mbedtls_ssl_context *ssl, #endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + +static void ssl_conf_remove_psk( mbedtls_ssl_config *conf ) +{ + /* Remove reference to existing PSK, if any. */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( conf->psk_opaque != 0 ) + { + /* The maintenance of the PSK key slot is the + * user's responsibility. */ + conf->psk_opaque = 0; + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( conf->psk != NULL ) + { + mbedtls_platform_zeroize( conf->psk, conf->psk_len ); + + mbedtls_free( conf->psk ); + conf->psk = NULL; + conf->psk_len = 0; + } + + /* Remove reference to PSK identity, if any. */ + if( conf->psk_identity != NULL ) + { + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; + conf->psk_identity_len = 0; + } +} + int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, const unsigned char *psk, size_t psk_len, const unsigned char *psk_identity, size_t psk_identity_len ) @@ -7343,20 +7374,7 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } - if( conf->psk != NULL ) - { - mbedtls_platform_zeroize( conf->psk, conf->psk_len ); - - mbedtls_free( conf->psk ); - conf->psk = NULL; - conf->psk_len = 0; - } - if( conf->psk_identity != NULL ) - { - mbedtls_free( conf->psk_identity ); - conf->psk_identity = NULL; - conf->psk_identity_len = 0; - } + ssl_conf_remove_psk( conf ); if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL || ( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL ) @@ -7377,6 +7395,24 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, return( 0 ); } +static void ssl_remove_psk( mbedtls_ssl_context *ssl ) +{ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ssl->handshake->psk_opaque != 0 ) + { + ssl->handshake->psk_opaque = 0; + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ssl->handshake->psk != NULL ) + { + mbedtls_platform_zeroize( ssl->handshake->psk, + ssl->handshake->psk_len ); + mbedtls_free( ssl->handshake->psk ); + ssl->handshake->psk_len = 0; + } +} + int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, const unsigned char *psk, size_t psk_len ) { @@ -7386,13 +7422,7 @@ int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, if( psk_len > MBEDTLS_PSK_MAX_LEN ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - if( ssl->handshake->psk != NULL ) - { - mbedtls_platform_zeroize( ssl->handshake->psk, - ssl->handshake->psk_len ); - mbedtls_free( ssl->handshake->psk ); - ssl->handshake->psk_len = 0; - } + ssl_remove_psk( ssl ); if( ( ssl->handshake->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); @@ -7403,6 +7433,50 @@ int mbedtls_ssl_set_hs_psk( mbedtls_ssl_context *ssl, return( 0 ); } +#if defined(MBEDTLS_USE_PSA_CRYPTO) +int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf, + psa_key_slot_t psk_slot, + const unsigned char *psk_identity, + size_t psk_identity_len ) +{ + if( psk_slot == 0 || psk_identity == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + /* Identity len will be encoded on two bytes */ + if( ( psk_identity_len >> 16 ) != 0 || + psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) + { + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + } + + ssl_conf_remove_psk( conf ); + + if( ( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL ) + { + mbedtls_free( conf->psk_identity ); + conf->psk_identity = NULL; + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + } + + conf->psk_identity_len = psk_identity_len; + memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); + + conf->psk_opaque = psk_slot; + return( 0 ); +} + +int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl, + psa_key_slot_t psk_slot ) +{ + if( psk_slot == 0 || ssl->handshake == NULL ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ssl_remove_psk( ssl ); + ssl->handshake->psk_opaque = psk_slot; + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + void mbedtls_ssl_conf_psk_cb( mbedtls_ssl_config *conf, int (*f_psk)(void *, mbedtls_ssl_context *, const unsigned char *, size_t), From e86964ca01689bc57066c7d69cf1ebf038931b57 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 23 Oct 2018 11:37:50 +0100 Subject: [PATCH 05/26] Add support for opaque PSKs in ssl_client2 example program This commit adds support for the use of PSA-based opaque PSKs in the TLS client example application programs/ssl/ssl_client2. Specifically, a numerical command line option `psk_slot` with the following constraints and semantics is added: - It can only be used alongside the provisioning of a raw PSK through the preexisting `psk` command line option. - It can only be used if both TLS 1.2 and a PSK-only ciphersuite are enforced through the appropriate use of the `min_version` and `force_ciphersuite` command line options. - If the previous conditions are met, setting `psk_slot=d` will result in the PSA key slot with identifier `d` being populated with the raw PSK data specified through the `psk` parameter and passed to Mbed TLS via `mbedtls_ssl_conf_psk_opaque()` prior to the handshake. Enforcing the TLS version and ciphersuite is necessary to determine the exact KDF algorithm the PSK will be used for. This is required as it is currently not possible to set up a key without specifying exactly one algorithm the key may be used with. --- programs/ssl/ssl_client2.c | 219 +++++++++++++++++++++++++++---------- 1 file changed, 163 insertions(+), 56 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 87b9ab1bd..51a0c3f5b 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -85,6 +85,7 @@ int main( void ) #define DFL_CRT_FILE "" #define DFL_KEY_FILE "" #define DFL_PSK "" +#define DFL_PSK_SLOT 0 #define DFL_PSK_IDENTITY "Client_identity" #define DFL_ECJPAKE_PW NULL #define DFL_EC_MAX_OPS -1 @@ -139,9 +140,23 @@ int main( void ) #endif /* MBEDTLS_X509_CRT_PARSE_C */ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -#define USAGE_PSK \ +#define USAGE_PSK_RAW \ " psk=%%s default: \"\" (in hex, without 0x)\n" \ " psk_identity=%%s default: \"Client_identity\"\n" +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#define USAGE_PSK_SLOT \ + " psk_slot=%%d default: 0\n" \ + " An empty key slot identifier to be used to hold the PSK.\n" \ + " Note: Currently only supported in conjunction with\n" \ + " the use of min_version to force TLS 1.2 and force_ciphersuite \n" \ + " to force a particular PSK-only ciphersuite.\n" \ + " Note: This is to test integration of PSA-based opaque PSKs with\n" \ + " Mbed TLS only. Production systems are likely to configure Mbed TLS\n" \ + " with prepopulated key slots instead of importing raw key material.\n" +#else +#define USAGE_PSK_SLOT "" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#define USAGE_PSK USAGE_PSK_RAW USAGE_PSK_SLOT #else #define USAGE_PSK "" #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ @@ -337,6 +352,9 @@ struct options const char *ca_path; /* the path with the CA certificate(s) reside */ const char *crt_file; /* the file with the client certificate */ const char *key_file; /* the file with the client key */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + int psk_slot; +#endif 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 */ @@ -540,6 +558,13 @@ int main( int argc, char *argv[] ) const char *pers = "ssl_client2"; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_slot_t slot; + psa_algorithm_t alg = 0; + psa_key_policy_t policy; + psa_status_t status; +#endif + #if defined(MBEDTLS_X509_CRT_PARSE_C) mbedtls_x509_crt_profile crt_profile_for_test = mbedtls_x509_crt_profile_default; #endif @@ -559,9 +584,6 @@ int main( int argc, char *argv[] ) #endif char *p, *q; const int *list; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_status_t status; -#endif /* * Make sure memory references are valid. @@ -628,6 +650,9 @@ int main( int argc, char *argv[] ) opt.crt_file = DFL_CRT_FILE; opt.key_file = DFL_KEY_FILE; opt.psk = DFL_PSK; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + opt.psk_slot = DFL_PSK_SLOT; +#endif opt.psk_identity = DFL_PSK_IDENTITY; opt.ecjpake_pw = DFL_ECJPAKE_PW; opt.ec_max_ops = DFL_EC_MAX_OPS; @@ -728,6 +753,10 @@ int main( int argc, char *argv[] ) opt.key_file = q; else if( strcmp( p, "psk" ) == 0 ) opt.psk = q; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + else if( strcmp( p, "psk_slot" ) == 0 ) + opt.psk_slot = atoi( q ); +#endif else if( strcmp( p, "psk_identity" ) == 0 ) opt.psk_identity = q; else if( strcmp( p, "ecjpake_pw" ) == 0 ) @@ -1012,57 +1041,6 @@ int main( int argc, char *argv[] ) mbedtls_debug_set_threshold( opt.debug_level ); #endif - if( opt.force_ciphersuite[0] > 0 ) - { - const mbedtls_ssl_ciphersuite_t *ciphersuite_info; - ciphersuite_info = - mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] ); - - if( opt.max_version != -1 && - ciphersuite_info->min_minor_ver > opt.max_version ) - { - mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" ); - ret = 2; - goto usage; - } - if( opt.min_version != -1 && - ciphersuite_info->max_minor_ver < opt.min_version ) - { - mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" ); - ret = 2; - goto usage; - } - - /* If the server selects a version that's not supported by - * this suite, then there will be no common ciphersuite... */ - if( opt.max_version == -1 || - opt.max_version > ciphersuite_info->max_minor_ver ) - { - opt.max_version = ciphersuite_info->max_minor_ver; - } - if( opt.min_version < ciphersuite_info->min_minor_ver ) - { - opt.min_version = ciphersuite_info->min_minor_ver; - /* DTLS starts with TLS 1.1 */ - if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && - opt.min_version < MBEDTLS_SSL_MINOR_VERSION_2 ) - opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; - } - - /* Enable RC4 if needed and not explicitly disabled */ - if( ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) - { - if( opt.arc4 == MBEDTLS_SSL_ARC4_DISABLED ) - { - mbedtls_printf( "forced RC4 ciphersuite with RC4 disabled\n" ); - ret = 2; - goto usage; - } - - opt.arc4 = MBEDTLS_SSL_ARC4_ENABLED; - } - } - #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) /* * Unhexify the pre-shared key if any is given @@ -1113,6 +1091,101 @@ int main( int argc, char *argv[] ) } #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_slot != 0 ) + { + if( opt.psk == NULL ) + { + mbedtls_printf( "psk_slot set but no psk to be imported specified.\n" ); + ret = 2; + goto usage; + } + + if( opt.force_ciphersuite[0] <= 0 ) + { + mbedtls_printf( "opaque PSKs are only supported in conjunction with forcing TLS 1.2 and a PSK-only ciphersuite through the 'force_ciphersuite' option.\n" ); + ret = 2; + goto usage; + } + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( opt.force_ciphersuite[0] > 0 ) + { + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] ); + + if( opt.max_version != -1 && + ciphersuite_info->min_minor_ver > opt.max_version ) + { + mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" ); + ret = 2; + goto usage; + } + if( opt.min_version != -1 && + ciphersuite_info->max_minor_ver < opt.min_version ) + { + mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" ); + ret = 2; + goto usage; + } + + /* If the server selects a version that's not supported by + * this suite, then there will be no common ciphersuite... */ + if( opt.max_version == -1 || + opt.max_version > ciphersuite_info->max_minor_ver ) + { + opt.max_version = ciphersuite_info->max_minor_ver; + } + if( opt.min_version < ciphersuite_info->min_minor_ver ) + { + opt.min_version = ciphersuite_info->min_minor_ver; + /* DTLS starts with TLS 1.1 */ + if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + opt.min_version < MBEDTLS_SSL_MINOR_VERSION_2 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + } + + /* Enable RC4 if needed and not explicitly disabled */ + if( ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + { + if( opt.arc4 == MBEDTLS_SSL_ARC4_DISABLED ) + { + mbedtls_printf( "forced RC4 ciphersuite with RC4 disabled\n" ); + ret = 2; + goto usage; + } + + opt.arc4 = MBEDTLS_SSL_ARC4_ENABLED; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_slot != 0 ) + { + /* Ensure that the chosen ciphersuite is PSK-only; 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 || + opt.min_version != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + mbedtls_printf( "opaque PSKs are only supported in conjunction with forcing TLS 1.2 and a PSK-only ciphersuite through the 'force_ciphersuite' option.\n" ); + ret = 2; + goto usage; + } + + /* Determine KDF algorithm the opaque PSK will be used in. */ +#if defined(MBEDTLS_SHA512_C) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); + else +#endif /* MBEDTLS_SHA512_C */ + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + } + #if defined(MBEDTLS_ECP_C) if( opt.curves != NULL ) { @@ -1484,6 +1557,40 @@ int main( int argc, char *argv[] ) #endif #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_slot != 0 ) + { + /* The algorithm has already been determined earlier. */ + slot = (psa_key_slot_t) opt.psk_slot; + + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); + + status = psa_set_key_policy( slot, &policy ); + if( status != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + + status = psa_import_key( slot, PSA_KEY_TYPE_DERIVE, psk, psk_len ); + if( status != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + + if( ( ret = mbedtls_ssl_conf_psk_opaque( &conf, slot, + (const unsigned char *) opt.psk_identity, + strlen( opt.psk_identity ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk_opaque returned %d\n\n", + ret ); + goto exit; + } + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ if( ( ret = mbedtls_ssl_conf_psk( &conf, psk, psk_len, (const unsigned char *) opt.psk_identity, strlen( opt.psk_identity ) ) ) != 0 ) @@ -1492,7 +1599,7 @@ int main( int argc, char *argv[] ) ret ); goto exit; } -#endif +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ if( opt.min_version != DFL_MIN_VERSION ) mbedtls_ssl_conf_min_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, From 2e4f616708747eccb6ab87a706a8ac9520ac5aa9 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 23 Oct 2018 11:54:44 +0100 Subject: [PATCH 06/26] Don't suggest the use of a PSK suite if no PSK configured on client --- library/ssl_cli.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index ff576f3a8..70ce90f75 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -51,6 +51,27 @@ #include "mbedtls/platform_util.h" #endif +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_conf_has_psk( mbedtls_ssl_config const *conf ) +{ + if( conf->psk_identity == NULL || + conf->psk_identity_len == 0 ) + { + return( 0 ); + } + + if( conf->psk != NULL && conf->psk_len != 0 ) + return( 1 ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( conf->psk_opaque != 0 ) + return( 1 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return( 0 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) static void ssl_write_hostname_ext( mbedtls_ssl_context *ssl, unsigned char *buf, @@ -754,6 +775,15 @@ static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_inf return( 1 ); #endif + /* Don't suggest PSK-based ciphersuite if no PSK is available. */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && + ssl_conf_has_psk( ssl ) == 0 ) + { + return( 1 ); + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + return( 0 ); } @@ -3007,10 +3037,12 @@ ecdh_calc_secret: /* * opaque psk_identity<0..2^16-1>; */ - if( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL ) + if( ssl_conf_has_psk( ssl ) == 0 ) { - MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no private key for PSK" ) ); - return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); + /* We don't offer PSK suites if we don't have a PSK, + * and we check that the server's choice is among the + * ciphersuites we offered, so this should never happen. */ + return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } i = 4; From dfab8e221aac1c9f736f29e2c3072307ec4a29d9 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 23 Oct 2018 11:59:34 +0100 Subject: [PATCH 07/26] Allow opaque PSKs in pure-PSK ciphersuites only In contrast, RSA-PSK, ECDHE-PSK and DHE-PSK are explicitly excluded for the moment. --- library/ssl_cli.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 70ce90f75..90cafebe8 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -70,6 +70,23 @@ static int ssl_conf_has_psk( mbedtls_ssl_config const *conf ) return( 0 ); } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int ssl_conf_has_raw_psk( mbedtls_ssl_config const *conf ) +{ + if( conf->psk_identity == NULL || + conf->psk_identity_len == 0 ) + { + return( 0 ); + } + + if( conf->psk != NULL && conf->psk_len != 0 ) + return( 1 ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ #if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) @@ -778,7 +795,7 @@ static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_inf /* Don't suggest PSK-based ciphersuite if no PSK is available. */ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && - ssl_conf_has_psk( ssl ) == 0 ) + ssl_conf_has_psk( ssl->conf ) == 0 ) { return( 1 ); } @@ -3037,7 +3054,7 @@ ecdh_calc_secret: /* * opaque psk_identity<0..2^16-1>; */ - if( ssl_conf_has_psk( ssl ) == 0 ) + if( ssl_conf_has_psk( ssl->conf ) == 0 ) { /* We don't offer PSK suites if we don't have a PSK, * and we check that the server's choice is among the @@ -3071,6 +3088,12 @@ ecdh_calc_secret: #if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_RSA_PSK ) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only suites. */ + if( ssl_conf_has_raw_psk( ssl->conf ) == 0 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 ) return( ret ); } @@ -3079,6 +3102,12 @@ ecdh_calc_secret: #if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_DHE_PSK ) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only suites. */ + if( ssl_conf_has_raw_psk( ssl->conf ) == 0 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + /* * ClientDiffieHellmanPublic public (DHM send G^X mod P) */ @@ -3109,6 +3138,12 @@ ecdh_calc_secret: #if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_ECDHE_PSK ) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only suites. */ + if( ssl_conf_has_raw_psk( ssl->conf ) == 0 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + /* * ClientECDiffieHellmanPublic public; */ From 35b23c748421a32a7efa00507e13a1076ae76cb8 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 23 Oct 2018 12:10:41 +0100 Subject: [PATCH 08/26] Simplify master secret derivation in mbedtls_ssl_derive_keys() --- library/ssl_tls.c | 78 +++++++++++++++++++++++++++-------------------- 1 file changed, 45 insertions(+), 33 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 2150c03d1..4c0d0c17e 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -621,6 +621,10 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) const mbedtls_cipher_info_t *cipher_info; const mbedtls_md_info_t *md_info; +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + unsigned char session_hash[48]; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ + mbedtls_ssl_session *session = ssl->session_negotiate; mbedtls_ssl_transform *transform = ssl->transform_negotiate; mbedtls_ssl_handshake_params *handshake = ssl->handshake; @@ -700,56 +704,62 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) * TLSv1+: * master = PRF( premaster, "master secret", randbytes )[0..47] */ - if( handshake->resume == 0 ) + if( handshake->resume != 0 ) { - MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", handshake->premaster, - handshake->pmslen ); + MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); + } + else + { + /* The label for the KDF used for key expansion. + * This is either "master secret" or "extended master secret" + * depending on whether the Extended Master Secret extension + * is used. */ + char const *lbl = "master secret"; + + /* The salt for the KDF used for key expansion. + * - If the Extended Master Secret extension is not used, + * this is ClientHello.Random + ServerHello.Random + * (see Sect. 8.1 in RFC 5246). + * - If the Extended Master Secret extension is used, + * this is the transcript of the handshake so far. + * (see Sect. 4 in RFC 7627). */ + unsigned char const *salt = handshake->randbytes; + size_t salt_len = 64; + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + const mbedtls_ssl_ciphersuite_t *ciphersuite_info = + ssl->transform_negotiate->ciphersuite_info; + mbedtls_md_type_t const md_type = ciphersuite_info->mac; +#endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) if( ssl->handshake->extended_ms == MBEDTLS_SSL_EXTENDED_MS_ENABLED ) { - unsigned char session_hash[48]; - size_t hash_len; - MBEDTLS_SSL_DEBUG_MSG( 3, ( "using extended master secret" ) ); + lbl = "extended master secret"; + salt = session_hash; ssl->handshake->calc_verify( ssl, session_hash ); - #if defined(MBEDTLS_SSL_PROTO_TLS1_2) if( ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 ) { #if defined(MBEDTLS_SHA512_C) - if( ssl->transform_negotiate->ciphersuite_info->mac == - MBEDTLS_MD_SHA384 ) - { - hash_len = 48; - } + if( md_type == MBEDTLS_MD_SHA384 ) + salt_len = 48; else -#endif - hash_len = 32; +#endif /* MBEDTLS_SHA512_C */ + salt_len = 32; } else #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ - hash_len = 36; - - MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, hash_len ); - - ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, - "extended master secret", - session_hash, hash_len, - session->master, 48 ); - if( ret != 0 ) - { - MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); - return( ret ); - } + salt_len = 36; + MBEDTLS_SSL_DEBUG_BUF( 3, "session hash", session_hash, salt_len ); } - else -#endif +#endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */ + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, - "master secret", - handshake->randbytes, 64, + lbl, salt, salt_len, session->master, 48 ); if( ret != 0 ) { @@ -757,11 +767,13 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) return( ret ); } + MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", + handshake->premaster, + handshake->pmslen ); + mbedtls_platform_zeroize( handshake->premaster, sizeof(handshake->premaster) ); } - else - MBEDTLS_SSL_DEBUG_MSG( 3, ( "no premaster (session resumed)" ) ); /* * Swap the client and server random values. From 7d0a569d388d862947821826fd7cc70d11a223d3 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 23 Oct 2018 15:26:22 +0100 Subject: [PATCH 09/26] Implement PSA-based PSK-to-MS derivation in mbedtls_ssl_derive_keys --- library/ssl_tls.c | 93 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 82 insertions(+), 11 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 4c0d0c17e..7e861a5fb 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -607,6 +607,28 @@ static void ssl_calc_finished_tls_sha384( mbedtls_ssl_context *, unsigned char * #endif #endif /* MBEDTLS_SSL_PROTO_TLS1_2 */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) +static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl ) +{ + if( ssl->conf->f_psk != NULL ) + { + /* If we've used a callback to select the PSK, + * the static configuration is irrelevant. */ + if( ssl->handshake->psk_opaque != 0 ) + return( 1 ); + + return( 0 ); + } + + if( ssl->conf->psk_opaque != 0 ) + return( 1 ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO && + MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) { int ret = 0; @@ -758,21 +780,70 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) } #endif /* MBEDTLS_SSL_EXTENDED_MS_ENABLED */ - ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, - lbl, salt, salt_len, - session->master, 48 ); - if( ret != 0 ) +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + ssl_use_opaque_psk( ssl ) == 1 ) { - MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); - return( ret ); + /* Perform PSK-to-MS expansion in a single step. */ + psa_status_t status; + psa_algorithm_t alg; + psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; + psa_key_slot_t psk; + + MBEDTLS_SSL_DEBUG_MSG( 2, ( "perform PSA-based PSK-to-MS expansion" ) ); + + psk = ssl->conf->psk_opaque; + if( ssl->handshake->psk_opaque != 0 ) + psk = ssl->handshake->psk_opaque; + + if( md_type == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); + else + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); + + status = psa_key_derivation( &generator, psk, alg, + salt, salt_len, + (unsigned char const *) lbl, + (size_t) strlen( lbl ), + 48 ); + if( status != PSA_SUCCESS ) + { + psa_generator_abort( &generator ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_generator_read( &generator, session->master, 48 ); + if( status != PSA_SUCCESS ) + { + psa_generator_abort( &generator ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); + } + + status = psa_generator_abort( &generator ); + if( status != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); } + else +#endif + { + ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, + lbl, salt, salt_len, + session->master, 48 ); + if( ret != 0 ) + { + MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); + return( ret ); + } - MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", - handshake->premaster, - handshake->pmslen ); + MBEDTLS_SSL_DEBUG_BUF( 3, "premaster secret", + handshake->premaster, + handshake->pmslen ); - mbedtls_platform_zeroize( handshake->premaster, - sizeof(handshake->premaster) ); + mbedtls_platform_zeroize( handshake->premaster, + sizeof(handshake->premaster) ); + } } /* From afd311ee1266f0c7e42f79f538ab925654c70928 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 23 Oct 2018 15:26:40 +0100 Subject: [PATCH 10/26] Skip PMS generation on client if opaque PSK is used For opaque PSKs, the PSK-to-MS expansion is performed atomatically on the PSA-side. --- library/ssl_cli.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 90cafebe8..3f91d4f5b 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -3165,6 +3165,17 @@ ecdh_calc_secret: return( MBEDTLS_ERR_SSL_INTERNAL_ERROR ); } +#if defined(MBEDTLS_USE_PSA_CRYPTO) && \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && + ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && + ssl_conf_has_raw_psk( ssl->conf ) == 0 ) + { + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) ); + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO && + MBEDTLS_KEY_EXCHANGE_PSK_ENABLED */ if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, ciphersuite_info->key_exchange ) ) != 0 ) { From f7027514fb130a5cbc8301c1f53654cff4f7fb4e Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Tue, 23 Oct 2018 15:27:39 +0100 Subject: [PATCH 11/26] Add tests to ssl-opt.sh exercising client-side opaque PSK --- tests/ssl-opt.sh | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index ce9aee28a..41fbf7c28 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -3830,6 +3830,62 @@ run_test "PSK callback: psk, no callback" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: opaque psk on client, no callback" \ + "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \ + "$P_CLI extended_ms=0 debug_level=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ + psk_identity=foo psk=abc123 psk_slot=1" \ + 0 \ + -c "skip PMS generation for opaque PSK"\ + -S "skip PMS generation for opaque PSK"\ + -C "using extended master secret"\ + -S "using extended master secret"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: opaque psk on client, no callback, SHA-384" \ + "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \ + "$P_CLI extended_ms=0 debug_level=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ + psk_identity=foo psk=abc123 psk_slot=1" \ + 0 \ + -c "skip PMS generation for opaque PSK"\ + -S "skip PMS generation for opaque PSK"\ + -C "using extended master secret"\ + -S "using extended master secret"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: opaque psk on client, no callback, EMS" \ + "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \ + "$P_CLI extended_ms=1 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ + psk_identity=foo psk=abc123 psk_slot=1" \ + 0 \ + -c "skip PMS generation for opaque PSK"\ + -S "skip PMS generation for opaque PSK"\ + -c "using extended master secret"\ + -s "using extended master secret"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: opaque psk on client, no callback, SHA-384, EMS" \ + "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \ + "$P_CLI extended_ms=1 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ + psk_identity=foo psk=abc123 psk_slot=1" \ + 0 \ + -c "skip PMS generation for opaque PSK"\ + -S "skip PMS generation for opaque PSK"\ + -c "using extended master secret"\ + -s "using extended master secret"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + run_test "PSK callback: no psk, no callback" \ "$P_SRV" \ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ From b64ba5f2c0f30811eabadef7d887aa161353a11a Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Fri, 26 Oct 2018 11:28:08 +0100 Subject: [PATCH 12/26] Add support for opaque PSKs to ssl_server2 example application This commit adds command line parameters `psk_slot` and `psk_list_slot` to the example application `programs/ssl/ssl_server2`. These have the following semantics: - `psk_slot`: The same semantics as for the `ssl_client2` example application. That is, if a PSK is configured through the use of the command line parameters `psk` and `psk_identity`, then `psk_slot=X` can be used to import the PSK into PSA key slot X and registering it statically with the SSL configuration through the new API call mbedtls_ssl_conf_hs_opaque(). - `psk_list_slot`: In addition to the static PSK registered in the the SSL configuration, servers can register a callback for picking the PSK corresponding to the PSK identity that the client chose. The `ssl_server2` example application uses such a callback to select the PSK from a list of PSKs + Identities provided through the command line parameter `psk_list`, and to register the selected PSK via `mbedtls_ssl_set_hs_psk()`. In this case, the new parameter `psk_list_slot=X` has the effect of registering all PSKs provided in in `psk_list` as PSA keys in the key slots starting from slot `X`, and having the PSK selection callback register the chosen PSK through the new API function `mbedtls_ssl_set_hs_psk_opaque()`. --- programs/ssl/ssl_server2.c | 201 +++++++++++++++++++++++++++++++++++-- 1 file changed, 195 insertions(+), 6 deletions(-) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 1c6ccaef1..1169763d7 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -123,6 +123,8 @@ int main( void ) #define DFL_ASYNC_PRIVATE_DELAY2 ( -1 ) #define DFL_ASYNC_PRIVATE_ERROR ( 0 ) #define DFL_PSK "" +#define DFL_PSK_SLOT 0 +#define DFL_PSK_LIST_SLOT 0 #define DFL_PSK_IDENTITY "Client_identity" #define DFL_ECJPAKE_PW NULL #define DFL_PSK_LIST NULL @@ -224,9 +226,38 @@ int main( void ) #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -#define USAGE_PSK \ +#define USAGE_PSK_RAW \ " psk=%%s default: \"\" (in hex, without 0x)\n" \ - " psk_identity=%%s default: \"Client_identity\"\n" + " psk_identity=%%s default: \"Client_identity\"\n" \ + " psk_list=%%s default: \"\"\n" \ + " A list of (PSK identity, PSK value) pairs in (hex format, without 0x)\n" \ + " id1,psk1[,id2,psk2[,...]]\n" +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#define USAGE_PSK_SLOT \ + " psk_slot=%%d default: 0 (don't use key slots)\n" \ + " An empty key slot identifier to be used to hold the static PSK\n" \ + " configured through the psk parameter.\n"\ + " Note: Currently only supported in conjunction with\n" \ + " the use of min_version to force TLS 1.2 and force_ciphersuite \n" \ + " to force a particular PSK-only ciphersuite.\n" \ + " Note: This is to test integration of PSA-based opaque PSKs with\n" \ + " Mbed TLS only. Production systems are likely to configure Mbed TLS\n" \ + " with prepopulated key slots instead of importing raw key material.\n" \ + " psk_list_slot=%%d default: 0 (don't use key slots)\n" \ + " The base of a consecutive list of empty key slot identifiers to be used\n" \ + " to hold the dynamic PSKs configured through the psk_list parameter;\n" \ + " for example, if you specify a list of 3 dynamic PSKs through the psk_list\n"\ + " parameter, then the slots psk_slot, .., psk_slot+3 must be empty.\n" \ + " Note: Currently only supported in conjunction with\n" \ + " the use of min_version to force TLS 1.2 and force_ciphersuite \n" \ + " to force a particular PSK-only ciphersuite.\n" \ + " Note: This is to test integration of PSA-based opaque PSKs with\n" \ + " Mbed TLS only. Production systems are likely to configure Mbed TLS\n" \ + " with prepopulated key slots instead of importing raw key material.\n" +#else +#define USAGE_PSK_SLOT "" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#define USAGE_PSK USAGE_PSK_RAW USAGE_PSK_SLOT #else #define USAGE_PSK "" #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ @@ -453,6 +484,10 @@ struct options int async_private_delay1; /* number of times f_async_resume needs to be called for key 1, or -1 for no async */ int async_private_delay2; /* number of times f_async_resume needs to be called for key 2, or -1 for no async */ int async_private_error; /* inject error in async private callback */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + int psk_slot; + int psk_list_slot; +#endif const char *psk; /* the pre-shared key */ const char *psk_identity; /* the pre-shared key identity */ char *psk_list; /* list of PSK id/key pairs for callback */ @@ -771,6 +806,9 @@ struct _psk_entry const char *name; size_t key_len; unsigned char key[MBEDTLS_PSK_MAX_LEN]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_slot_t slot; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ psk_entry *next; }; @@ -819,6 +857,11 @@ psk_entry *psk_parse( char *psk_string ) if( unhexify( new->key, key_hex, &new->key_len ) != 0 ) goto error; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_list_slot != 0 ) + new->slot = opt.psk_list_slot++; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + new->next = cur; cur = new; } @@ -844,6 +887,11 @@ int psk_callback( void *p_info, mbedtls_ssl_context *ssl, if( name_len == strlen( cur->name ) && memcmp( name, cur->name, name_len ) == 0 ) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( cur->slot != 0 ) + return( mbedtls_ssl_set_hs_psk_opaque( ssl, cur->slot ) ); + else +#endif return( mbedtls_ssl_set_hs_psk( ssl, cur->key, cur->key_len ) ); } @@ -1174,12 +1222,39 @@ int idle( mbedtls_net_context *fd, return( 0 ); } +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static psa_status_t psa_setup_psk_key_slot( psa_key_slot_t slot, + psa_algorithm_t alg, + unsigned char *psk, + size_t psk_len ) +{ + psa_status_t status; + psa_key_policy_t policy; + + psa_key_policy_init( &policy ); + psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); + + status = psa_set_key_policy( slot, &policy ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_import_key( slot, PSA_KEY_TYPE_DERIVE, psk, psk_len ); + if( status != PSA_SUCCESS ) + return( status ); + + return( PSA_SUCCESS ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + int main( int argc, char *argv[] ) { int ret = 0, len, written, frags, exchanges_left; int version_suites[4][2]; unsigned char* buf = 0; #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm_t alg = 0; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ unsigned char psk[MBEDTLS_PSK_MAX_LEN]; size_t psk_len = 0; psk_entry *psk_info = NULL; @@ -1342,6 +1417,10 @@ int main( int argc, char *argv[] ) opt.async_private_delay2 = DFL_ASYNC_PRIVATE_DELAY2; opt.async_private_error = DFL_ASYNC_PRIVATE_ERROR; opt.psk = DFL_PSK; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + opt.psk_slot = DFL_PSK_SLOT; + opt.psk_list_slot = DFL_PSK_LIST_SLOT; +#endif opt.psk_identity = DFL_PSK_IDENTITY; opt.psk_list = DFL_PSK_LIST; opt.ecjpake_pw = DFL_ECJPAKE_PW; @@ -1470,6 +1549,12 @@ int main( int argc, char *argv[] ) #endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ else if( strcmp( p, "psk" ) == 0 ) opt.psk = q; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + else if( strcmp( p, "psk_slot" ) == 0 ) + opt.psk_slot = atoi( q ); + else if( strcmp( p, "psk_list_slot" ) == 0 ) + opt.psk_list_slot = atoi( q ); +#endif else if( strcmp( p, "psk_identity" ) == 0 ) opt.psk_identity = q; else if( strcmp( p, "psk_list" ) == 0 ) @@ -1779,6 +1864,42 @@ int main( int argc, char *argv[] ) goto exit; } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_slot != 0 ) + { + if( strlen( opt.psk ) == 0 ) + { + mbedtls_printf( "psk_slot set but no psk to be imported specified.\n" ); + ret = 2; + goto usage; + } + + if( opt.force_ciphersuite[0] <= 0 ) + { + mbedtls_printf( "opaque PSKs are only supported in conjunction with forcing TLS 1.2 and a PSK-only ciphersuite through the 'force_ciphersuite' option.\n" ); + ret = 2; + goto usage; + } + } + + if( opt.psk_list_slot != 0 ) + { + if( opt.psk_list == NULL ) + { + mbedtls_printf( "psk_slot set but no psk to be imported specified.\n" ); + ret = 2; + goto usage; + } + + if( opt.force_ciphersuite[0] <= 0 ) + { + mbedtls_printf( "opaque PSKs are only supported in conjunction with forcing TLS 1.2 and a PSK-only ciphersuite through the 'force_ciphersuite' option.\n" ); + ret = 2; + goto usage; + } + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( opt.force_ciphersuite[0] > 0 ) { const mbedtls_ssl_ciphersuite_t *ciphersuite_info; @@ -1828,6 +1949,30 @@ int main( int argc, char *argv[] ) opt.arc4 = MBEDTLS_SSL_ARC4_ENABLED; } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_slot != 0 || opt.psk_list_slot != 0 ) + { + /* Ensure that the chosen ciphersuite is PSK-only; 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 || + opt.min_version != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + mbedtls_printf( "opaque PSKs are only supported in conjunction with forcing TLS 1.2 and a PSK-only ciphersuite through the 'force_ciphersuite' option.\n" ); + ret = 2; + goto usage; + } + + /* Determine KDF algorithm the opaque PSK will be used in. */ +#if defined(MBEDTLS_SHA512_C) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); + else +#endif /* MBEDTLS_SHA512_C */ + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ } if( opt.version_suites != NULL ) @@ -2501,12 +2646,35 @@ int main( int argc, char *argv[] ) #endif #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( strlen( opt.psk ) != 0 && strlen( opt.psk_identity ) != 0 ) { - ret = mbedtls_ssl_conf_psk( &conf, psk, psk_len, - (const unsigned char *) opt.psk_identity, - strlen( opt.psk_identity ) ); - if( ret != 0 ) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_slot != 0 ) + { + /* The algorithm has already been determined earlier. */ + status = psa_setup_psk_key_slot( opt.psk_slot, alg, + psk, psk_len ); + if( status != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + + if( ( ret = mbedtls_ssl_conf_psk_opaque( &conf, opt.psk_slot, + (const unsigned char *) opt.psk_identity, + strlen( opt.psk_identity ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk_opaque returned %d\n\n", + ret ); + goto exit; + } + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_ssl_conf_psk( &conf, psk, psk_len, + (const unsigned char *) opt.psk_identity, + strlen( opt.psk_identity ) ) ) != 0 ) { mbedtls_printf( " failed\n mbedtls_ssl_conf_psk returned -0x%04X\n\n", - ret ); goto exit; @@ -2514,7 +2682,28 @@ int main( int argc, char *argv[] ) } if( opt.psk_list != NULL ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_list_slot != 0 ) + { + psk_entry *cur_psk; + for( cur_psk = psk_info; cur_psk != NULL; cur_psk = cur_psk->next ) + { + fprintf( stderr, "REGISTER KEY SLOT %d\n", (int) cur_psk->slot ); + status = psa_setup_psk_key_slot( cur_psk->slot, alg, + cur_psk->key, + cur_psk->key_len ); + if( status != PSA_SUCCESS ) + { + fprintf( stderr, "REGISTER KEY SLOT\n" ); + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + } + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_ssl_conf_psk_cb( &conf, psk_callback, psk_info ); + } #endif #if defined(MBEDTLS_DHM_C) From 520224e577e14be0cecb55e203586c3f5844d83c Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Fri, 26 Oct 2018 11:38:07 +0100 Subject: [PATCH 13/26] Rename ssl_conf_has_[raw_]_psk to ssl_conf_has_static_[raw_]psk This is to differentiate the function from the functions relevant on the server-side, which also need to take into the PSK callback. --- library/ssl_cli.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 3f91d4f5b..cd25dca91 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -52,7 +52,7 @@ #endif #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) -static int ssl_conf_has_psk( mbedtls_ssl_config const *conf ) +static int ssl_conf_has_static_psk( mbedtls_ssl_config const *conf ) { if( conf->psk_identity == NULL || conf->psk_identity_len == 0 ) @@ -72,7 +72,7 @@ static int ssl_conf_has_psk( mbedtls_ssl_config const *conf ) } #if defined(MBEDTLS_USE_PSA_CRYPTO) -static int ssl_conf_has_raw_psk( mbedtls_ssl_config const *conf ) +static int ssl_conf_has_static_raw_psk( mbedtls_ssl_config const *conf ) { if( conf->psk_identity == NULL || conf->psk_identity_len == 0 ) @@ -795,7 +795,7 @@ static int ssl_validate_ciphersuite( const mbedtls_ssl_ciphersuite_t * suite_inf /* Don't suggest PSK-based ciphersuite if no PSK is available. */ #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && - ssl_conf_has_psk( ssl->conf ) == 0 ) + ssl_conf_has_static_psk( ssl->conf ) == 0 ) { return( 1 ); } @@ -3054,7 +3054,7 @@ ecdh_calc_secret: /* * opaque psk_identity<0..2^16-1>; */ - if( ssl_conf_has_psk( ssl->conf ) == 0 ) + if( ssl_conf_has_static_psk( ssl->conf ) == 0 ) { /* We don't offer PSK suites if we don't have a PSK, * and we check that the server's choice is among the @@ -3090,7 +3090,7 @@ ecdh_calc_secret: { #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Opaque PSKs are currently only supported for PSK-only suites. */ - if( ssl_conf_has_raw_psk( ssl->conf ) == 0 ) + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); #endif /* MBEDTLS_USE_PSA_CRYPTO */ @@ -3104,7 +3104,7 @@ ecdh_calc_secret: { #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Opaque PSKs are currently only supported for PSK-only suites. */ - if( ssl_conf_has_raw_psk( ssl->conf ) == 0 ) + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); #endif /* MBEDTLS_USE_PSA_CRYPTO */ @@ -3140,7 +3140,7 @@ ecdh_calc_secret: { #if defined(MBEDTLS_USE_PSA_CRYPTO) /* Opaque PSKs are currently only supported for PSK-only suites. */ - if( ssl_conf_has_raw_psk( ssl->conf ) == 0 ) + if( ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); #endif /* MBEDTLS_USE_PSA_CRYPTO */ @@ -3169,7 +3169,7 @@ ecdh_calc_secret: defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) if( ciphersuite_info->key_exchange == MBEDTLS_KEY_EXCHANGE_PSK && ssl->minor_ver == MBEDTLS_SSL_MINOR_VERSION_3 && - ssl_conf_has_raw_psk( ssl->conf ) == 0 ) + ssl_conf_has_static_raw_psk( ssl->conf ) == 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) ); } From 845b946d92e467bab163e290a02fe79f95adb94d Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Fri, 26 Oct 2018 12:07:29 +0100 Subject: [PATCH 14/26] Add server-support for opaque PSKs --- library/ssl_srv.c | 75 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 36ca0d69f..54cce0ad6 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -149,6 +149,48 @@ static int ssl_parse_servername_ext( mbedtls_ssl_context *ssl, } #endif /* MBEDTLS_SSL_SERVER_NAME_INDICATION */ +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +static int ssl_conf_has_psk_or_cb( mbedtls_ssl_config const *conf ) +{ + if( conf->f_psk != NULL ) + return( 1 ); + + if( conf->psk_identity_len == 0 || conf->psk_identity == NULL ) + return( 0 ); + + if( conf->psk != NULL && conf->psk_len != 0 ) + return( 1 ); + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( conf->psk_opaque != 0 ) + return( 1 ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + return( 0 ); +} + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +static int ssl_use_opaque_psk( mbedtls_ssl_context const *ssl ) +{ + if( ssl->conf->f_psk != NULL ) + { + /* If we've used a callback to select the PSK, + * the static configuration is irrelevant. */ + + if( ssl->handshake->psk_opaque != 0 ) + return( 1 ); + + return( 0 ); + } + + if( ssl->conf->psk_opaque != 0 ) + return( 1 ); + + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + static int ssl_parse_renegotiation_info( mbedtls_ssl_context *ssl, const unsigned char *buf, size_t len ) @@ -867,9 +909,7 @@ static int ssl_ciphersuite_match( mbedtls_ssl_context *ssl, int suite_id, /* If the ciphersuite requires a pre-shared key and we don't * have one, skip it now rather than failing later */ if( mbedtls_ssl_ciphersuite_uses_psk( suite_info ) && - ssl->conf->f_psk == NULL && - ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || - ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) + ssl_conf_has_psk_or_cb( ssl->conf ) == 0 ) { MBEDTLS_SSL_DEBUG_MSG( 3, ( "ciphersuite mismatch: no pre-shared key" ) ); return( 0 ); @@ -3648,9 +3688,7 @@ static int ssl_parse_client_psk_identity( mbedtls_ssl_context *ssl, unsigned cha int ret = 0; size_t n; - if( ssl->conf->f_psk == NULL && - ( ssl->conf->psk == NULL || ssl->conf->psk_identity == NULL || - ssl->conf->psk_identity_len == 0 || ssl->conf->psk_len == 0 ) ) + if( ssl_conf_has_psk_or_cb( ssl->conf ) == 0 ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no pre-shared key" ) ); return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED ); @@ -3828,6 +3866,13 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE ); } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* For opaque PSKs, we perform the PSK-to-MS derivation atomatically + * and skip the intermediate PMS. */ + if( ssl_use_opaque_psk( ssl ) ) + MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) ); + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, ciphersuite_info->key_exchange ) ) != 0 ) { @@ -3859,6 +3904,12 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) return( ret ); } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + if( ( ret = ssl_parse_encrypted_pms( ssl, p, end, 2 ) ) != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, ( "ssl_parse_encrypted_pms" ), ret ); @@ -3888,6 +3939,12 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) return( ret ); } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + if( p != end ) { MBEDTLS_SSL_DEBUG_MSG( 1, ( "bad client key exchange" ) ); @@ -3919,6 +3976,12 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP ); } +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /* Opaque PSKs are currently only supported for PSK-only. */ + if( ssl_use_opaque_psk( ssl ) == 1 ) + return( MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE ); +#endif + MBEDTLS_SSL_DEBUG_ECP( 3, "ECDH: Qp ", &ssl->handshake->ecdh_ctx.Qp ); if( ( ret = mbedtls_ssl_psk_derive_premaster( ssl, From 28c79dc3d080908c68e0791b9035b9d802215977 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Fri, 26 Oct 2018 13:15:08 +0100 Subject: [PATCH 15/26] Add tests to ssl-opt.sh exercising server-side opaque PSK --- tests/ssl-opt.sh | 178 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 41fbf7c28..45b2e207f 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -3886,6 +3886,184 @@ run_test "PSK callback: opaque psk on client, no callback, SHA-384, EMS" \ -S "SSL - Unknown identity received" \ -S "SSL - Verification of the message MAC failed" +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, static opaque on server, no callback" \ + "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_slot=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_CLI extended_ms=0 debug_level=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ + psk_identity=foo psk=abc123" \ + 0 \ + -C "skip PMS generation for opaque PSK"\ + -s "skip PMS generation for opaque PSK"\ + -C "using extended master secret"\ + -S "using extended master secret"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, static opaque on server, no callback, SHA-384" \ + "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_slot=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384" \ + "$P_CLI extended_ms=0 debug_level=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ + psk_identity=foo psk=abc123" \ + 0 \ + -C "skip PMS generation for opaque PSK"\ + -s "skip PMS generation for opaque PSK"\ + -C "using extended master secret"\ + -S "using extended master secret"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, static opaque on server, no callback, EMS" \ + "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_slot=1 min_version=tls1_2 \ + force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA extended_ms=1" \ + "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ + psk_identity=foo psk=abc123 extended_ms=1" \ + 0 \ + -c "using extended master secret"\ + -s "using extended master secret"\ + -C "skip PMS generation for opaque PSK"\ + -s "skip PMS generation for opaque PSK"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, static opaque on server, no callback, EMS, SHA384" \ + "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_slot=1 min_version=tls1_2 \ + force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 extended_ms=1" \ + "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ + psk_identity=foo psk=abc123 extended_ms=1" \ + 0 \ + -c "using extended master secret"\ + -s "using extended master secret"\ + -C "skip PMS generation for opaque PSK"\ + -s "skip PMS generation for opaque PSK"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, no static PSK on server, opaque PSK from callback" \ + "$P_SRV extended_ms=0 debug_level=3 psk_list=abc,dead,def,beef psk_list_slot=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ + psk_identity=def psk=beef" \ + 0 \ + -C "skip PMS generation for opaque PSK"\ + -s "skip PMS generation for opaque PSK"\ + -C "using extended master secret"\ + -S "using extended master secret"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, no static PSK on server, opaque PSK from callback, SHA-384" \ + "$P_SRV extended_ms=0 debug_level=3 psk_list=abc,dead,def,beef psk_list_slot=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384" \ + "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ + psk_identity=def psk=beef" \ + 0 \ + -C "skip PMS generation for opaque PSK"\ + -s "skip PMS generation for opaque PSK"\ + -C "using extended master secret"\ + -S "using extended master secret"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, no static PSK on server, opaque PSK from callback, EMS" \ + "$P_SRV debug_level=3 psk_list=abc,dead,def,beef psk_list_slot=1 min_version=tls1_2 \ + force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA extended_ms=1" \ + "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ + psk_identity=abc psk=dead extended_ms=1" \ + 0 \ + -c "using extended master secret"\ + -s "using extended master secret"\ + -C "skip PMS generation for opaque PSK"\ + -s "skip PMS generation for opaque PSK"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, no static PSK on server, opaque PSK from callback, EMS, SHA384" \ + "$P_SRV debug_level=3 psk_list=abc,dead,def,beef psk_list_slot=1 min_version=tls1_2 \ + force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 extended_ms=1" \ + "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ + psk_identity=abc psk=dead extended_ms=1" \ + 0 \ + -c "using extended master secret"\ + -s "using extended master secret"\ + -C "skip PMS generation for opaque PSK"\ + -s "skip PMS generation for opaque PSK"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, mismatching static raw PSK on server, opaque PSK from callback" \ + "$P_SRV extended_ms=0 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef psk_list_slot=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ + psk_identity=def psk=beef" \ + 0 \ + -C "skip PMS generation for opaque PSK"\ + -s "skip PMS generation for opaque PSK"\ + -C "using extended master secret"\ + -S "using extended master secret"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, mismatching static opaque PSK on server, opaque PSK from callback" \ + "$P_SRV extended_ms=0 psk_slot=1 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef psk_list_slot=2 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ + psk_identity=def psk=beef" \ + 0 \ + -C "skip PMS generation for opaque PSK"\ + -s "skip PMS generation for opaque PSK"\ + -C "using extended master secret"\ + -S "using extended master secret"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, mismatching static opaque PSK on server, raw PSK from callback" \ + "$P_SRV extended_ms=0 psk_slot=1 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ + psk_identity=def psk=beef" \ + 0 \ + -C "skip PMS generation for opaque PSK"\ + -C "using extended master secret"\ + -S "using extended master secret"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, id-matching but wrong raw PSK on server, opaque PSK from callback" \ + "$P_SRV extended_ms=0 psk_slot=1 psk_identity=def psk=abc123 debug_level=3 psk_list=abc,dead,def,beef min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ + psk_identity=def psk=beef" \ + 0 \ + -C "skip PMS generation for opaque PSK"\ + -C "using extended master secret"\ + -S "using extended master secret"\ + -S "SSL - None of the common ciphersuites is usable" \ + -S "SSL - Unknown identity received" \ + -S "SSL - Verification of the message MAC failed" + +requires_config_enabled MBEDTLS_USE_PSA_CRYPTO +run_test "PSK callback: raw psk on client, matching opaque PSK on server, wrong opaque PSK from callback" \ + "$P_SRV extended_ms=0 psk_slot=1 psk_identity=def psk=beef debug_level=3 psk_list=abc,dead,def,abc123 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ + psk_identity=def psk=beef" \ + 1 \ + -s "SSL - Verification of the message MAC failed" + run_test "PSK callback: no psk, no callback" \ "$P_SRV" \ "$P_CLI force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ From 463194d47a8c8eeb4d2c6006dd16d064b2d12fcf Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 5 Nov 2018 12:44:15 +0000 Subject: [PATCH 16/26] Fix typo in documentation of mbedtls_ssl_conf_opaque_psk() --- include/mbedtls/ssl.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 171803f75..678660659 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2128,10 +2128,10 @@ int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, * \param conf The SSL configuration to register the PSK with. * \param psk The identifier of the key slot holding the PSK. * Until \p conf is destroyed or this function is successfully - * again, the key slot \p psk must be populated with a key of - * type #PSA_ALG_CATEGORY_KEY_DERIVATION whose policy allows - * its use for the key derivation algorithm applied in the - * handshake. + * called again, the key slot \p psk must be populated with a + * key of type #PSA_ALG_CATEGORY_KEY_DERIVATION whose policy + * allows its use for the key derivation algorithm applied + * in the handshake. * \param psk_identity The pointer to the pre-shared key identity. * \param psk_identity_len The length of the pre-shared key identity * in bytes. From c1385c104f3db681d083c21e9d6b8a629fe92aa7 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 5 Nov 2018 12:44:27 +0000 Subject: [PATCH 17/26] Don't use idiom `if( func() )` but always add explicit value check --- library/ssl_srv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 54cce0ad6..4d99f884d 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -3869,7 +3869,7 @@ static int ssl_parse_client_key_exchange( mbedtls_ssl_context *ssl ) #if defined(MBEDTLS_USE_PSA_CRYPTO) /* For opaque PSKs, we perform the PSK-to-MS derivation atomatically * and skip the intermediate PMS. */ - if( ssl_use_opaque_psk( ssl ) ) + if( ssl_use_opaque_psk( ssl ) == 1 ) MBEDTLS_SSL_DEBUG_MSG( 1, ( "skip PMS generation for opaque PSK" ) ); else #endif /* MBEDTLS_USE_PSA_CRYPTO */ From f9ed7d5f76b0ea9bdd61d05a31fd52963eab6c44 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 5 Nov 2018 12:45:16 +0000 Subject: [PATCH 18/26] Don't use 48 as a magic number in ssl_derive_keys() In multiple places, it occurrs as the fixed length of the master secret, so use a constant with a descriptive name instead. This is reinforced by the fact the some further occurrences of '48' are semantically different. --- library/ssl_tls.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 7e861a5fb..8f3d203de 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -643,6 +643,10 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) const mbedtls_cipher_info_t *cipher_info; const mbedtls_md_info_t *md_info; + /* cf. RFC 5246, Section 8.1: + * "The master secret is always exactly 48 bytes in length." */ + size_t const master_secret_len = 48; + #if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) unsigned char session_hash[48]; #endif /* MBEDTLS_SSL_EXTENDED_MASTER_SECRET */ @@ -807,14 +811,15 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) salt, salt_len, (unsigned char const *) lbl, (size_t) strlen( lbl ), - 48 ); + master_secret_len ); if( status != PSA_SUCCESS ) { psa_generator_abort( &generator ); return( MBEDTLS_ERR_SSL_HW_ACCEL_FAILED ); } - status = psa_generator_read( &generator, session->master, 48 ); + status = psa_generator_read( &generator, session->master, + master_secret_len ); if( status != PSA_SUCCESS ) { psa_generator_abort( &generator ); @@ -830,7 +835,8 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) { ret = handshake->tls_prf( handshake->premaster, handshake->pmslen, lbl, salt, salt_len, - session->master, 48 ); + session->master, + master_secret_len ); if( ret != 0 ) { MBEDTLS_SSL_DEBUG_RET( 1, "prf", ret ); From a63ac3f149060cb3a57ea8da7502e747642a1132 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 5 Nov 2018 12:47:16 +0000 Subject: [PATCH 19/26] Safe-guard `ssl_conf_remove_psk()` for simultaneous raw-opaque PSKs The code maintains the invariant that raw and opaque PSKs are never configured simultaneously, so strictly speaking `ssl_conf_remove_psk()` need not consider clearing the raw PSK if it has already cleared an opaque one - and previously, it didn't. However, it doesn't come at any cost to keep this check as a safe-guard to future unforeseen situations where opaque and raw PSKs _are_ both present. --- library/ssl_tls.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 8f3d203de..6fa2e3a76 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -7426,7 +7426,11 @@ static void ssl_conf_remove_psk( mbedtls_ssl_config *conf ) * user's responsibility. */ conf->psk_opaque = 0; } - else + /* This and the following branch should never + * be taken simultaenously as we maintain the + * invariant that raw and opaque PSKs are never + * configured simultaneously. As a safeguard, + * though, `else` is omitted here. */ #endif /* MBEDTLS_USE_PSA_CRYPTO */ if( conf->psk != NULL ) { From 5cd607bf2eeee64b06c476be5931b308169dd88b Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 5 Nov 2018 12:52:42 +0000 Subject: [PATCH 20/26] Remove overly long line in ssl_client2.c --- programs/ssl/ssl_client2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 51a0c3f5b..598ec43fe 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -1582,7 +1582,7 @@ int main( int argc, char *argv[] ) if( ( ret = mbedtls_ssl_conf_psk_opaque( &conf, slot, (const unsigned char *) opt.psk_identity, - strlen( opt.psk_identity ) ) ) != 0 ) + strlen( opt.psk_identity ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk_opaque returned %d\n\n", ret ); From 3f24ea976daba87302516653a6d67a40a39d4396 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 5 Nov 2018 13:25:17 +0000 Subject: [PATCH 21/26] Destroy PSA-based temporary opaque PSK key at the end of ssl_client2 --- programs/ssl/ssl_client2.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 598ec43fe..61dd50ebf 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -2230,6 +2230,26 @@ exit: mbedtls_ctr_drbg_free( &ctr_drbg ); mbedtls_entropy_free( &entropy ); +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_slot != 0 ) + { + /* This is ok even if the slot hasn't been + * initialized (we might have jumed here + * immediately because of bad cmd line params, + * for example). */ + status = psa_destroy_key( opt.psk_slot ); + if( status != PSA_SUCCESS ) + { + mbedtls_printf( "Failed to destroy key slot %u - error was %d", + (unsigned) opt.psk_slot, (int) status ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED && + MBEDTLS_USE_PSA_CRYPTO */ + #if defined(_WIN32) mbedtls_printf( " + Press Enter to exit this program.\n" ); fflush( stdout ); getchar(); From c43b6ea847fc0837e0ee2e485a1a4ba7e7548942 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 5 Nov 2018 13:48:43 +0000 Subject: [PATCH 22/26] Destroy PSA-based temporary opaque PSKs at the end of ssl_server2 --- programs/ssl/ssl_server2.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index 1169763d7..f4b737faf 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -815,16 +815,30 @@ struct _psk_entry /* * Free a list of psk_entry's */ -void psk_free( psk_entry *head ) +int psk_free( psk_entry *head ) { psk_entry *next; while( head != NULL ) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; + psa_key_slot_t const slot = head->slot; + + if( slot != 0 ) + { + status = psa_destroy_key( slot ); + if( status != PSA_SUCCESS ) + return( status ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + next = head->next; mbedtls_free( head ); head = next; } + + return( 0 ); } /* @@ -3332,12 +3346,31 @@ exit: sni_free( sni_info ); #endif #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) - psk_free( psk_info ); + if( ( ret = psk_free( psk_info ) ) != 0 ) + mbedtls_printf( "Failed to list of opaque PSKs - error was %d\n", ret ); #endif #if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO) mbedtls_dhm_free( &dhm ); #endif +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_slot != 0 ) + { + /* This is ok even if the slot hasn't been + * initialized (we might have jumed here + * immediately because of bad cmd line params, + * for example). */ + status = psa_destroy_key( opt.psk_slot ); + if( status != PSA_SUCCESS ) + { + mbedtls_printf( "Failed to destroy key slot %u - error was %d", + (unsigned) opt.psk_slot, (int) status ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED && + MBEDTLS_USE_PSA_CRYPTO */ + mbedtls_ssl_free( &ssl ); mbedtls_ssl_config_free( &conf ); mbedtls_ctr_drbg_free( &ctr_drbg ); From 1d911cd59dbe70a4d8bebbc767454d020ba5cf91 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 15 Nov 2018 13:06:09 +0000 Subject: [PATCH 23/26] Automatically allocate opaque PSK key slots in ssl_{client/server}2 Previously, command line arguments `psk_slot` and `psk_list_slot` could be used to indicate the PSA key slots that the example applications should use to store the PSK(s) provided. This commit changes this approach to use the utility function `mbedtls_psa_get_free_key_slot()` to obtain free key slots from the PSA Crypto implementation automatically, so that users only need to pass boolean flags `psk_opaque` and `psk_list_opaque` on the command line to enable / disable PSA-based opaque PSKs. --- programs/ssl/ssl_client2.c | 37 +++++++++------ programs/ssl/ssl_server2.c | 94 ++++++++++++++++++++++---------------- tests/ssl-opt.sh | 34 +++++++------- 3 files changed, 93 insertions(+), 72 deletions(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 61dd50ebf..1bf6e2f0c 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -61,6 +61,7 @@ int main( void ) #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" +#include "mbedtls/psa_util.h" #endif #include @@ -85,7 +86,7 @@ int main( void ) #define DFL_CRT_FILE "" #define DFL_KEY_FILE "" #define DFL_PSK "" -#define DFL_PSK_SLOT 0 +#define DFL_PSK_OPAQUE 0 #define DFL_PSK_IDENTITY "Client_identity" #define DFL_ECJPAKE_PW NULL #define DFL_EC_MAX_OPS -1 @@ -145,8 +146,9 @@ int main( void ) " psk_identity=%%s default: \"Client_identity\"\n" #if defined(MBEDTLS_USE_PSA_CRYPTO) #define USAGE_PSK_SLOT \ - " psk_slot=%%d default: 0\n" \ - " An empty key slot identifier to be used to hold the PSK.\n" \ + " psk_opaque=%%d default: 0 (don't use opaque static PSK)\n" \ + " Enable this to store the PSK configured through command line\n" \ + " parameter `psk` in a PSA-based key slot.\n" \ " Note: Currently only supported in conjunction with\n" \ " the use of min_version to force TLS 1.2 and force_ciphersuite \n" \ " to force a particular PSK-only ciphersuite.\n" \ @@ -353,7 +355,7 @@ struct options const char *crt_file; /* the file with the client certificate */ const char *key_file; /* the file with the client key */ #if defined(MBEDTLS_USE_PSA_CRYPTO) - int psk_slot; + int psk_opaque; #endif const char *psk; /* the pre-shared key */ const char *psk_identity; /* the pre-shared key identity */ @@ -651,7 +653,7 @@ int main( int argc, char *argv[] ) opt.key_file = DFL_KEY_FILE; opt.psk = DFL_PSK; #if defined(MBEDTLS_USE_PSA_CRYPTO) - opt.psk_slot = DFL_PSK_SLOT; + opt.psk_opaque = DFL_PSK_OPAQUE; #endif opt.psk_identity = DFL_PSK_IDENTITY; opt.ecjpake_pw = DFL_ECJPAKE_PW; @@ -754,8 +756,8 @@ int main( int argc, char *argv[] ) else if( strcmp( p, "psk" ) == 0 ) opt.psk = q; #if defined(MBEDTLS_USE_PSA_CRYPTO) - else if( strcmp( p, "psk_slot" ) == 0 ) - opt.psk_slot = atoi( q ); + else if( strcmp( p, "psk_opaque" ) == 0 ) + opt.psk_opaque = atoi( q ); #endif else if( strcmp( p, "psk_identity" ) == 0 ) opt.psk_identity = q; @@ -1093,11 +1095,11 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_USE_PSA_CRYPTO) - if( opt.psk_slot != 0 ) + if( opt.psk_opaque != 0 ) { if( opt.psk == NULL ) { - mbedtls_printf( "psk_slot set but no psk to be imported specified.\n" ); + mbedtls_printf( "psk_opaque set but no psk to be imported specified.\n" ); ret = 2; goto usage; } @@ -1162,7 +1164,7 @@ int main( int argc, char *argv[] ) } #if defined(MBEDTLS_USE_PSA_CRYPTO) - if( opt.psk_slot != 0 ) + if( opt.psk_opaque != 0 ) { /* Ensure that the chosen ciphersuite is PSK-only; we must know * the ciphersuite in advance to set the correct policy for the @@ -1558,10 +1560,15 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) - if( opt.psk_slot != 0 ) + if( opt.psk_opaque != 0 ) { /* The algorithm has already been determined earlier. */ - slot = (psa_key_slot_t) opt.psk_slot; + status = mbedtls_psa_get_free_key_slot( &slot ); + if( status != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } psa_key_policy_init( &policy ); psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); @@ -2232,17 +2239,17 @@ exit: #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && \ defined(MBEDTLS_USE_PSA_CRYPTO) - if( opt.psk_slot != 0 ) + if( opt.psk_opaque != 0 ) { /* This is ok even if the slot hasn't been * initialized (we might have jumed here * immediately because of bad cmd line params, * for example). */ - status = psa_destroy_key( opt.psk_slot ); + status = psa_destroy_key( slot ); if( status != PSA_SUCCESS ) { mbedtls_printf( "Failed to destroy key slot %u - error was %d", - (unsigned) opt.psk_slot, (int) status ); + (unsigned) slot, (int) status ); if( ret == 0 ) ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; } diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c index f4b737faf..534a3f373 100644 --- a/programs/ssl/ssl_server2.c +++ b/programs/ssl/ssl_server2.c @@ -62,6 +62,7 @@ int main( void ) #if defined(MBEDTLS_USE_PSA_CRYPTO) #include "psa/crypto.h" +#include "mbedtls/psa_util.h" #endif #include @@ -123,8 +124,8 @@ int main( void ) #define DFL_ASYNC_PRIVATE_DELAY2 ( -1 ) #define DFL_ASYNC_PRIVATE_ERROR ( 0 ) #define DFL_PSK "" -#define DFL_PSK_SLOT 0 -#define DFL_PSK_LIST_SLOT 0 +#define DFL_PSK_OPAQUE 0 +#define DFL_PSK_LIST_OPAQUE 0 #define DFL_PSK_IDENTITY "Client_identity" #define DFL_ECJPAKE_PW NULL #define DFL_PSK_LIST NULL @@ -234,20 +235,18 @@ int main( void ) " id1,psk1[,id2,psk2[,...]]\n" #if defined(MBEDTLS_USE_PSA_CRYPTO) #define USAGE_PSK_SLOT \ - " psk_slot=%%d default: 0 (don't use key slots)\n" \ - " An empty key slot identifier to be used to hold the static PSK\n" \ - " configured through the psk parameter.\n"\ + " psk_opaque=%%d default: 0 (don't use opaque static PSK)\n" \ + " Enable this to store the PSK configured through command line\n" \ + " parameter `psk` in a PSA-based key slot.\n" \ " Note: Currently only supported in conjunction with\n" \ " the use of min_version to force TLS 1.2 and force_ciphersuite \n" \ " to force a particular PSK-only ciphersuite.\n" \ " Note: This is to test integration of PSA-based opaque PSKs with\n" \ " Mbed TLS only. Production systems are likely to configure Mbed TLS\n" \ " with prepopulated key slots instead of importing raw key material.\n" \ - " psk_list_slot=%%d default: 0 (don't use key slots)\n" \ - " The base of a consecutive list of empty key slot identifiers to be used\n" \ - " to hold the dynamic PSKs configured through the psk_list parameter;\n" \ - " for example, if you specify a list of 3 dynamic PSKs through the psk_list\n"\ - " parameter, then the slots psk_slot, .., psk_slot+3 must be empty.\n" \ + " psk_list_opaque=%%d default: 0 (don't use opaque dynamic PSKs)\n" \ + " Enable this to store the list of dynamically chosen PSKs configured\n" \ + " through the command line parameter `psk_list` in PSA-based key slots.\n" \ " Note: Currently only supported in conjunction with\n" \ " the use of min_version to force TLS 1.2 and force_ciphersuite \n" \ " to force a particular PSK-only ciphersuite.\n" \ @@ -485,8 +484,8 @@ struct options int async_private_delay2; /* number of times f_async_resume needs to be called for key 2, or -1 for no async */ int async_private_error; /* inject error in async private callback */ #if defined(MBEDTLS_USE_PSA_CRYPTO) - int psk_slot; - int psk_list_slot; + int psk_opaque; + int psk_list_opaque; #endif const char *psk; /* the pre-shared key */ const char *psk_identity; /* the pre-shared key identity */ @@ -871,11 +870,6 @@ psk_entry *psk_parse( char *psk_string ) if( unhexify( new->key, key_hex, &new->key_len ) != 0 ) goto error; -#if defined(MBEDTLS_USE_PSA_CRYPTO) - if( opt.psk_list_slot != 0 ) - new->slot = opt.psk_list_slot++; -#endif /* MBEDTLS_USE_PSA_CRYPTO */ - new->next = cur; cur = new; } @@ -1250,11 +1244,17 @@ static psa_status_t psa_setup_psk_key_slot( psa_key_slot_t slot, status = psa_set_key_policy( slot, &policy ); if( status != PSA_SUCCESS ) + { + fprintf( stderr, "POLICY\n" ); return( status ); + } status = psa_import_key( slot, PSA_KEY_TYPE_DERIVE, psk, psk_len ); if( status != PSA_SUCCESS ) + { + fprintf( stderr, "IMPORT\n" ); return( status ); + } return( PSA_SUCCESS ); } @@ -1268,6 +1268,7 @@ int main( int argc, char *argv[] ) #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) #if defined(MBEDTLS_USE_PSA_CRYPTO) psa_algorithm_t alg = 0; + psa_key_slot_t psk_slot = 0; #endif /* MBEDTLS_USE_PSA_CRYPTO */ unsigned char psk[MBEDTLS_PSK_MAX_LEN]; size_t psk_len = 0; @@ -1432,8 +1433,8 @@ int main( int argc, char *argv[] ) opt.async_private_error = DFL_ASYNC_PRIVATE_ERROR; opt.psk = DFL_PSK; #if defined(MBEDTLS_USE_PSA_CRYPTO) - opt.psk_slot = DFL_PSK_SLOT; - opt.psk_list_slot = DFL_PSK_LIST_SLOT; + opt.psk_opaque = DFL_PSK_OPAQUE; + opt.psk_list_opaque = DFL_PSK_LIST_OPAQUE; #endif opt.psk_identity = DFL_PSK_IDENTITY; opt.psk_list = DFL_PSK_LIST; @@ -1564,10 +1565,10 @@ int main( int argc, char *argv[] ) else if( strcmp( p, "psk" ) == 0 ) opt.psk = q; #if defined(MBEDTLS_USE_PSA_CRYPTO) - else if( strcmp( p, "psk_slot" ) == 0 ) - opt.psk_slot = atoi( q ); - else if( strcmp( p, "psk_list_slot" ) == 0 ) - opt.psk_list_slot = atoi( q ); + else if( strcmp( p, "psk_opaque" ) == 0 ) + opt.psk_opaque = atoi( q ); + else if( strcmp( p, "psk_list_opaque" ) == 0 ) + opt.psk_list_opaque = atoi( q ); #endif else if( strcmp( p, "psk_identity" ) == 0 ) opt.psk_identity = q; @@ -1879,11 +1880,11 @@ int main( int argc, char *argv[] ) } #if defined(MBEDTLS_USE_PSA_CRYPTO) - if( opt.psk_slot != 0 ) + if( opt.psk_opaque != 0 ) { if( strlen( opt.psk ) == 0 ) { - mbedtls_printf( "psk_slot set but no psk to be imported specified.\n" ); + mbedtls_printf( "psk_opaque set but no psk to be imported specified.\n" ); ret = 2; goto usage; } @@ -1896,7 +1897,7 @@ int main( int argc, char *argv[] ) } } - if( opt.psk_list_slot != 0 ) + if( opt.psk_list_opaque != 0 ) { if( opt.psk_list == NULL ) { @@ -1965,7 +1966,7 @@ int main( int argc, char *argv[] ) } #if defined(MBEDTLS_USE_PSA_CRYPTO) - if( opt.psk_slot != 0 || opt.psk_list_slot != 0 ) + if( opt.psk_opaque != 0 || opt.psk_list_opaque != 0 ) { /* Ensure that the chosen ciphersuite is PSK-only; we must know * the ciphersuite in advance to set the correct policy for the @@ -2664,20 +2665,27 @@ int main( int argc, char *argv[] ) if( strlen( opt.psk ) != 0 && strlen( opt.psk_identity ) != 0 ) { #if defined(MBEDTLS_USE_PSA_CRYPTO) - if( opt.psk_slot != 0 ) + if( opt.psk_opaque != 0 ) { - /* The algorithm has already been determined earlier. */ - status = psa_setup_psk_key_slot( opt.psk_slot, alg, - psk, psk_len ); + status = mbedtls_psa_get_free_key_slot( &psk_slot ); if( status != PSA_SUCCESS ) { + fprintf( stderr, "ALLOC FAIL\n" ); ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; goto exit; } - if( ( ret = mbedtls_ssl_conf_psk_opaque( &conf, opt.psk_slot, - (const unsigned char *) opt.psk_identity, - strlen( opt.psk_identity ) ) ) != 0 ) + /* The algorithm has already been determined earlier. */ + status = psa_setup_psk_key_slot( psk_slot, alg, psk, psk_len ); + if( status != PSA_SUCCESS ) + { + fprintf( stderr, "SETUP FAIL\n" ); + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + if( ( ret = mbedtls_ssl_conf_psk_opaque( &conf, psk_slot, + (const unsigned char *) opt.psk_identity, + strlen( opt.psk_identity ) ) ) != 0 ) { mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk_opaque returned %d\n\n", ret ); @@ -2698,24 +2706,30 @@ int main( int argc, char *argv[] ) if( opt.psk_list != NULL ) { #if defined(MBEDTLS_USE_PSA_CRYPTO) - if( opt.psk_list_slot != 0 ) + if( opt.psk_list_opaque != 0 ) { psk_entry *cur_psk; for( cur_psk = psk_info; cur_psk != NULL; cur_psk = cur_psk->next ) { - fprintf( stderr, "REGISTER KEY SLOT %d\n", (int) cur_psk->slot ); + status = mbedtls_psa_get_free_key_slot( &cur_psk->slot ); + if( status != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + status = psa_setup_psk_key_slot( cur_psk->slot, alg, cur_psk->key, cur_psk->key_len ); if( status != PSA_SUCCESS ) { - fprintf( stderr, "REGISTER KEY SLOT\n" ); ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; goto exit; } } } #endif /* MBEDTLS_USE_PSA_CRYPTO */ + mbedtls_ssl_conf_psk_cb( &conf, psk_callback, psk_info ); } #endif @@ -3355,17 +3369,17 @@ exit: #if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && \ defined(MBEDTLS_USE_PSA_CRYPTO) - if( opt.psk_slot != 0 ) + if( opt.psk_opaque != 0 ) { /* This is ok even if the slot hasn't been * initialized (we might have jumed here * immediately because of bad cmd line params, * for example). */ - status = psa_destroy_key( opt.psk_slot ); + status = psa_destroy_key( psk_slot ); if( status != PSA_SUCCESS ) { mbedtls_printf( "Failed to destroy key slot %u - error was %d", - (unsigned) opt.psk_slot, (int) status ); + (unsigned) psk_slot, (int) status ); } } #endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED && diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 45b2e207f..129b91c08 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -3834,7 +3834,7 @@ requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: opaque psk on client, no callback" \ "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \ "$P_CLI extended_ms=0 debug_level=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ - psk_identity=foo psk=abc123 psk_slot=1" \ + psk_identity=foo psk=abc123 psk_opaque=1" \ 0 \ -c "skip PMS generation for opaque PSK"\ -S "skip PMS generation for opaque PSK"\ @@ -3848,7 +3848,7 @@ requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: opaque psk on client, no callback, SHA-384" \ "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo" \ "$P_CLI extended_ms=0 debug_level=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ - psk_identity=foo psk=abc123 psk_slot=1" \ + psk_identity=foo psk=abc123 psk_opaque=1" \ 0 \ -c "skip PMS generation for opaque PSK"\ -S "skip PMS generation for opaque PSK"\ @@ -3862,7 +3862,7 @@ requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: opaque psk on client, no callback, EMS" \ "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \ "$P_CLI extended_ms=1 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ - psk_identity=foo psk=abc123 psk_slot=1" \ + psk_identity=foo psk=abc123 psk_opaque=1" \ 0 \ -c "skip PMS generation for opaque PSK"\ -S "skip PMS generation for opaque PSK"\ @@ -3876,7 +3876,7 @@ requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: opaque psk on client, no callback, SHA-384, EMS" \ "$P_SRV extended_ms=1 debug_level=3 psk=abc123 psk_identity=foo" \ "$P_CLI extended_ms=1 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ - psk_identity=foo psk=abc123 psk_slot=1" \ + psk_identity=foo psk=abc123 psk_opaque=1" \ 0 \ -c "skip PMS generation for opaque PSK"\ -S "skip PMS generation for opaque PSK"\ @@ -3888,7 +3888,7 @@ run_test "PSK callback: opaque psk on client, no callback, SHA-384, EMS" \ requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, static opaque on server, no callback" \ - "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_slot=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ "$P_CLI extended_ms=0 debug_level=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=foo psk=abc123" \ 0 \ @@ -3902,7 +3902,7 @@ run_test "PSK callback: raw psk on client, static opaque on server, no callba requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, static opaque on server, no callback, SHA-384" \ - "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_slot=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384" \ + "$P_SRV extended_ms=0 debug_level=1 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384" \ "$P_CLI extended_ms=0 debug_level=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ psk_identity=foo psk=abc123" \ 0 \ @@ -3916,7 +3916,7 @@ run_test "PSK callback: raw psk on client, static opaque on server, no callba requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, static opaque on server, no callback, EMS" \ - "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_slot=1 min_version=tls1_2 \ + "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls1_2 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA extended_ms=1" \ "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=foo psk=abc123 extended_ms=1" \ @@ -3931,7 +3931,7 @@ run_test "PSK callback: raw psk on client, static opaque on server, no callba requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, static opaque on server, no callback, EMS, SHA384" \ - "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_slot=1 min_version=tls1_2 \ + "$P_SRV debug_level=3 psk=abc123 psk_identity=foo psk_opaque=1 min_version=tls1_2 \ force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 extended_ms=1" \ "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ psk_identity=foo psk=abc123 extended_ms=1" \ @@ -3946,7 +3946,7 @@ run_test "PSK callback: raw psk on client, static opaque on server, no callba requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, no static PSK on server, opaque PSK from callback" \ - "$P_SRV extended_ms=0 debug_level=3 psk_list=abc,dead,def,beef psk_list_slot=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_SRV extended_ms=0 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=def psk=beef" \ 0 \ @@ -3960,7 +3960,7 @@ run_test "PSK callback: raw psk on client, no static PSK on server, opaque PS requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, no static PSK on server, opaque PSK from callback, SHA-384" \ - "$P_SRV extended_ms=0 debug_level=3 psk_list=abc,dead,def,beef psk_list_slot=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384" \ + "$P_SRV extended_ms=0 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384" \ "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ psk_identity=def psk=beef" \ 0 \ @@ -3974,7 +3974,7 @@ run_test "PSK callback: raw psk on client, no static PSK on server, opaque PS requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, no static PSK on server, opaque PSK from callback, EMS" \ - "$P_SRV debug_level=3 psk_list=abc,dead,def,beef psk_list_slot=1 min_version=tls1_2 \ + "$P_SRV debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls1_2 \ force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA extended_ms=1" \ "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=abc psk=dead extended_ms=1" \ @@ -3989,7 +3989,7 @@ run_test "PSK callback: raw psk on client, no static PSK on server, opaque PS requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, no static PSK on server, opaque PSK from callback, EMS, SHA384" \ - "$P_SRV debug_level=3 psk_list=abc,dead,def,beef psk_list_slot=1 min_version=tls1_2 \ + "$P_SRV debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls1_2 \ force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 extended_ms=1" \ "$P_CLI debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-256-CBC-SHA384 \ psk_identity=abc psk=dead extended_ms=1" \ @@ -4004,7 +4004,7 @@ run_test "PSK callback: raw psk on client, no static PSK on server, opaque PS requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, mismatching static raw PSK on server, opaque PSK from callback" \ - "$P_SRV extended_ms=0 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef psk_list_slot=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_SRV extended_ms=0 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=def psk=beef" \ 0 \ @@ -4018,7 +4018,7 @@ run_test "PSK callback: raw psk on client, mismatching static raw PSK on serv requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, mismatching static opaque PSK on server, opaque PSK from callback" \ - "$P_SRV extended_ms=0 psk_slot=1 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef psk_list_slot=2 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef psk_list_opaque=1 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=def psk=beef" \ 0 \ @@ -4032,7 +4032,7 @@ run_test "PSK callback: raw psk on client, mismatching static opaque PSK on s requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, mismatching static opaque PSK on server, raw PSK from callback" \ - "$P_SRV extended_ms=0 psk_slot=1 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=foo psk=abc123 debug_level=3 psk_list=abc,dead,def,beef min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=def psk=beef" \ 0 \ @@ -4045,7 +4045,7 @@ run_test "PSK callback: raw psk on client, mismatching static opaque PSK on s requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, id-matching but wrong raw PSK on server, opaque PSK from callback" \ - "$P_SRV extended_ms=0 psk_slot=1 psk_identity=def psk=abc123 debug_level=3 psk_list=abc,dead,def,beef min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=def psk=abc123 debug_level=3 psk_list=abc,dead,def,beef min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=def psk=beef" \ 0 \ @@ -4058,7 +4058,7 @@ run_test "PSK callback: raw psk on client, id-matching but wrong raw PSK on s requires_config_enabled MBEDTLS_USE_PSA_CRYPTO run_test "PSK callback: raw psk on client, matching opaque PSK on server, wrong opaque PSK from callback" \ - "$P_SRV extended_ms=0 psk_slot=1 psk_identity=def psk=beef debug_level=3 psk_list=abc,dead,def,abc123 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ + "$P_SRV extended_ms=0 psk_opaque=1 psk_identity=def psk=beef debug_level=3 psk_list=abc,dead,def,abc123 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA" \ "$P_CLI extended_ms=0 debug_level=3 min_version=tls1_2 force_ciphersuite=TLS-PSK-WITH-AES-128-CBC-SHA \ psk_identity=def psk=beef" \ 1 \ From f9a3287b7ff7eb49cc1d9c5a8a9bed305bae8bef Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 15 Nov 2018 13:18:25 +0000 Subject: [PATCH 24/26] Fix typo in documentation of mbedtls_ssl_conf_psk() --- include/mbedtls/ssl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mbedtls/ssl.h b/include/mbedtls/ssl.h index 678660659..f7c9d936a 100644 --- a/include/mbedtls/ssl.h +++ b/include/mbedtls/ssl.h @@ -2086,7 +2086,7 @@ int mbedtls_ssl_conf_own_cert( mbedtls_ssl_config *conf, * want to use \c mbedtls_ssl_conf_psk_cb() instead. * * \warning Currently, clients can only register a single pre-shared key. - * Calling this function or mbedtls_ssl_conf_opaque_psk() more + * Calling this function or mbedtls_ssl_conf_psk_opaque() more * than once will overwrite values configured in previous calls. * Support for setting multiple PSKs on clients and selecting * one based on the identity hint is not a planned feature, From 7390c71609caf90103daa86752344062a66ac61e Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Thu, 15 Nov 2018 13:33:04 +0000 Subject: [PATCH 25/26] Share code for PSK identity configuration This commit shares the code for setting the PSK identity hint between the functions mbedtls_ssl_conf_psk() and mbedtls_ssl_conf_psk_opaque(). --- library/ssl_tls.c | 92 ++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 6fa2e3a76..93439697e 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -7450,44 +7450,56 @@ static void ssl_conf_remove_psk( mbedtls_ssl_config *conf ) } } -int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, - const unsigned char *psk, size_t psk_len, - const unsigned char *psk_identity, size_t psk_identity_len ) +/* This function assumes that PSK identity in the SSL config is unset. + * It checks that the provided identity is well-formed and attempts + * to make a copy of it in the SSL config. + * On failure, the PSK identity in the config remains unset. */ +static int ssl_conf_set_psk_identity( mbedtls_ssl_config *conf, + unsigned char const *psk_identity, + size_t psk_identity_len ) { - if( psk == NULL || psk_identity == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - if( psk_len > MBEDTLS_PSK_MAX_LEN ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - /* Identity len will be encoded on two bytes */ - if( ( psk_identity_len >> 16 ) != 0 || + if( psk_identity == NULL || + ( psk_identity_len >> 16 ) != 0 || psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) { return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } - ssl_conf_remove_psk( conf ); - - if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL || - ( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL ) - { - mbedtls_free( conf->psk ); - mbedtls_free( conf->psk_identity ); - conf->psk = NULL; - conf->psk_identity = NULL; + conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ); + if( conf->psk_identity == NULL ) return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - conf->psk_len = psk_len; conf->psk_identity_len = psk_identity_len; - - memcpy( conf->psk, psk, conf->psk_len ); memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); return( 0 ); } +int mbedtls_ssl_conf_psk( mbedtls_ssl_config *conf, + const unsigned char *psk, size_t psk_len, + const unsigned char *psk_identity, size_t psk_identity_len ) +{ + int ret; + /* Remove opaque/raw PSK + PSK Identity */ + ssl_conf_remove_psk( conf ); + + /* Check and set raw PSK */ + if( psk == NULL || psk_len > MBEDTLS_PSK_MAX_LEN ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + if( ( conf->psk = mbedtls_calloc( 1, psk_len ) ) == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + conf->psk_len = psk_len; + memcpy( conf->psk, psk, conf->psk_len ); + + /* Check and set PSK Identity */ + ret = ssl_conf_set_psk_identity( conf, psk_identity, psk_identity_len ); + if( ret != 0 ) + ssl_conf_remove_psk( conf ); + + return( ret ); +} + static void ssl_remove_psk( mbedtls_ssl_context *ssl ) { #if defined(MBEDTLS_USE_PSA_CRYPTO) @@ -7532,30 +7544,22 @@ int mbedtls_ssl_conf_psk_opaque( mbedtls_ssl_config *conf, const unsigned char *psk_identity, size_t psk_identity_len ) { - if( psk_slot == 0 || psk_identity == NULL ) - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - - /* Identity len will be encoded on two bytes */ - if( ( psk_identity_len >> 16 ) != 0 || - psk_identity_len > MBEDTLS_SSL_OUT_CONTENT_LEN ) - { - return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); - } - + int ret; + /* Clear opaque/raw PSK + PSK Identity, if present. */ ssl_conf_remove_psk( conf ); - if( ( conf->psk_identity = mbedtls_calloc( 1, psk_identity_len ) ) == NULL ) - { - mbedtls_free( conf->psk_identity ); - conf->psk_identity = NULL; - return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); - } - - conf->psk_identity_len = psk_identity_len; - memcpy( conf->psk_identity, psk_identity, conf->psk_identity_len ); - + /* Check and set opaque PSK */ + if( psk_slot == 0 ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); conf->psk_opaque = psk_slot; - return( 0 ); + + /* Check and set PSK Identity */ + ret = ssl_conf_set_psk_identity( conf, psk_identity, + psk_identity_len ); + if( ret != 0 ) + ssl_conf_remove_psk( conf ); + + return( ret ); } int mbedtls_ssl_set_hs_psk_opaque( mbedtls_ssl_context *ssl, From c44e0a4bd1d39655bd70097a4b8b7e22f8bf7a26 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Mon, 19 Nov 2018 11:44:14 +0000 Subject: [PATCH 26/26] Initialize PSA key slot as invalid in ssl_client2.c Otherwise, if `mbedtls_psa_get_free_key_slot()` fails to find a fresh key slot, the slot value will be undefined, and the call to `psa_destroy_key()` at the end of `main()` is undefined behavior. --- programs/ssl/ssl_client2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c index 1bf6e2f0c..ff625fbd2 100644 --- a/programs/ssl/ssl_client2.c +++ b/programs/ssl/ssl_client2.c @@ -561,7 +561,7 @@ int main( int argc, char *argv[] ) const char *pers = "ssl_client2"; #if defined(MBEDTLS_USE_PSA_CRYPTO) - psa_key_slot_t slot; + psa_key_slot_t slot = 0; psa_algorithm_t alg = 0; psa_key_policy_t policy; psa_status_t status;