os/ossrv/ssl/libcrypto/src/crypto/rsa/rsa_oaep.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/* crypto/rsa/rsa_oaep.c */
sl@0
     2
/* Written by Ulf Moeller. This software is distributed on an "AS IS"
sl@0
     3
   basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. */
sl@0
     4
sl@0
     5
/* EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) */
sl@0
     6
sl@0
     7
/* See Victor Shoup, "OAEP reconsidered," Nov. 2000,
sl@0
     8
 * <URL: http://www.shoup.net/papers/oaep.ps.Z>
sl@0
     9
 * for problems with the security proof for the
sl@0
    10
 * original OAEP scheme, which EME-OAEP is based on.
sl@0
    11
 * 
sl@0
    12
 * A new proof can be found in E. Fujisaki, T. Okamoto,
sl@0
    13
 * D. Pointcheval, J. Stern, "RSA-OEAP is Still Alive!",
sl@0
    14
 * Dec. 2000, <URL: http://eprint.iacr.org/2000/061/>.
sl@0
    15
 * The new proof has stronger requirements for the
sl@0
    16
 * underlying permutation: "partial-one-wayness" instead
sl@0
    17
 * of one-wayness.  For the RSA function, this is
sl@0
    18
 * an equivalent notion.
sl@0
    19
 */
sl@0
    20
sl@0
    21
sl@0
    22
#if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
sl@0
    23
#include <stdio.h>
sl@0
    24
#include "cryptlib.h"
sl@0
    25
#include <openssl/bn.h>
sl@0
    26
#include <openssl/rsa.h>
sl@0
    27
#include <openssl/evp.h>
sl@0
    28
#include <openssl/rand.h>
sl@0
    29
#include <openssl/sha.h>
sl@0
    30
sl@0
    31
EXPORT_C int MGF1(unsigned char *mask, long len,
sl@0
    32
	const unsigned char *seed, long seedlen);
sl@0
    33
sl@0
    34
EXPORT_C int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
sl@0
    35
	const unsigned char *from, int flen,
sl@0
    36
	const unsigned char *param, int plen)
sl@0
    37
	{
sl@0
    38
	int i, emlen = tlen - 1;
sl@0
    39
	unsigned char *db, *seed;
sl@0
    40
	unsigned char *dbmask, seedmask[SHA_DIGEST_LENGTH];
sl@0
    41
sl@0
    42
	if (flen > emlen - 2 * SHA_DIGEST_LENGTH - 1)
sl@0
    43
		{
sl@0
    44
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,
sl@0
    45
		   RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
sl@0
    46
		return 0;
sl@0
    47
		}
sl@0
    48
sl@0
    49
	if (emlen < 2 * SHA_DIGEST_LENGTH + 1)
sl@0
    50
		{
sl@0
    51
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_KEY_SIZE_TOO_SMALL);
sl@0
    52
		return 0;
sl@0
    53
		}
sl@0
    54
sl@0
    55
	dbmask = OPENSSL_malloc(emlen - SHA_DIGEST_LENGTH);
sl@0
    56
	if (dbmask == NULL)
sl@0
    57
		{
sl@0
    58
		RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
sl@0
    59
		return 0;
sl@0
    60
		}
sl@0
    61
sl@0
    62
	to[0] = 0;
sl@0
    63
	seed = to + 1;
sl@0
    64
	db = to + SHA_DIGEST_LENGTH + 1;
sl@0
    65
sl@0
    66
	EVP_Digest((void *)param, plen, db, NULL, EVP_sha1(), NULL);
sl@0
    67
	memset(db + SHA_DIGEST_LENGTH, 0,
sl@0
    68
		emlen - flen - 2 * SHA_DIGEST_LENGTH - 1);
sl@0
    69
	db[emlen - flen - SHA_DIGEST_LENGTH - 1] = 0x01;
sl@0
    70
	memcpy(db + emlen - flen - SHA_DIGEST_LENGTH, from, (unsigned int) flen);
sl@0
    71
	if (RAND_bytes(seed, SHA_DIGEST_LENGTH) <= 0)
sl@0
    72
		return 0;
sl@0
    73
#ifdef PKCS_TESTVECT
sl@0
    74
	memcpy(seed,
sl@0
    75
	   "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f",
sl@0
    76
	   20);
sl@0
    77
#endif
sl@0
    78
sl@0
    79
	MGF1(dbmask, emlen - SHA_DIGEST_LENGTH, seed, SHA_DIGEST_LENGTH);
sl@0
    80
	for (i = 0; i < emlen - SHA_DIGEST_LENGTH; i++)
sl@0
    81
		db[i] ^= dbmask[i];
sl@0
    82
sl@0
    83
	MGF1(seedmask, SHA_DIGEST_LENGTH, db, emlen - SHA_DIGEST_LENGTH);
sl@0
    84
	for (i = 0; i < SHA_DIGEST_LENGTH; i++)
sl@0
    85
		seed[i] ^= seedmask[i];
sl@0
    86
sl@0
    87
	OPENSSL_free(dbmask);
sl@0
    88
	return 1;
sl@0
    89
	}
sl@0
    90
sl@0
    91
EXPORT_C int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
sl@0
    92
	const unsigned char *from, int flen, int num,
sl@0
    93
	const unsigned char *param, int plen)
sl@0
    94
	{
sl@0
    95
	int i, dblen, mlen = -1;
sl@0
    96
	const unsigned char *maskeddb;
sl@0
    97
	int lzero;
sl@0
    98
	unsigned char *db = NULL, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH];
sl@0
    99
	int bad = 0;
sl@0
   100
sl@0
   101
	if (--num < 2 * SHA_DIGEST_LENGTH + 1)
