diff --git a/include/mbedtls/ssl_ticket.h b/include/mbedtls/ssl_ticket.h index 855930953a..98fd287079 100644 --- a/include/mbedtls/ssl_ticket.h +++ b/include/mbedtls/ssl_ticket.h @@ -34,6 +34,10 @@ #include "mbedtls/ssl.h" #include "mbedtls/cipher.h" +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#endif + #if defined(MBEDTLS_THREADING_C) #include "mbedtls/threading.h" #endif @@ -53,7 +57,14 @@ typedef struct mbedtls_ssl_ticket_key unsigned char MBEDTLS_PRIVATE(name)[MBEDTLS_SSL_TICKET_KEY_NAME_BYTES]; /*!< random key identifier */ uint32_t MBEDTLS_PRIVATE(generation_time); /*!< key generation timestamp (seconds) */ +#if !defined(MBEDTLS_USE_PSA_CRYPTO) mbedtls_cipher_context_t MBEDTLS_PRIVATE(ctx); /*!< context for auth enc/decryption */ +#else + mbedtls_svc_key_id_t MBEDTLS_PRIVATE(key); /*!< key used for auth enc/decryption */ + psa_algorithm_t MBEDTLS_PRIVATE(alg); /*!< algorithm of auth enc/decryption */ + psa_key_type_t MBEDTLS_PRIVATE(key_type); /*!< key type */ + size_t MBEDTLS_PRIVATE(key_bits); /*!< key length in bits */ +#endif } mbedtls_ssl_ticket_key; diff --git a/library/ssl_ticket.c b/library/ssl_ticket.c index b04e184776..7f658497ef 100644 --- a/library/ssl_ticket.c +++ b/library/ssl_ticket.c @@ -73,6 +73,10 @@ static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, unsigned char buf[MAX_KEY_BYTES]; mbedtls_ssl_ticket_key *key = ctx->keys + index; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; +#endif + #if defined(MBEDTLS_HAVE_TIME) key->generation_time = (uint32_t) mbedtls_time( NULL ); #endif @@ -83,10 +87,23 @@ static int ssl_ticket_gen_key( mbedtls_ssl_ticket_context *ctx, if( ( ret = ctx->f_rng( ctx->p_rng, buf, sizeof( buf ) ) ) != 0 ) return( ret ); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_set_key_usage_flags( &attributes, + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ); + psa_set_key_algorithm( &attributes, key->alg ); + psa_set_key_type( &attributes, key->key_type ); + psa_set_key_bits( &attributes, key->key_bits ); + + ret = psa_ssl_status_to_mbedtls( + psa_import_key( &attributes, buf, + PSA_BITS_TO_BYTES( key->key_bits ), + &key->key ) ); +#else /* With GCM and CCM, same context can encrypt & decrypt */ ret = mbedtls_cipher_setkey( &key->ctx, buf, mbedtls_cipher_get_key_bitlen( &key->ctx ), MBEDTLS_ENCRYPT ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ mbedtls_platform_zeroize( buf, sizeof( buf ) ); @@ -106,6 +123,10 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) uint32_t current_time = (uint32_t) mbedtls_time( NULL ); uint32_t key_time = ctx->keys[ctx->active].generation_time; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif + if( current_time >= key_time && current_time - key_time < ctx->ticket_lifetime ) { @@ -114,6 +135,13 @@ static int ssl_ticket_update_keys( mbedtls_ssl_ticket_context *ctx ) ctx->active = 1 - ctx->active; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ( status = psa_destroy_key( ctx->keys[ctx->active].key ) ) != PSA_SUCCESS ) + { + return psa_ssl_status_to_mbedtls( status ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + return( ssl_ticket_gen_key( ctx, ctx->active ) ); } else @@ -131,15 +159,44 @@ int mbedtls_ssl_ticket_rotate( mbedtls_ssl_ticket_context *ctx, { const unsigned char idx = 1 - ctx->active; mbedtls_ssl_ticket_key * const key = ctx->keys + idx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + const size_t bitlen = key->key_bits; +#else const int bitlen = mbedtls_cipher_get_key_bitlen( &key->ctx ); - int ret; +#endif + if( nlength < TICKET_KEY_NAME_BYTES || klength * 8 < (size_t)bitlen ) return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); - /* With GCM and CCM, same context can encrypt & decrypt */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ( status = psa_destroy_key( key->key ) ) != PSA_SUCCESS ) + { + ret = psa_ssl_status_to_mbedtls( status ); + return( ret ); + } + + psa_set_key_usage_flags( &attributes, + PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT ); + psa_set_key_algorithm( &attributes, key->alg ); + psa_set_key_type( &attributes, key->key_type ); + psa_set_key_bits( &attributes, key->key_bits ); + + if( ( status = psa_import_key( &attributes, k, + PSA_BITS_TO_BYTES( key->key_bits ), + &key->key ) ) != PSA_SUCCESS ) + { + ret = psa_ssl_status_to_mbedtls( status ); + return( ret ); + } +#else ret = mbedtls_cipher_setkey( &key->ctx, k, bitlen, MBEDTLS_ENCRYPT ); if( ret != 0 ) return( ret ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ ctx->active = idx; ctx->ticket_lifetime = lifetime; @@ -161,15 +218,22 @@ int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; const mbedtls_cipher_info_t *cipher_info; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm_t alg; + psa_key_type_t key_type; + size_t key_bits; +#endif + ctx->f_rng = f_rng; ctx->p_rng = p_rng; ctx->ticket_lifetime = lifetime; - cipher_info = mbedtls_cipher_info_from_type( cipher); + cipher_info = mbedtls_cipher_info_from_type( cipher ); if( mbedtls_cipher_info_get_mode( cipher_info ) != MBEDTLS_MODE_GCM && - mbedtls_cipher_info_get_mode( cipher_info ) != MBEDTLS_MODE_CCM ) + mbedtls_cipher_info_get_mode( cipher_info ) != MBEDTLS_MODE_CCM && + mbedtls_cipher_info_get_mode( cipher_info ) != MBEDTLS_MODE_CHACHAPOLY ) { return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); } @@ -178,26 +242,24 @@ int mbedtls_ssl_ticket_setup( mbedtls_ssl_ticket_context *ctx, return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); #if defined(MBEDTLS_USE_PSA_CRYPTO) - ret = mbedtls_cipher_setup_psa( &ctx->keys[0].ctx, - cipher_info, TICKET_AUTH_TAG_BYTES ); - if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) - return( ret ); - /* We don't yet expect to support all ciphers through PSA, - * so allow fallback to ordinary mbedtls_cipher_setup(). */ - if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) -#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( mbedtls_ssl_cipher_to_psa( cipher_info->type, TICKET_AUTH_TAG_BYTES, + &alg, &key_type, &key_bits ) != PSA_SUCCESS ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ctx->keys[0].alg = alg; + ctx->keys[0].key_type = key_type; + ctx->keys[0].key_bits = key_bits; + + ctx->keys[1].alg = alg; + ctx->keys[1].key_type = key_type; + ctx->keys[1].key_bits = key_bits; +#else if( ( ret = mbedtls_cipher_setup( &ctx->keys[0].ctx, cipher_info ) ) != 0 ) return( ret ); -#if defined(MBEDTLS_USE_PSA_CRYPTO) - ret = mbedtls_cipher_setup_psa( &ctx->keys[1].ctx, - cipher_info, TICKET_AUTH_TAG_BYTES ); - if( ret != 0 && ret != MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) - return( ret ); - if( ret == MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ) -#endif /* MBEDTLS_USE_PSA_CRYPTO */ if( ( ret = mbedtls_cipher_setup( &ctx->keys[1].ctx, cipher_info ) ) != 0 ) return( ret ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ if( ( ret = ssl_ticket_gen_key( ctx, 0 ) ) != 0 || ( ret = ssl_ticket_gen_key( ctx, 1 ) ) != 0 ) @@ -238,6 +300,10 @@ int mbedtls_ssl_ticket_write( void *p_ticket, unsigned char *state = state_len_bytes + TICKET_CRYPT_LEN_BYTES; size_t clear_len, ciph_len; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif + *tlen = 0; if( ctx == NULL || ctx->f_rng == NULL ) @@ -275,6 +341,17 @@ int mbedtls_ssl_ticket_write( void *p_ticket, MBEDTLS_PUT_UINT16_BE( clear_len, state_len_bytes, 0 ); /* Encrypt and authenticate */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ( status = psa_aead_encrypt( key->key, key->alg, iv, TICKET_IV_BYTES, + key_name, TICKET_ADD_DATA_LEN, + state, clear_len, + state, end - state, + &ciph_len ) ) != PSA_SUCCESS ) + { + ret = psa_ssl_status_to_mbedtls( status ); + goto cleanup; + } +#else if( ( ret = mbedtls_cipher_auth_encrypt_ext( &key->ctx, iv, TICKET_IV_BYTES, /* Additional data: key name, IV and length */ @@ -285,6 +362,8 @@ int mbedtls_ssl_ticket_write( void *p_ticket, { goto cleanup; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ciph_len != clear_len + TICKET_AUTH_TAG_BYTES ) { ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; @@ -335,6 +414,10 @@ int mbedtls_ssl_ticket_parse( void *p_ticket, unsigned char *ticket = enc_len_p + TICKET_CRYPT_LEN_BYTES; size_t enc_len, clear_len; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED; +#endif + if( ctx == NULL || ctx->f_rng == NULL ) return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); @@ -367,6 +450,16 @@ int mbedtls_ssl_ticket_parse( void *p_ticket, } /* Decrypt and authenticate */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( ( status = psa_aead_decrypt( key->key, key->alg, iv, TICKET_IV_BYTES, + key_name, TICKET_ADD_DATA_LEN, + ticket, enc_len + TICKET_AUTH_TAG_BYTES, + ticket, enc_len, &clear_len ) ) != PSA_SUCCESS ) + { + ret = psa_ssl_status_to_mbedtls( status ); + goto cleanup; + } +#else if( ( ret = mbedtls_cipher_auth_decrypt_ext( &key->ctx, iv, TICKET_IV_BYTES, /* Additional data: key name, IV and length */ @@ -380,6 +473,8 @@ int mbedtls_ssl_ticket_parse( void *p_ticket, goto cleanup; } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( clear_len != enc_len ) { ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR; @@ -418,8 +513,13 @@ cleanup: */ void mbedtls_ssl_ticket_free( mbedtls_ssl_ticket_context *ctx ) { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_destroy_key( ctx->keys[0].key ); + psa_destroy_key( ctx->keys[1].key ); +#else mbedtls_cipher_free( &ctx->keys[0].ctx ); mbedtls_cipher_free( &ctx->keys[1].ctx ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ #if defined(MBEDTLS_THREADING_C) mbedtls_mutex_free( &ctx->mutex ); diff --git a/tests/ssl-opt.sh b/tests/ssl-opt.sh index 9e99c1f2ef..d5334cece3 100755 --- a/tests/ssl-opt.sh +++ b/tests/ssl-opt.sh @@ -2816,7 +2816,6 @@ run_test "Session resume using tickets: basic" \ -c "a session has been resumed" requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 -requires_config_disabled MBEDTLS_USE_PSA_CRYPTO run_test "Session resume using tickets: manual rotation" \ "$P_SRV debug_level=3 tickets=1 ticket_rotate=1" \ "$P_CLI debug_level=3 tickets=1 reconnect=1" \ @@ -3109,6 +3108,21 @@ run_test "Session resume using tickets: ARIA-256-CCM" \ -s "a session has been resumed" \ -c "a session has been resumed" +requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2 +run_test "Session resume using tickets: CHACHA20-POLY1305" \ + "$P_SRV debug_level=3 tickets=1 ticket_aead=CHACHA20-POLY1305" \ + "$P_CLI debug_level=3 tickets=1 reconnect=1" \ + 0 \ + -c "client hello, adding session ticket extension" \ + -s "found session ticket extension" \ + -s "server hello, adding session ticket extension" \ + -c "found session_ticket extension" \ + -c "parse new session ticket" \ + -S "session successfully restored from cache" \ + -s "session successfully restored from ticket" \ + -s "a session has been resumed" \ + -c "a session has been resumed" + # Tests for Session Tickets with DTLS requires_config_enabled MBEDTLS_SSL_PROTO_TLS1_2