Fix two invalid memory reads in RSA OAEP mode.

Submitted by: Ivan Nestlerode <inestlerode@us.ibm.com>
Reviewed by: steve
This commit is contained in:
Dr. Stephen Henson 2008-05-19 21:33:55 +00:00
parent 4bd4afa34e
commit 94fd382f8b
2 changed files with 23 additions and 8 deletions

View File

@ -685,6 +685,14 @@
[NTT] [NTT]
Changes between 0.9.8g and 0.9.8h [xx XXX xxxx] Changes between 0.9.8g and 0.9.8h [xx XXX xxxx]
*) RSA OAEP patches to fix two separate invalid memory reads.
The first one involves inputs when 'lzero' is greater than
'SHA_DIGEST_LENGTH' (it would read about SHA_DIGEST_LENGTH bytes
before the beginning of from). The second one involves inputs where
the 'db' section contains nothing but zeroes (there is a one-byte
invalid read after the end of 'db').
[Ivan Nesterlode <inestlerode@us.ibm.com>]
*) Add TLS session ticket callback. This allows an application to set *) Add TLS session ticket callback. This allows an application to set
TLS ticket cipher and HMAC keys rather than relying on hardcoded fixed TLS ticket cipher and HMAC keys rather than relying on hardcoded fixed

View File

@ -96,6 +96,7 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
const unsigned char *maskeddb; const unsigned char *maskeddb;
int lzero; int lzero;
unsigned char *db = NULL, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH]; unsigned char *db = NULL, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH];
unsigned char *padded_from;
int bad = 0; int bad = 0;
if (--num < 2 * SHA_DIGEST_LENGTH + 1) if (--num < 2 * SHA_DIGEST_LENGTH + 1)
@ -106,8 +107,6 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
lzero = num - flen; lzero = num - flen;
if (lzero < 0) if (lzero < 0)
{ {
/* lzero == -1 */
/* signalling this error immediately after detection might allow /* signalling this error immediately after detection might allow
* for side-channel attacks (e.g. timing if 'plen' is huge * for side-channel attacks (e.g. timing if 'plen' is huge
* -- cf. James H. Manger, "A Chosen Ciphertext Attack on RSA Optimal * -- cf. James H. Manger, "A Chosen Ciphertext Attack on RSA Optimal
@ -115,20 +114,28 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
* so we use a 'bad' flag */ * so we use a 'bad' flag */
bad = 1; bad = 1;
lzero = 0; lzero = 0;
flen = num; /* don't overflow the memcpy to padded_from */
} }
maskeddb = from - lzero + SHA_DIGEST_LENGTH;
dblen = num - SHA_DIGEST_LENGTH; dblen = num - SHA_DIGEST_LENGTH;
db = OPENSSL_malloc(dblen); db = OPENSSL_malloc(dblen + num);
if (db == NULL) if (db == NULL)
{ {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, ERR_R_MALLOC_FAILURE); RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
return -1; return -1;
} }
/* Always do this zero-padding copy (even when lzero == 0)
* to avoid leaking timing info about the value of lzero. */
padded_from = db + dblen;
memset(padded_from, 0, lzero);
memcpy(padded_from + lzero, from, flen);
maskeddb = padded_from + SHA_DIGEST_LENGTH;
MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen); MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen);
for (i = lzero; i < SHA_DIGEST_LENGTH; i++) for (i = 0; i < SHA_DIGEST_LENGTH; i++)
seed[i] ^= from[i - lzero]; seed[i] ^= padded_from[i];
MGF1(db, dblen, seed, SHA_DIGEST_LENGTH); MGF1(db, dblen, seed, SHA_DIGEST_LENGTH);
for (i = 0; i < dblen; i++) for (i = 0; i < dblen; i++)
@ -143,13 +150,13 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
for (i = SHA_DIGEST_LENGTH; i < dblen; i++) for (i = SHA_DIGEST_LENGTH; i < dblen; i++)
if (db[i] != 0x00) if (db[i] != 0x00)
break; break;
if (db[i] != 0x01 || i++ >= dblen) if (i == dblen || db[i] != 0x01)
goto decoding_err; goto decoding_err;
else else
{ {
/* everything looks OK */ /* everything looks OK */
mlen = dblen - i; mlen = dblen - ++i;
if (tlen < mlen) if (tlen < mlen)
{ {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE); RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE);