Check OAEP padding in a more constant-time way

This commit is contained in:
Manuel Pégourié-Gonnard 2013-11-29 12:49:44 +01:00
parent a5cfc35db2
commit ab44d7ecc3

View File

@ -646,8 +646,8 @@ int rsa_rsaes_oaep_decrypt( rsa_context *ctx,
size_t output_max_len ) size_t output_max_len )
{ {
int ret; int ret;
size_t ilen; size_t ilen, i, pad_len;
unsigned char *p; unsigned char *p, bad, pad_done;
unsigned char buf[POLARSSL_MPI_MAX_SIZE]; unsigned char buf[POLARSSL_MPI_MAX_SIZE];
unsigned char lhash[POLARSSL_MD_MAX_SIZE]; unsigned char lhash[POLARSSL_MD_MAX_SIZE];
unsigned int hlen; unsigned int hlen;
@ -680,7 +680,7 @@ int rsa_rsaes_oaep_decrypt( rsa_context *ctx,
return( ret ); return( ret );
/* /*
* Unmask data * Unmask data and generate lHash
*/ */
hlen = md_get_size( md_info ); hlen = md_get_size( md_info );
@ -700,28 +700,39 @@ int rsa_rsaes_oaep_decrypt( rsa_context *ctx,
md_free_ctx( &md_ctx ); md_free_ctx( &md_ctx );
/* /*
* Check contents * Check contents, in "constant-time"
*/ */
p = buf; p = buf;
bad = 0;
if( *p++ != 0 ) bad |= *p++; /* First byte must be 0 */
return( POLARSSL_ERR_RSA_INVALID_PADDING );
p += hlen; /* Skip seed */ p += hlen; /* Skip seed */
/* Check lHash */ /* Check lHash */
if( memcmp( lhash, p, hlen ) != 0 ) for( i = 0; i < hlen; i++ )
return( POLARSSL_ERR_RSA_INVALID_PADDING ); bad |= lhash[i] ^ *p++;
p += hlen; /* Get zero-padding len, but always read till end of buffer
* (minus one, for the 01 byte) */
pad_len = 0;
pad_done = 0;
for( i = 0; i < ilen - 2 * hlen - 2; i++ )
{
pad_done |= p[i];
pad_len += ( pad_done == 0 );
}
while( *p == 0 && p < buf + ilen ) p += pad_len;
p++; bad |= *p++ ^ 0x01;
if( p == buf + ilen ) /*
return( POLARSSL_ERR_RSA_INVALID_PADDING ); * The only information "leaked" is whether the padding was correct or not
* (eg, no data is copied if it was not correct). This meets the
if( *p++ != 0x01 ) * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between
* the different error conditions.
*/
if( bad != 0 )
return( POLARSSL_ERR_RSA_INVALID_PADDING ); return( POLARSSL_ERR_RSA_INVALID_PADDING );
if (ilen - (p - buf) > output_max_len) if (ilen - (p - buf) > output_max_len)