sl@0
   102
		/* 'num' is the length of the modulus, i.e. does not depend on the
sl@0
   103
		 * particular ciphertext. */
sl@0
   104
		goto decoding_err;
sl@0
   105
sl@0
   106
	lzero = num - flen;
sl@0
   107
	if (lzero < 0)
sl@0
   108
		{
sl@0
   109
		/* lzero == -1 */
sl@0
   110
sl@0
   111
		/* signalling this error immediately after detection might allow
sl@0
   112
		 * for side-channel attacks (e.g. timing if 'plen' is huge
sl@0
   113
		 * -- cf. James H. Manger, "A Chosen Ciphertext Attack on RSA Optimal
sl@0
   114
		 * Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001),
sl@0
   115
		 * so we use a 'bad' flag */
sl@0
   116
		bad = 1;
sl@0
   117
		lzero = 0;
sl@0
   118
		}
sl@0
   119
	maskeddb = from - lzero + SHA_DIGEST_LENGTH;
sl@0
   120
sl@0
   121
	dblen = num - SHA_DIGEST_LENGTH;
sl@0
   122
	db = OPENSSL_malloc(dblen);
sl@0
   123
	if (db == NULL)
sl@0
   124
		{
sl@0
   125
		RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
sl@0
   126
		return -1;
sl@0
   127
		}
sl@0
   128
sl@0
   129
	MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen);
sl@0
   130
	for (i = lzero; i < SHA_DIGEST_LENGTH; i++)
sl@0
   131
		seed[i] ^= from[i - lzero];
sl@0
   132
  
sl@0
   133
	MGF1(db, dblen, seed, SHA_DIGEST_LENGTH);
sl@0
   134
	for (i = 0; i < dblen; i++)
sl@0
   135
		db[i] ^= maskeddb[i];
sl@0
   136
sl@0
   137
	EVP_Digest((void *)param, plen, phash, NULL, EVP_sha1(), NULL);
sl@0
   138
sl@0
   139
	if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0 || bad)
sl@0
   140
		goto decoding_err;
sl@0
   141
	else
sl@0
   142
		{
sl@0
   143
		for (i = SHA_DIGEST_LENGTH; i < dblen; i++)
sl@0
   144
			if (db[i] != 0x00)
sl@0
   145
				break;
sl@0
   146
		if (db[i] != 0x01 || i++ >= dblen)
sl@0
   147
			goto decoding_err;
sl@0
   148
		else
sl@0
   149
			{
sl@0
   150
			/* everything looks OK */
sl@0
   151
sl@0
   152
			mlen = dblen - i;
sl@0
   153
			if (tlen < mlen)
sl@0
   154
				{
sl@0
   155
				RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE);
sl@0
   156
				mlen = -1;
sl@0
   157
				}
sl@0
   158
			else
sl@0
   159
				memcpy(to, db + i, mlen);
sl@0
   160
			}
sl@0
   161
		}
sl@0
   162
	OPENSSL_free(db);
sl@0
   163
	return mlen;
sl@0
   164
sl@0
   165
decoding_err:
sl@0
   166
	/* to avoid chosen ciphertext attacks, the error message should not reveal
sl@0
   167
	 * which kind of decoding error happened */
sl@0
   168
	RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR);
sl@0
   169
	if (db != NULL) OPENSSL_free(db);
sl@0
   170
	return -1;
sl@0
   171
	}
sl@0
   172
sl@0
   173
EXPORT_C int PKCS1_MGF1(unsigned char *mask, long len,
sl@0
   174
	const unsigned char *seed, long seedlen, const EVP_MD *dgst)
sl@0
   175
	{
sl@0
   176
	long i, outlen = 0;
sl@0
   177
	unsigned char cnt[4];
sl@0
   178
	EVP_MD_CTX c;
sl@0
   179
	unsigned char md[EVP_MAX_MD_SIZE];
sl@0
   180
	int mdlen;
sl@0
   181
sl@0
   182
	EVP_MD_CTX_init(&c);
sl@0
   183
	mdlen = EVP_MD_size(dgst);
sl@0
   184
	for (i = 0; outlen < len; i++)
sl@0
   185
		{
sl@0
   186
		cnt[0] = (unsigned char)((i >> 24) & 255);
sl@0
   187
		cnt[1] = (unsigned char)((i >> 16) & 255);
sl@0
   188
		cnt[2] = (unsigned char)((i >> 8)) & 255;
sl@0
   189
		cnt[3] = (unsigned char)(i & 255);
sl@0
   190
		EVP_DigestInit_ex(&c,dgst, NULL);
sl@0
   191
		EVP_DigestUpdate(&c, seed, seedlen);
sl@0
   192
		EVP_DigestUpdate(&c, cnt, 4);
sl@0
   193
		if (outlen + mdlen <= len)
sl@0
   194
			{
sl@0
   195
			EVP_DigestFinal_ex(&c, mask + outlen, NULL);
sl@0
   196
			outlen += mdlen;
sl@0
   197
			}
sl@0
   198
		else
sl@0
   199
			{
sl@0
   200
			EVP_DigestFinal_ex(&c, md, NULL);
sl@0
   201
			memcpy(mask + outlen, md, len - outlen);
sl@0
   202
			outlen = len;
sl@0
   203
			}
sl@0
   204
		}
sl@0
   205
	EVP_MD_CTX_cleanup(&c);
sl@0
   206
	return 0;
sl@0
   207
	}
sl@0
   208
sl@0
   209
EXPORT_C int MGF1(unsigned char *mask, long len, const unsigned char *seed, long seedlen)
sl@0
   210
	{
sl@0
   211
	return PKCS1_MGF1(mask, len, seed, seedlen, EVP_sha1());
sl@0
   212
	}
sl@0
   213
#endif