From ef29b2c3c9f04c52590fbc7ff84ae4eeb51f8b73 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Fri, 26 Oct 2018 11:28:08 +0100 Subject: [PATCH] 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)