RSA: wipe stack buffers

The RSA private key functions rsa_rsaes_pkcs1_v15_decrypt and
rsa_rsaes_oaep_decrypt put sensitive data (decryption results) on the
stack. Wipe it before returning.

Thanks to Laurent Simon for reporting this issue.
This commit is contained in:
Gilles Peskine 2017-03-23 14:37:37 +01:00 committed by Simon Butcher
parent 77da95357f
commit 4a7f6a0ddb
2 changed files with 38 additions and 9 deletions

View File

@ -3,6 +3,9 @@ mbed TLS ChangeLog (Sorted per branch, date)
= mbed TLS 2.x.x branch released xxxx-xx-xx = mbed TLS 2.x.x branch released xxxx-xx-xx
Security Security
* Wipe stack buffers in RSA private key operations
(rsa_rsaes_pkcs1_v15_decrypt(), rsa_rsaes_oaep_decrypt).
Found by Laurent Simon.
* Add exponent blinding to RSA private operations as a countermeasure * Add exponent blinding to RSA private operations as a countermeasure
against side-channel attacks like the cache attack described in against side-channel attacks like the cache attack described in
https://arxiv.org/abs/1702.08719v2. https://arxiv.org/abs/1702.08719v2.

View File

@ -66,6 +66,11 @@
#define mbedtls_free free #define mbedtls_free free
#endif #endif
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0;
}
/* /*
* Initialize an RSA context * Initialize an RSA context
*/ */
@ -824,7 +829,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
: mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf );
if( ret != 0 ) if( ret != 0 )
return( ret ); goto cleanup;
/* /*
* Unmask data and generate lHash * Unmask data and generate lHash
@ -833,7 +838,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 )
{ {
mbedtls_md_free( &md_ctx ); mbedtls_md_free( &md_ctx );
return( ret ); goto cleanup;
} }
@ -884,15 +889,26 @@ int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx,
* the different error conditions. * the different error conditions.
*/ */
if( bad != 0 ) if( bad != 0 )
return( MBEDTLS_ERR_RSA_INVALID_PADDING ); {
ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
goto cleanup;
}
if( ilen - ( p - buf ) > output_max_len ) if( ilen - ( p - buf ) > output_max_len )
return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); {
ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
goto cleanup;
}
*olen = ilen - (p - buf); *olen = ilen - (p - buf);
memcpy( output, p, *olen ); memcpy( output, p, *olen );
ret = 0;
return( 0 ); cleanup:
mbedtls_zeroize( buf, sizeof( buf ) );
mbedtls_zeroize( lhash, sizeof( lhash ) );
return( ret );
} }
#endif /* MBEDTLS_PKCS1_V21 */ #endif /* MBEDTLS_PKCS1_V21 */
@ -926,7 +942,7 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
: mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf );
if( ret != 0 ) if( ret != 0 )
return( ret ); goto cleanup;
p = buf; p = buf;
bad = 0; bad = 0;
@ -971,15 +987,25 @@ int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx,
bad |= ( pad_count < 8 ); bad |= ( pad_count < 8 );
if( bad ) if( bad )
return( MBEDTLS_ERR_RSA_INVALID_PADDING ); {
ret = MBEDTLS_ERR_RSA_INVALID_PADDING;
goto cleanup;
}
if( ilen - ( p - buf ) > output_max_len ) if( ilen - ( p - buf ) > output_max_len )
return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); {
ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
goto cleanup;
}
*olen = ilen - (p - buf); *olen = ilen - (p - buf);
memcpy( output, p, *olen ); memcpy( output, p, *olen );
ret = 0;
return( 0 ); cleanup:
mbedtls_zeroize( buf, sizeof( buf ) );
return( ret );
} }
#endif /* MBEDTLS_PKCS1_V15 */ #endif /* MBEDTLS_PKCS1_V15 */