ssl_parse_encrypted_pms refactor: prepare for remote private key
Use the public key to extract metadata rather than the public key.
Don't abort early if there is no private key.
This is in preparation for allowing the private key operation to be
offloaded to an external cryptographic module.
diff --git a/library/ssl_srv.c b/library/ssl_srv.c
index 56a2662..c857815 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -3422,7 +3422,9 @@
size_t pms_offset )
{
int ret;
- size_t len = mbedtls_pk_get_len( 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;
+ 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];
@@ -3430,14 +3432,8 @@
size_t i, peer_pmslen;
unsigned int diff;
- if( ! mbedtls_pk_can_do( mbedtls_ssl_own_key( ssl ), MBEDTLS_PK_RSA ) )
- {
- MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
- return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
- }
-
/*
- * Decrypt the premaster using own private RSA key
+ * Prepare to decrypt the premaster using own private RSA key
*/
#if defined(MBEDTLS_SSL_PROTO_TLS1) || defined(MBEDTLS_SSL_PROTO_TLS1_1) || \
defined(MBEDTLS_SSL_PROTO_TLS1_2)
@@ -3466,18 +3462,31 @@
* 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.
- * Also, avoid data-dependant branches here to protect against
- * timing-based variants.
+ * 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 );
- ret = mbedtls_pk_decrypt( mbedtls_ssl_own_key( ssl ), p, len,
+ /*
+ * Decrypt the premaster secret
+ */
+ if( ! mbedtls_pk_can_do( private_key, MBEDTLS_PK_RSA ) )
+ {
+ /* */
+ MBEDTLS_SSL_DEBUG_MSG( 1, ( "got no RSA private key" ) );
+ return( MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED );
+ }
+
+ ret = mbedtls_pk_decrypt( private_key, p, len,
peer_pms, &peer_pmslen,
sizeof( peer_pms ),
ssl->conf->f_rng, ssl->conf->p_rng );
+ /* Avoid data-dependent branches while checking for invalid
+ * padding, to protect against timing-based Bleichenbacher-type
+ * attacks. */
diff = (unsigned int) ret;
diff |= peer_pmslen ^ 48;
diff |= peer_pms[0] ^ ver[0];
@@ -3508,6 +3517,8 @@
#pragma warning( pop )
#endif
+ /* Set pms to either the true or the fake PMS, without
+ * data-dependent branches. */
for( i = 0; i < ssl->handshake->pmslen; i++ )
pms[i] = ( mask & fake_pms[i] ) | ( (~mask) & peer_pms[i] );