Add helper function for calculation of TLS 1.3 PSK binder

Signed-off-by: Hanno Becker <hanno.becker@arm.com>
This commit is contained in:
Hanno Becker 2021-05-24 06:44:14 +01:00
parent a4f40a0f48
commit b7d9bad6be
2 changed files with 165 additions and 0 deletions

View file

@ -565,4 +565,136 @@ int mbedtls_ssl_tls1_3_derive_resumption_master_secret(
return( 0 );
}
static int ssl_tls1_3_calc_finished_core( mbedtls_md_type_t md_type,
unsigned char const *base_key,
unsigned char const *transcript,
unsigned char *dst )
{
const mbedtls_md_info_t* const md_info = mbedtls_md_info_from_type( md_type );
size_t const md_size = mbedtls_md_get_size( md_info );
unsigned char finished_key[MBEDTLS_MD_MAX_SIZE];
int ret;
/* We should never call this function with an unknown hash,
* but add an assertion anyway. */
if( md_info == 0 )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
/* TLS 1.3 Finished message
*
* struct {
* opaque verify_data[Hash.length];
* } Finished;
*
* verify_data =
* HMAC( finished_key,
* Hash( Handshake Context +
* Certificate* +
* CertificateVerify* )
* )
*
* finished_key =
* HKDF-Expand-Label( BaseKey, "finished", "", Hash.length )
*/
ret = mbedtls_ssl_tls1_3_hkdf_expand_label(
md_type, base_key, md_size,
MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( finished ),
NULL, 0,
finished_key, md_size );
if( ret != 0 )
goto exit;
ret = mbedtls_md_hmac( md_info, finished_key, md_size, transcript, md_size, dst );
if( ret != 0 )
goto exit;
exit:
mbedtls_platform_zeroize( finished_key, sizeof( finished_key ) );
return( ret );
}
int mbedtls_ssl_tls1_3_create_psk_binder( mbedtls_ssl_context *ssl,
const mbedtls_md_type_t md_type,
unsigned char const *psk, size_t psk_len,
int psk_type,
unsigned char const *transcript,
unsigned char *result )
{
int ret = 0;
unsigned char binder_key[MBEDTLS_MD_MAX_SIZE];
unsigned char early_secret[MBEDTLS_MD_MAX_SIZE];
mbedtls_md_info_t const *md_info = mbedtls_md_info_from_type( md_type );
size_t const md_size = mbedtls_md_get_size( md_info );
/* We should never call this function with an unknown hash,
* but add an assertion anyway. */
if( md_info == 0 )
return( MBEDTLS_ERR_SSL_INTERNAL_ERROR );
/*
* 0
* |
* v
* PSK -> HKDF-Extract = Early Secret
* |
* +-----> Derive-Secret(., "ext binder" | "res binder", "")
* | = binder_key
* v
*/
ret = mbedtls_ssl_tls1_3_evolve_secret( md_type,
NULL, /* Old secret */
psk, psk_len, /* Input */
early_secret );
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_evolve_secret", ret );
goto exit;
}
if( psk_type == MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION )
{
ret = mbedtls_ssl_tls1_3_derive_secret( md_type,
early_secret, md_size,
MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( res_binder ),
NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
binder_key, md_size );
MBEDTLS_SSL_DEBUG_MSG( 4, ( "Derive Early Secret with 'res binder'" ) );
}
else
{
ret = mbedtls_ssl_tls1_3_derive_secret( md_type,
early_secret, md_size,
MBEDTLS_SSL_TLS1_3_LBL_WITH_LEN( ext_binder ),
NULL, 0, MBEDTLS_SSL_TLS1_3_CONTEXT_UNHASHED,
binder_key, md_size );
MBEDTLS_SSL_DEBUG_MSG( 4, ( "Derive Early Secret with 'ext binder'" ) );
}
if( ret != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "mbedtls_ssl_tls1_3_derive_secret", ret );
goto exit;
}
/*
* The binding_value is computed in the same way as the Finished message
* but with the BaseKey being the binder_key.
*/
ret = ssl_tls1_3_calc_finished_core( md_type, binder_key, transcript, result );
if( ret != 0 )
goto exit;
MBEDTLS_SSL_DEBUG_BUF( 3, "psk binder", result, md_size );
exit:
mbedtls_platform_zeroize( early_secret, sizeof( early_secret ) );
mbedtls_platform_zeroize( binder_key, sizeof( binder_key ) );
return( ret );
}
#endif /* MBEDTLS_SSL_PROTO_TLS1_3_EXPERIMENTAL */

View file

@ -465,4 +465,37 @@ int mbedtls_ssl_tls1_3_evolve_secret(
const unsigned char *input, size_t input_len,
unsigned char *secret_new );
#define MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL 0
#define MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION 1
/**
* \brief Calculate a TLS 1.3 PSK binder.
*
* \param ssl The SSL context. This is used for debugging only and may
* be \c NULL if MBEDTLS_DEBUG_C is disabled.
* \param md_type The hash algorithm associated to the PSK \p psk.
* \param psk The buffer holding the PSK for which to create a binder.
* \param psk_len The size of \p psk in bytes.
* \param is_external This indicates whether the PSK \p psk is externally
* provisioned (#MBEDTLS_SSL_TLS1_3_PSK_EXTERNAL) or a
* resumption PSK (#MBEDTLS_SSL_TLS1_3_PSK_RESUMPTION).
* \param transcript The handshake transcript up to the point where the
* PSK binder calculation happens. This must be readable,
* and its size must be equal to the digest size of
* the hash algorithm represented by \p md_type.
* \param result The address at which to store the PSK binder on success.
* This must be writable, and its size must be equal to the
* digest size of the hash algorithm represented by
* \p md_type.
*
* \returns \c 0 on success.
* \returns A negative error code on failure.
*/
int mbedtls_ssl_tls1_3_create_psk_binder( mbedtls_ssl_context *ssl,
const mbedtls_md_type_t md_type,
unsigned char const *psk, size_t psk_len,
int psk_type,
unsigned char const *transcript,
unsigned char *result );
#endif /* MBEDTLS_SSL_TLS1_3_KEYS_H */