Add implementation of TLS-1.2 PSK-to-MS key derivation
diff --git a/library/psa_crypto.c b/library/psa_crypto.c
index b0fb5a8..010c338 100644
--- a/library/psa_crypto.c
+++ b/library/psa_crypto.c
@@ -3275,7 +3275,9 @@
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 @@
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 @@
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 @@
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 @@
}
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