Implement TLS 1.3 key evolution function

Signed-off-by: Hanno Becker <hanno.becker@arm.com>
This commit is contained in:
Hanno Becker 2020-08-20 13:42:46 +01:00
parent e4849d10a6
commit e9cccb440c
2 changed files with 135 additions and 0 deletions

View file

@ -285,4 +285,66 @@ int mbedtls_ssl_tls1_3_derive_secret(
dstbuf, buflen ) );
}
int mbedtls_ssl_tls1_3_evolve_secret(
mbedtls_md_type_t hash_alg,
const unsigned char *secret_old,
const unsigned char *input, size_t input_len,
unsigned char *secret_new )
{
int ret = MBEDTLS_ERR_SSL_INTERNAL_ERROR;
size_t hlen, ilen;
unsigned char _secret[ MBEDTLS_MD_MAX_SIZE ] = { 0 };
unsigned char _input [ MBEDTLS_MD_MAX_SIZE ] = { 0 };
const mbedtls_md_info_t *md;
md = mbedtls_md_info_from_type( hash_alg );
if( md == NULL )
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
hlen = mbedtls_md_get_size( md );
/* For non-initial runs, call Derive-Secret( ., "derived", "")
* on the old secreet. */
if( secret_old != NULL )
{
ret = mbedtls_ssl_tls1_3_derive_secret(
hash_alg,
secret_old, hlen,
MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( derived ),
NULL, 0, /* context */
MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
_secret, hlen );
if( ret != 0 )
goto cleanup;
}
if( input != NULL )
{
memcpy( _input, input, input_len );
ilen = input_len;
}
else
{
ilen = hlen;
}
/* HKDF-Extract takes a salt and input key material.
* The salt is the old secret, and the input key material
* is the input secret (PSK / ECDHE). */
ret = mbedtls_hkdf_extract( md,
_secret, hlen,
_input, ilen,
secret_new );
if( ret != 0 )
goto cleanup;
ret = 0;
cleanup:
mbedtls_platform_zeroize( _secret, sizeof(_secret) );
mbedtls_platform_zeroize( _input, sizeof(_input) );
return( ret );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */

View file

@ -182,6 +182,79 @@ int mbedtls_ssl_tls1_3_derive_secret(
int context_already_hashed,
unsigned char *dstbuf, size_t buflen );
/**
* \brief Compute the next secret in the TLS 1.3 key schedule
*
* The TLS 1.3 key schedule proceeds as follows to compute
* the three main secrets during the handshake: The early
* secret for early data, the handshake secret for all
* other encrypted handshake messages, and the master
* secret for all application traffic.
*
* <tt>
* 0
* |
* v
* PSK -> HKDF-Extract = Early Secret
* |
* v
* Derive-Secret( ., "derived", "" )
* |
* v
* (EC)DHE -> HKDF-Extract = Handshake Secret
* |
* v
* Derive-Secret( ., "derived", "" )
* |
* v
* 0 -> HKDF-Extract = Master Secret
* </tt>
*
* Each of the three secrets in turn is the basis for further
* key derivations, such as the derivation of traffic keys and IVs;
* see e.g. mbedtls_ssl_tls1_3_make_traffic_keys().
*
* This function implements one step in this evolution of secrets:
*
* <tt>
* old_secret
* |
* v
* Derive-Secret( ., "derived", "" )
* |
* v
* input -> HKDF-Extract = new_secret
* </tt>
*
* \param hash_alg The identifier for the hash function used for the
* applications of HKDF.
* \param secret_old The address of the buffer holding the old secret
* on function entry. If not \c NULL, this must be a
* readable buffer whose size matches the output size
* of the hash function represented by \p hash_alg.
* If \c NULL, an all \c 0 array will be used instead.
* \param input The address of the buffer holding the additional
* input for the key derivation (e.g., the PSK or the
* ephemeral (EC)DH secret). If not \c NULL, this must be
* a readable buffer whose size \p input_len Bytes.
* If \c NULL, an all \c 0 array will be used instead.
* \param input_len The length of \p input in Bytes.
* \param secret_new The address of the buffer holding the new secret
* on function exit. This must be a writable buffer
* whose size matches the output size of the hash
* function represented by \p hash_alg.
* This may be the same as \p secret_old.
*
* \returns \c 0 on success.
* \returns A negative error code on failure.
*/
int mbedtls_ssl_tls1_3_evolve_secret(
mbedtls_md_type_t hash_alg,
const unsigned char *secret_old,
const unsigned char *input, size_t input_len,
unsigned char *secret_new );
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */
#endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */