diff --git a/library/psa_crypto.c b/library/psa_crypto.c index b0fb5a883..010c338c0 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -3275,7 +3275,9 @@ psa_status_t psa_generator_abort( psa_crypto_generator_t *generator ) mbedtls_free( generator->ctx.hkdf.info ); status = psa_hmac_abort_internal( &generator->ctx.hkdf.hmac ); } - else if( PSA_ALG_IS_TLS12_PRF( generator->alg ) ) + else if( PSA_ALG_IS_TLS12_PRF( generator->alg ) || + /* TLS-1.2 PSK-to-MS KDF uses the same generator as TLS-1.2 PRF */ + PSA_ALG_IS_TLS12_PSK_TO_MS( generator->alg ) ) { if( generator->ctx.tls12_prf.key != NULL ) { @@ -3578,7 +3580,8 @@ psa_status_t psa_generator_read( psa_crypto_generator_t *generator, status = psa_generator_hkdf_read( &generator->ctx.hkdf, hash_alg, output, output_length ); } - else if( PSA_ALG_IS_TLS12_PRF( generator->alg ) ) + else if( PSA_ALG_IS_TLS12_PRF( generator->alg ) || + PSA_ALG_IS_TLS12_PSK_TO_MS( generator->alg ) ) { status = psa_generator_tls12_prf_read( &generator->ctx.tls12_prf, generator->alg, output, @@ -3749,6 +3752,47 @@ static psa_status_t psa_generator_tls12_prf_setup( return( PSA_SUCCESS ); } + +/* Set up a TLS-1.2-PSK-to-MS-based generator. */ +static psa_status_t psa_generator_tls12_psk_to_ms_setup( + psa_tls12_prf_generator_t *tls12_prf, + const unsigned char *psk, + size_t psk_len, + psa_algorithm_t hash_alg, + const uint8_t *salt, + size_t salt_length, + const uint8_t *label, + size_t label_length ) +{ + psa_status_t status; + unsigned char pms[ 4 + 2 * PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN ]; + + if( psk_len > PSA_ALG_TLS12_PSK_TO_MS_MAX_PSK_LEN ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + /* Quoting RFC 4279, Section 2: + * + * The premaster secret is formed as follows: if the PSK is N octets + * long, concatenate a uint16 with the value N, N zero octets, a second + * uint16 with the value N, and the PSK itself. + */ + + pms[0] = ( psk_len >> 8 ) & 0xff; + pms[1] = ( psk_len >> 0 ) & 0xff; + memset( pms + 2, 0, psk_len ); + pms[2 + psk_len + 0] = pms[0]; + pms[2 + psk_len + 1] = pms[1]; + memcpy( pms + 4 + psk_len, psk, psk_len ); + + status = psa_generator_tls12_prf_setup( tls12_prf, + pms, 4 + 2 * psk_len, + hash_alg, + salt, salt_length, + label, label_length ); + + mbedtls_zeroize( pms, sizeof( pms ) ); + return( status ); +} #endif /* MBEDTLS_MD_C */ /* Note that if this function fails, you must call psa_generator_abort() @@ -3799,7 +3843,9 @@ static psa_status_t psa_key_derivation_internal( salt, salt_length, label, label_length ); } - else if( PSA_ALG_IS_TLS12_PRF( alg ) ) + /* TLS-1.2 PRF and TLS-1.2 PSK-to-MS are very similar, so share code. */ + else if( PSA_ALG_IS_TLS12_PRF( alg ) || + PSA_ALG_IS_TLS12_PSK_TO_MS( alg ) ) { psa_algorithm_t hash_alg = PSA_ALG_TLS12_PRF_GET_HASH( alg ); size_t hash_size = PSA_HASH_SIZE( hash_alg ); @@ -3812,10 +3858,22 @@ static psa_status_t psa_key_derivation_internal( } max_capacity = 255 * hash_size; - status = psa_generator_tls12_prf_setup( &generator->ctx.tls12_prf, - secret, secret_length, - hash_alg, salt, salt_length, - label, label_length ); + + if( PSA_ALG_IS_TLS12_PRF( alg ) ) + { + status = psa_generator_tls12_prf_setup( &generator->ctx.tls12_prf, + secret, secret_length, + hash_alg, salt, salt_length, + label, label_length ); + } + else + { + status = psa_generator_tls12_psk_to_ms_setup( + &generator->ctx.tls12_prf, + secret, secret_length, + hash_alg, salt, salt_length, + label, label_length ); + } } else #endif