in xsec/enc/OpenSSL/OpenSSLCryptoKeyRSA.cpp [168:260]
int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
const unsigned char *from, int flen, int num,
const unsigned char *param, int plen,
const EVP_MD* digest,
const EVP_MD* mgf_digest)
{
int i, digestlen = EVP_MD_size(digest), dblen, mlen = -1;
const unsigned char *maskeddb;
int lzero;
unsigned char *db = NULL, seed[EVP_MAX_MD_SIZE], phash[EVP_MAX_MD_SIZE];
unsigned char *padded_from;
int bad = 0;
if (--num < 2 * digestlen + 1)
/* 'num' is the length of the modulus, i.e. does not depend on the
* particular ciphertext. */
goto decoding_err;
lzero = num - flen;
if (lzero < 0)
{
/* signalling this error immediately after detection might allow
* for side-channel attacks (e.g. timing if 'plen' is huge
* -- cf. James H. Manger, "A Chosen Ciphertext Attack on RSA Optimal
* Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001),
* so we use a 'bad' flag */
bad = 1;
lzero = 0;
flen = num; /* don't overflow the memcpy to padded_from */
}
dblen = num - digestlen;
db = (unsigned char*) OPENSSL_malloc(dblen + num);
if (db == NULL)
{
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
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 + digestlen;
if (MGF1(seed, digestlen, maskeddb, dblen, mgf_digest))
return -1;
for (i = 0; i < digestlen; i++)
seed[i] ^= padded_from[i];
if (MGF1(db, dblen, seed, digestlen, mgf_digest))
return -1;
for (i = 0; i < dblen; i++)
db[i] ^= maskeddb[i];
if (!EVP_Digest((void *)param, plen, phash, NULL, digest, NULL))
return -1;
if (memcmp(db, phash, digestlen) != 0 || bad)
goto decoding_err;
else
{
for (i = digestlen; i < dblen; i++)
if (db[i] != 0x00)
break;
if (i == dblen || db[i] != 0x01)
goto decoding_err;
else
{
/* everything looks OK */
mlen = dblen - ++i;
if (tlen < mlen)
{
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE);
mlen = -1;
}
else
memcpy(to, db + i, mlen);
}
}
OPENSSL_free(db);
return mlen;
decoding_err:
/* to avoid chosen ciphertext attacks, the error message should not reveal
* which kind of decoding error happened */
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR);
if (db != NULL) OPENSSL_free(db);
return -1;
}