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