Check PKCS 1.5 padding in a more constant-time way

(Avoid branches that depend on secret data.)
This commit is contained in:
Manuel Pégourié-Gonnard 2013-11-30 13:36:53 +01:00
parent ab44d7ecc3
commit 27290daf3b

View File

@ -757,10 +757,9 @@ int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx,
unsigned char *output, unsigned char *output,
size_t output_max_len) size_t output_max_len)
{ {
int ret, correct = 1; int ret;
size_t ilen, pad_count = 0; size_t ilen, pad_count = 0, i;
unsigned char *p, *q; unsigned char *p, bad, pad_done = 0;
unsigned char bt;
unsigned char buf[POLARSSL_MPI_MAX_SIZE]; unsigned char buf[POLARSSL_MPI_MAX_SIZE];
if( ctx->padding != RSA_PKCS_V15 ) if( ctx->padding != RSA_PKCS_V15 )
@ -779,57 +778,46 @@ int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx,
return( ret ); return( ret );
p = buf; p = buf;
bad = 0;
if( *p++ != 0 ) /*
correct = 0; * Check and get padding len in "constant-time"
*/
bad |= *p++; /* First byte must be 0 */
bt = *p++; /* This test does not depend on secret data */
if( ( bt != RSA_CRYPT && mode == RSA_PRIVATE ) || if( mode == RSA_PRIVATE )
( bt != RSA_SIGN && mode == RSA_PUBLIC ) )
{ {
correct = 0; bad |= *p++ ^ RSA_CRYPT;
/* Get padding len, but always read till end of buffer
* (minus one, for the 00 byte) */
for( i = 0; i < ilen - 3; i++ )
{
pad_done |= ( p[i] == 0 );
pad_count += ( pad_done == 0 );
} }
if( bt == RSA_CRYPT ) p += pad_count;
{ bad |= *p++; /* Must be zero */
while( *p != 0 && p < buf + ilen - 1 )
pad_count += ( *p++ != 0 );
correct &= ( *p == 0 && p < buf + ilen - 1 );
q = p;
// Also pass over all other bytes to reduce timing differences
//
while ( q < buf + ilen - 1 )
pad_count += ( *q++ != 0 );
// Prevent compiler optimization of pad_count
//
correct |= pad_count & 0x100000; /* Always 0 unless 1M bit keys */
p++;
} }
else else
{ {
while( *p == 0xFF && p < buf + ilen - 1 ) bad |= *p++ ^ RSA_SIGN;
pad_count += ( *p++ == 0xFF );
correct &= ( *p == 0 && p < buf + ilen - 1 ); /* Get padding len, but always read till end of buffer
* (minus one, for the 00 byte) */
q = p; for( i = 0; i < ilen - 3; i++ )
{
// Also pass over all other bytes to reduce timing differences pad_done |= ( p[i] == 0xFF );
// pad_count += ( pad_done == 0 );
while ( q < buf + ilen - 1 )
pad_count += ( *q++ != 0 );
// Prevent compiler optimization of pad_count
//
correct |= pad_count & 0x100000; /* Always 0 unless 1M bit keys */
p++;
} }
if( correct == 0 ) p += pad_count;
bad |= *p++; /* Must be zero */
}
if( bad )
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)