Import OpenSSL-1.0.0e.
[dragonfly.git] / crypto / openssl / 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
22 #if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
23 #include <stdio.h>
24 #include "cryptlib.h"
25 #include <openssl/bn.h>
26 #include <openssl/rsa.h>
27 #include <openssl/evp.h>
28 #include <openssl/rand.h>
29 #include <openssl/sha.h>
30
31 static int MGF1(unsigned char *mask, long len,
32         const unsigned char *seed, long seedlen);
33
34 int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
35         const unsigned char *from, int flen,
36         const unsigned char *param, int plen)
37         {
38         int i, emlen = tlen - 1;
39         unsigned char *db, *seed;
40         unsigned char *dbmask, seedmask[SHA_DIGEST_LENGTH];
41
42         if (flen > emlen - 2 * SHA_DIGEST_LENGTH - 1)
43                 {
44                 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP,
45                    RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
46                 return 0;
47                 }
48
49         if (emlen < 2 * SHA_DIGEST_LENGTH + 1)
50                 {
51                 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, RSA_R_KEY_SIZE_TOO_SMALL);
52                 return 0;
53                 }
54
55         to[0] = 0;
56         seed = to + 1;
57         db = to + SHA_DIGEST_LENGTH + 1;
58
59         EVP_Digest((void *)param, plen, db, NULL, EVP_sha1(), NULL);
60         memset(db + SHA_DIGEST_LENGTH, 0,
61                 emlen - flen - 2 * SHA_DIGEST_LENGTH - 1);
62         db[emlen - flen - SHA_DIGEST_LENGTH - 1] = 0x01;
63         memcpy(db + emlen - flen - SHA_DIGEST_LENGTH, from, (unsigned int) flen);
64         if (RAND_bytes(seed, SHA_DIGEST_LENGTH) <= 0)
65                 return 0;
66 #ifdef PKCS_TESTVECT
67         memcpy(seed,
68            "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f",
69            20);
70 #endif
71
72         dbmask = OPENSSL_malloc(emlen - SHA_DIGEST_LENGTH);
73         if (dbmask == NULL)
74                 {
75                 RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
76                 return 0;
77                 }
78
79         if (MGF1(dbmask, emlen - SHA_DIGEST_LENGTH, seed, SHA_DIGEST_LENGTH) < 0)
80                 return 0;
81         for (i = 0; i < emlen - SHA_DIGEST_LENGTH; i++)
82                 db[i] ^= dbmask[i];
83
84         if (MGF1(seedmask, SHA_DIGEST_LENGTH, db, emlen - SHA_DIGEST_LENGTH) < 0)
85                 return 0;
86         for (i = 0; i < SHA_DIGEST_LENGTH; i++)
87                 seed[i] ^= seedmask[i];
88
89         OPENSSL_free(dbmask);
90         return 1;
91         }
92
93 int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
94         const unsigned char *from, int flen, int num,
95         const unsigned char *param, int plen)
96         {
97         int i, dblen, mlen = -1;
98         const unsigned char *maskeddb;
99         int lzero;
100         unsigned char *db = NULL, seed[SHA_DIGEST_LENGTH], phash[SHA_DIGEST_LENGTH];
101         unsigned char *padded_from;
102         int bad = 0;
103
104         if (--num < 2 * SHA_DIGEST_LENGTH + 1)
105                 /* 'num' is the length of the modulus, i.e. does not depend on the
106                  * particular ciphertext. */
107                 goto decoding_err;
108
109         lzero = num - flen;
110         if (lzero < 0)
111                 {
112                 /* signalling this error immediately after detection might allow
113                  * for side-channel attacks (e.g. timing if 'plen' is huge
114                  * -- cf. James H. Manger, "A Chosen Ciphertext Attack on RSA Optimal
115                  * Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001),
116                  * so we use a 'bad' flag */
117                 bad = 1;
118                 lzero = 0;
119                 flen = num; /* don't overflow the memcpy to padded_from */
120                 }
121
122         dblen = num - SHA_DIGEST_LENGTH;
123         db = OPENSSL_malloc(dblen + num);
124         if (db == NULL)
125                 {
126                 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, ERR_R_MALLOC_FAILURE);
127                 return -1;
128                 }
129
130         /* Always do this zero-padding copy (even when lzero == 0)
131          * to avoid leaking timing info about the value of lzero. */
132         padded_from = db + dblen;
133         memset(padded_from, 0, lzero);
134         memcpy(padded_from + lzero, from, flen);
135
136         maskeddb = padded_from + SHA_DIGEST_LENGTH;
137
138         if (MGF1(seed, SHA_DIGEST_LENGTH, maskeddb, dblen))
139                 return -1;
140         for (i = 0; i < SHA_DIGEST_LENGTH; i++)
141                 seed[i] ^= padded_from[i];
142   
143         if (MGF1(db, dblen, seed, SHA_DIGEST_LENGTH))
144                 return -1;
145         for (i = 0; i < dblen; i++)
146                 db[i] ^= maskeddb[i];
147
148         EVP_Digest((void *)param, plen, phash, NULL, EVP_sha1(), NULL);
149
150         if (memcmp(db, phash, SHA_DIGEST_LENGTH) != 0 || bad)
151                 goto decoding_err;
152         else
153                 {
154                 for (i = SHA_DIGEST_LENGTH; i < dblen; i++)
155                         if (db[i] != 0x00)
156                                 break;
157                 if (i == dblen || db[i] != 0x01)
158                         goto decoding_err;
159                 else
160                         {
161                         /* everything looks OK */
162
163                         mlen = dblen - ++i;
164                         if (tlen < mlen)
165                                 {
166                                 RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_DATA_TOO_LARGE);
167                                 mlen = -1;
168                                 }
169                         else
170                                 memcpy(to, db + i, mlen);
171                         }
172                 }
173         OPENSSL_free(db);
174         return mlen;
175
176 decoding_err:
177         /* to avoid chosen ciphertext attacks, the error message should not reveal
178          * which kind of decoding error happened */
179         RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP, RSA_R_OAEP_DECODING_ERROR);
180         if (db != NULL) OPENSSL_free(db);
181         return -1;
182         }
183
184 int PKCS1_MGF1(unsigned char *mask, long len,
185         const unsigned char *seed, long seedlen, const EVP_MD *dgst)
186         {
187         long i, outlen = 0;
188         unsigned char cnt[4];
189         EVP_MD_CTX c;
190         unsigned char md[EVP_MAX_MD_SIZE];
191         int mdlen;
192         int rv = -1;
193
194         EVP_MD_CTX_init(&c);
195         mdlen = EVP_MD_size(dgst);
196         if (mdlen < 0)
197                 goto err;
198         for (i = 0; outlen < len; i++)
199                 {
200                 cnt[0] = (unsigned char)((i >> 24) & 255);
201                 cnt[1] = (unsigned char)((i >> 16) & 255);
202                 cnt[2] = (unsigned char)((i >> 8)) & 255;
203                 cnt[3] = (unsigned char)(i & 255);
204                 if (!EVP_DigestInit_ex(&c,dgst, NULL)
205                         || !EVP_DigestUpdate(&c, seed, seedlen)
206                         || !EVP_DigestUpdate(&c, cnt, 4))
207                         goto err;
208                 if (outlen + mdlen <= len)
209                         {
210                         if (!EVP_DigestFinal_ex(&c, mask + outlen, NULL))
211                                 goto err;
212                         outlen += mdlen;
213                         }
214                 else
215                         {
216                         if (!EVP_DigestFinal_ex(&c, md, NULL))
217                                 goto err;
218                         memcpy(mask + outlen, md, len - outlen);
219                         outlen = len;
220                         }
221                 }
222         rv = 0;
223         err:
224         EVP_MD_CTX_cleanup(&c);
225         return rv;
226         }
227
228 static int MGF1(unsigned char *mask, long len, const unsigned char *seed,
229                  long seedlen)
230         {
231         return PKCS1_MGF1(mask, len, seed, seedlen, EVP_sha1());
232         }
233 #endif