mirror of
https://github.com/yuzu-emu/mbedtls.git
synced 2024-11-29 17:04:16 +01:00
ssl_parse_encrypted_pms refactor: prepare, decrypt, return
Reorganize ssl_parse_encrypted_pms so that it first prepares the ciphertext to decrypt, then decrypts it, then returns either the decrypted premaster secret or random data in an appropriate manner. This is in preparation for allowing the private key operation to be offloaded to an external cryptographic module which can operate asynchronously. The refactored code no longer calculates state before the decryption that needs to be saved until after the decryption, which allows the decryption to be started and later resumed.
This commit is contained in:
parent
422ccabe29
commit
bcd98a5306
@ -3416,21 +3416,17 @@ static int ssl_parse_client_dh_public( mbedtls_ssl_context *ssl, unsigned char *
|
|||||||
|
|
||||||
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
|
#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \
|
||||||
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
|
defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED)
|
||||||
static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
|
static int ssl_decrypt_encrypted_pms( mbedtls_ssl_context *ssl,
|
||||||
const unsigned char *p,
|
const unsigned char *p,
|
||||||
const unsigned char *end,
|
const unsigned char *end,
|
||||||
size_t pms_offset )
|
unsigned char *peer_pms,
|
||||||
|
size_t *peer_pmslen,
|
||||||
|
size_t peer_pmssize )
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
|
mbedtls_pk_context *private_key = mbedtls_ssl_own_key( ssl );
|
||||||
mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk;
|
mbedtls_pk_context *public_key = &mbedtls_ssl_own_cert( ssl )->pk;
|
||||||
size_t len = mbedtls_pk_get_len( public_key );
|
size_t len = mbedtls_pk_get_len( public_key );
|
||||||
unsigned char *pms = ssl->handshake->premaster + pms_offset;
|
|
||||||
unsigned char ver[2];
|
|
||||||
unsigned char fake_pms[48], peer_pms[48];
|
|
||||||
unsigned char mask;
|
|
||||||
size_t i, peer_pmslen;
|
|
||||||
unsigned int diff;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prepare to decrypt the premaster using own private RSA key
|
* Prepare to decrypt the premaster using own private RSA key
|
||||||
@ -3454,21 +3450,6 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
|
|||||||
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
|
return( MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE );
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_ssl_write_version( ssl->handshake->max_major_ver,
|
|
||||||
ssl->handshake->max_minor_ver,
|
|
||||||
ssl->conf->transport, ver );
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
|
|
||||||
* must not cause the connection to end immediately; instead, send a
|
|
||||||
* bad_record_mac later in the handshake.
|
|
||||||
* To protect against timing-based variants, always generate the fake
|
|
||||||
* premaster secret, so as to avoid data-dependant branches.
|
|
||||||
*/
|
|
||||||
ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) );
|
|
||||||
if( ret != 0 )
|
|
||||||
return( ret );
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Decrypt the premaster secret
|
* Decrypt the premaster secret
|
||||||
*/
|
*/
|
||||||
@ -3480,9 +3461,48 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = mbedtls_pk_decrypt( private_key, p, len,
|
ret = mbedtls_pk_decrypt( private_key, p, len,
|
||||||
peer_pms, &peer_pmslen,
|
peer_pms, peer_pmslen, peer_pmssize,
|
||||||
sizeof( peer_pms ),
|
|
||||||
ssl->conf->f_rng, ssl->conf->p_rng );
|
ssl->conf->f_rng, ssl->conf->p_rng );
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl,
|
||||||
|
const unsigned char *p,
|
||||||
|
const unsigned char *end,
|
||||||
|
size_t pms_offset )
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
unsigned char *pms = ssl->handshake->premaster + pms_offset;
|
||||||
|
unsigned char ver[2];
|
||||||
|
unsigned char fake_pms[48], peer_pms[48];
|
||||||
|
unsigned char mask;
|
||||||
|
size_t i, peer_pmslen;
|
||||||
|
unsigned int diff;
|
||||||
|
|
||||||
|
ret = ssl_decrypt_encrypted_pms( ssl, p, end,
|
||||||
|
peer_pms,
|
||||||
|
&peer_pmslen,
|
||||||
|
sizeof( peer_pms ) );
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Protection against Bleichenbacher's attack: invalid PKCS#1 v1.5 padding
|
||||||
|
* must not cause the connection to end immediately; instead, send a
|
||||||
|
* bad_record_mac later in the handshake.
|
||||||
|
* To protect against timing-based variants of the attack, we must
|
||||||
|
* not have any branch that depends on whether the decryption was
|
||||||
|
* successful. In particular, always generate the fake premaster secret,
|
||||||
|
* regardless of whether it will ultimately influence the output or not.
|
||||||
|
*/
|
||||||
|
ret = ssl->conf->f_rng( ssl->conf->p_rng, fake_pms, sizeof( fake_pms ) );
|
||||||
|
if( ret != 0 )
|
||||||
|
{
|
||||||
|
/* It's ok to abort on an RNG failure, since this does not */
|
||||||
|
return( ret );
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_ssl_write_version( ssl->handshake->max_major_ver,
|
||||||
|
ssl->handshake->max_minor_ver,
|
||||||
|
ssl->conf->transport, ver );
|
||||||
|
|
||||||
/* Avoid data-dependent branches while checking for invalid
|
/* Avoid data-dependent branches while checking for invalid
|
||||||
* padding, to protect against timing-based Bleichenbacher-type
|
* padding, to protect against timing-based Bleichenbacher-type
|
||||||
|
Loading…
Reference in New Issue
Block a user