Restructure outgoing CliKeyExch: Move RSA/RSA-PSK PMS generation

For RSA or RSA-PSK exchanges, the PMS contains 46 random bytes
picked by the client. These bytes are generated prior to the
writing of the ClientKeyExchange message.

This commit splits the previous function ssl_write_encrypted_pms() into
PPMS-GEN: ssl_rsa_generate_partial_pms()
PPMS-ENC: ssl_rsa_encrypt_partial_pms().
The prefix 'partial' is meant to emphasize that the generation of the PMS
is not always entirely done by these functions: For RSA-PSK e.g., the
PSK still needs to be added.

The two calls of ssl_write_encrypted_pms() in
ssl_write_client_key_exchange() will split in calls of the functions
PPMS-GEN and PPMS-ENC each, with PPMS-GEN being moved to the new
preparation function ssl_client_key_exchange_prepare() in this commit,
and PPMS-ENC being moved to ssl_client_key_exchange_write() in the
next commit.
This commit is contained in:
Hanno Becker 2018-05-23 13:08:07 +01:00
parent 6fb638b2fb
commit 01290c7240

View file

@ -2337,43 +2337,62 @@ static int ssl_parse_server_psk_hint( mbedtls_ssl_context *ssl,
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
/*
* Generate a pre-master secret and encrypt it with the server's RSA key
*/
static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
size_t offset, size_t *olen,
size_t pms_offset )
static int ssl_rsa_generate_partial_pms( mbedtls_ssl_context *ssl,
unsigned char* out,
unsigned add_length_tag )
{
int ret;
size_t len_bytes = mbedtls_ssl_get_minor_ver( ssl ) == MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2;
unsigned char *p = ssl->handshake->premaster + pms_offset;
mbedtls_pk_context *peer_pk = NULL;
if( offset + len_bytes > MBEDTLS_SSL_OUT_CONTENT_LEN )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) );
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
}
/*
* Generate (part of) the pre-master as
* Generate (part of) the pre-master secret as
* struct {
* [ uint16 length(48) ]
* ProtocolVersion client_version;
* opaque random[46];
* } PreMasterSecret;
*/
if( add_length_tag )
{
out[0] = 0;
out[1] = 48;
out += 2;
}
mbedtls_ssl_write_version( mbedtls_ssl_conf_get_max_major_ver( ssl->conf ),
mbedtls_ssl_conf_get_max_minor_ver( ssl->conf ),
ssl->conf->transport, p );
ssl->conf->transport, out );
if( ( ret = mbedtls_ssl_conf_get_frng( ssl->conf )
( ssl->conf->p_rng, p + 2, 46 ) ) != 0 )
( ssl->conf->p_rng, out + 2, 46 ) ) != 0 )
{
MBEDTLS_SSL_DEBUG_RET( 1, "f_rng", ret );
return( ret );
}
ssl->handshake->pmslen = 48;
return( 0 );
}
/*
* Encrypt the Premaster Secret it with the server's RSA key and
* write it to the provided buffer.
*/
static int ssl_rsa_encrypt_partial_pms( mbedtls_ssl_context *ssl,
unsigned char const *ppms,
unsigned char *out, size_t buflen,
size_t *olen )
{
int ret;
size_t len_bytes = mbedtls_ssl_get_minor_ver( ssl ) ==
MBEDTLS_SSL_MINOR_VERSION_0 ? 0 : 2;
mbedtls_pk_context *peer_pk = NULL;
if( buflen < len_bytes )
{
MBEDTLS_SSL_DEBUG_MSG( 1, ( "buffer too small for encrypted pms" ) );
return( MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL );
}
#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE)
/* Because the peer CRT pubkey is embedded into the handshake
@ -2403,7 +2422,7 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
}
/*
* Now write it out, encrypted
* Encrypt the part of the premaster secret and write it out.
*/
if( ! mbedtls_pk_can_do( peer_pk, MBEDTLS_PK_RSA ) )
{
@ -2413,9 +2432,8 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
}
if( ( ret = mbedtls_pk_encrypt( peer_pk,
p, ssl->handshake->pmslen,
ssl->out_msg + offset + len_bytes, olen,
MBEDTLS_SSL_OUT_CONTENT_LEN - offset - len_bytes,
ppms, 48, out + len_bytes,
olen, buflen - len_bytes,
mbedtls_ssl_conf_get_frng( ssl->conf ),
ssl->conf->p_rng ) ) != 0 )
{
@ -2427,8 +2445,8 @@ static int ssl_write_encrypted_pms( mbedtls_ssl_context *ssl,
defined(MBEDTLS_SSL_PROTO_TLS1_2)
if( len_bytes == 2 )
{
ssl->out_msg[offset+0] = (unsigned char)( *olen >> 8 );
ssl->out_msg[offset+1] = (unsigned char)( *olen );
out[0] = (unsigned char)( *olen >> 8 );
out[1] = (unsigned char)( *olen );
*olen += 2;
}
#endif
@ -3266,9 +3284,63 @@ cleanup:
return( ret );
}
static int ssl_client_key_exchange_prepare( mbedtls_ssl_context *ssl )
{
/* TBD */
int ret;
mbedtls_ssl_ciphersuite_handle_t ciphersuite_info =
mbedtls_ssl_handshake_get_ciphersuite( ssl->handshake );
((void) ret);
((void) ciphersuite_info);
/* TODO: The current API for DH and ECDH does not allow
* to separate public key generation from public key export.
*
* Ideally, we would like to pick the private (EC)DH keys
* in this preparation step, exporting the corresponding
* public key in the writing step only.
*
* The necessary extension of the (EC)DH API is being
* considered, but until then we perform the public
* generation + export in the writing step.
*
*/
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
if( mbedtls_ssl_suite_get_key_exchange( ciphersuite_info )
== MBEDTLS_KEY_EXCHANGE_RSA_PSK )
{
/* For RSA-PSK, the premaster secret is composed of
* - Length tag with value 48, encoded as a uint16
* - 2 bytes indicating the TLS version
* - 46 randomly chosen bytes
* - the chosen PSK.
* The following call takes care of all but the PSK. */
ret = ssl_rsa_generate_partial_pms( ssl, ssl->handshake->premaster,
1 /* Add length tag */ );
if( ret != 0 )
return( ret );
}
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED */
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED)
if( mbedtls_ssl_suite_get_key_exchange( ciphersuite_info )
== MBEDTLS_KEY_EXCHANGE_RSA )
{
/* For RSA-PSK, the premaster secret is composed of
* - 2 bytes indicating the TLS version
* - 46 randomly chosen bytes
* which the following call generates. */
ret = ssl_rsa_generate_partial_pms( ssl, ssl->handshake->premaster,
0 /* Omit length tag */ );
if( ret != 0 )
return( ret );
}
#endif /* MBEDTLS_KEY_EXCHANGE_RSA_ENABLED */
return( 0 );
}
static int ssl_client_key_exchange_write( mbedtls_ssl_context *ssl,
@ -3566,6 +3638,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
if( mbedtls_ssl_suite_get_key_exchange( ciphersuite_info )
== MBEDTLS_KEY_EXCHANGE_RSA_PSK )
{
/* Code for PMS generation has been moved,
* code for encryption and writing it hasn't. */
if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 2 ) ) != 0 )
return( ret );
}
@ -3644,6 +3718,8 @@ static int ssl_write_client_key_exchange( mbedtls_ssl_context *ssl )
MBEDTLS_KEY_EXCHANGE_RSA )
{
i = 4;
/* Code for PMS generation has been moved,
* code for encryption and writing it hasn't. */
if( ( ret = ssl_write_encrypted_pms( ssl, i, &n, 0 ) ) != 0 )
return( ret );
}