Commit a9ed4da8 authored by Bodo Möller's avatar Bodo Möller
Browse files

improve OAEP check

parent e1a4814c
Loading
Loading
Loading
Loading
+8 −1
Original line number Original line Diff line number Diff line
@@ -12,11 +12,18 @@
         *) applies to 0.9.6a/0.9.6b/0.9.6c and 0.9.7
         *) applies to 0.9.6a/0.9.6b/0.9.6c and 0.9.7
         +) applies to 0.9.7 only
         +) applies to 0.9.7 only


  *) Improve RSA_padding_check_PKCS1_OAEP() check again to avoid
     'wristwatch attack' using huge encoding parameters (cf.
     James H. Manger's CRYPTO 2001 paper).  Note that the
     RSA_PKCS1_OAEP_PADDING case of RSA_private_decrypt() does not use
     encoding paramters and hence was not vulnerable.
     [Bodo Moeller]

  +) Add a "destroy" handler to ENGINEs that allows structural cleanup to
  +) Add a "destroy" handler to ENGINEs that allows structural cleanup to
     be done prior to destruction. Use this to unload error strings from
     be done prior to destruction. Use this to unload error strings from
     ENGINEs that load their own error strings. NB: This adds two new API
     ENGINEs that load their own error strings. NB: This adds two new API
     functions to "get" and "set" this destroy handler in an ENGINE.
     functions to "get" and "set" this destroy handler in an ENGINE.
     [Geoff]
     [Geoff Thorpe]


  +) Alter all existing ENGINE implementations (except "openssl" and
  +) Alter all existing ENGINE implementations (except "openssl" and
     "openbsd") to dynamically instantiate their own error strings. This
     "openbsd") to dynamically instantiate their own error strings. This
+27 −12
Original line number Original line Diff line number Diff line
@@ -43,20 +43,20 @@ int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
		{
		{
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,
		   RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
		   RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
		return (0);
		return 0;
		}
		}


	if (emlen < 2 * SHA_DIGEST_LENGTH + 1)
	if (emlen < 2 * SHA_DIGEST_LENGTH + 1)
		{
		{
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_KEY_SIZE_TOO_SMALL);
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_KEY_SIZE_TOO_SMALL);
		return (0);
		return 0;
		}
		}


	dbmask = OPENSSL_malloc(emlen - SHA_DIGEST_LENGTH);
	dbmask = OPENSSL_malloc(emlen - SHA_DIGEST_LENGTH);
	if (dbmask == NULL)
	if (dbmask == NULL)
		{
		{
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
		return (0);
		return 0;
		}
		}


	to[0] = 0;
	to[0] = 0;
@@ -69,7 +69,7 @@ int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
	db[emlen - flen - SHA_DIGEST_LENGTH - 1] = 0x01;
	db[emlen - flen - SHA_DIGEST_LENGTH - 1] = 0x01;
	memcpy(db + emlen - flen - SHA_DIGEST_LENGTH, from, (unsigned int) flen);
	memcpy(db + emlen - flen - SHA_DIGEST_LENGTH, from, (unsigned int) flen);
	if (RAND_bytes(seed, SHA_DIGEST_LENGTH) <= 0)
	if (RAND_bytes(seed, SHA_DIGEST_LENGTH) <= 0)
		return (0);
		return 0;
#ifdef PKCS_TESTVECT
#ifdef PKCS_TESTVECT
	memcpy(seed,
	memcpy(seed,
	   "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f",
	   "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f",
@@ -96,13 +96,26 @@ 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];
	int bad = 0;


	if (--num < 2 * SHA_DIGEST_LENGTH + 1)
	if (--num < 2 * SHA_DIGEST_LENGTH + 1)
		/* 'num' is the length of the modulus, i.e. does not depend on the
		 * particular ciphertext. */
		goto decoding_err;
		goto decoding_err;


	lzero = num - flen;
	lzero = num - flen;
	if (lzero < 0)
	if (lzero < 0)
		goto decoding_err;
		{
		/* lzero == -1 */

		/* 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;
		}
	maskeddb = from - lzero + SHA_DIGEST_LENGTH;
	maskeddb = from - lzero + SHA_DIGEST_LENGTH;


	dblen = num - SHA_DIGEST_LENGTH;
	dblen = num - SHA_DIGEST_LENGTH;
@@ -110,7 +123,7 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
	if (db == NULL)
	if (db == NULL)
		{
		{
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
		return (-1);
		return -1;
		}
		}


	MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen);
	MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen);
@@ -123,7 +136,7 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,


	EVP_Digest((void *)param, plen, phash, NULL, EVP_sha1());
	EVP_Digest((void *)param, plen, phash, NULL, EVP_sha1());


	if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0)
	if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0 || bad)
		goto decoding_err;
		goto decoding_err;
	else
	else
		{
		{
@@ -134,6 +147,8 @@ int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
			goto decoding_err;
			goto decoding_err;
		else
		else
			{
			{
			/* everything looks OK */

			mlen = dblen - i;
			mlen = dblen - i;
			if (tlen < mlen)
			if (tlen < mlen)
				{
				{