Change operation values so they can be used as a mask.
[oweals/openssl.git] / crypto / rsa / rsa_pmeth.c
1 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
2  * project 2006.
3  */
4 /* ====================================================================
5  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer. 
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. All advertising materials mentioning features or use of this
20  *    software must display the following acknowledgment:
21  *    "This product includes software developed by the OpenSSL Project
22  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23  *
24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25  *    endorse or promote products derived from this software without
26  *    prior written permission. For written permission, please contact
27  *    licensing@OpenSSL.org.
28  *
29  * 5. Products derived from this software may not be called "OpenSSL"
30  *    nor may "OpenSSL" appear in their names without prior written
31  *    permission of the OpenSSL Project.
32  *
33  * 6. Redistributions of any form whatsoever must retain the following
34  *    acknowledgment:
35  *    "This product includes software developed by the OpenSSL Project
36  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49  * OF THE POSSIBILITY OF SUCH DAMAGE.
50  * ====================================================================
51  *
52  * This product includes cryptographic software written by Eric Young
53  * (eay@cryptsoft.com).  This product includes software written by Tim
54  * Hudson (tjh@cryptsoft.com).
55  *
56  */
57
58 #include <stdio.h>
59 #include "cryptlib.h"
60 #include <openssl/asn1t.h>
61 #include <openssl/x509.h>
62 #include <openssl/rsa.h>
63 #include <openssl/evp.h>
64 #include "evp_locl.h"
65
66 extern int int_rsa_verify(int dtype, const unsigned char *m, unsigned int m_len,
67                 unsigned char *rm, unsigned int *prm_len,
68                 const unsigned char *sigbuf, unsigned int siglen,
69                 RSA *rsa);
70
71 /* RSA pkey context structure */
72
73 typedef struct
74         {
75         /* Key gen parameters */
76         int nbits;
77         BIGNUM *pub_exp;
78         /* RSA padding mode */
79         int pad_mode;
80         /* message digest */
81         const EVP_MD *md;
82         /* Temp buffer */
83         unsigned char *tbuf;
84         } RSA_PKEY_CTX;
85
86 static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
87         {
88         RSA_PKEY_CTX *rctx;
89         rctx = OPENSSL_malloc(sizeof(RSA_PKEY_CTX));
90         if (!rctx)
91                 return 0;
92         rctx->nbits = 1024;
93         rctx->pub_exp = NULL;
94         rctx->pad_mode = RSA_PKCS1_PADDING;
95         rctx->md = NULL;
96         rctx->tbuf = NULL;
97
98         ctx->data = rctx;
99         
100         return 1;
101         }
102
103 static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk)
104         {
105         if (ctx->tbuf)
106                 return 1;
107         ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey));
108         if (!ctx->tbuf)
109                 return 0;
110         return 1;
111         }
112
113 static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx)
114         {
115         RSA_PKEY_CTX *rctx = ctx->data;
116         if (rctx)
117                 {
118                 if (rctx->pub_exp)
119                         BN_free(rctx->pub_exp);
120                 if (rctx->tbuf)
121                         OPENSSL_free(rctx->tbuf);
122                 }
123         OPENSSL_free(rctx);
124         }
125
126 static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, int *siglen,
127                                         const unsigned char *tbs, int tbslen)
128         {
129         int ret;
130         RSA_PKEY_CTX *rctx = ctx->data;
131
132         if (rctx->md)
133                 {
134                 if (tbslen != EVP_MD_size(rctx->md))
135                         {
136                         RSAerr(RSA_F_PKEY_RSA_SIGN,
137                                         RSA_R_INVALID_DIGEST_LENGTH);
138                         return -1;
139                         }
140                 if (rctx->pad_mode == RSA_X931_PADDING)
141                         {
142                         if (!setup_tbuf(rctx, ctx))
143                                 return -1;
144                         memcpy(rctx->tbuf, tbs, tbslen);
145                         rctx->tbuf[tbslen] =
146                                 RSA_X931_hash_id(EVP_MD_type(rctx->md));
147                         ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf,
148                                                 sig, ctx->pkey->pkey.rsa,
149                                                 RSA_X931_PADDING);
150                         }
151                 else if (rctx->pad_mode == RSA_PKCS1_PADDING)
152                         {
153                         unsigned int sltmp;
154                         ret = RSA_sign(EVP_MD_type(rctx->md),
155                                                 tbs, tbslen, sig, &sltmp,
156                                                         ctx->pkey->pkey.rsa);
157                         if (ret <= 0)
158                                 return ret;
159                         ret = sltmp;
160                         }
161                 else
162                         return -1;
163                 }
164         else
165                 ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa,
166                                                         rctx->pad_mode);
167         if (ret < 0)
168                 return ret;
169         *siglen = ret;
170         return 1;
171         }
172
173
174 static int pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx,
175                                         unsigned char *rout, int *routlen,
176                                         const unsigned char *sig, int siglen)
177         {
178         int ret;
179         RSA_PKEY_CTX *rctx = ctx->data;
180
181         if (rctx->md)
182                 {
183                 if (rctx->pad_mode == RSA_X931_PADDING)
184                         {
185                         if (!setup_tbuf(rctx, ctx))
186                                 return -1;
187                         ret = RSA_public_decrypt(siglen, sig,
188                                                 rctx->tbuf, ctx->pkey->pkey.rsa,
189                                                 RSA_X931_PADDING);
190                         if (ret < 1)
191                                 return 0;
192                         ret--;
193                         if (rctx->tbuf[ret] !=
194                                 RSA_X931_hash_id(EVP_MD_type(rctx->md)))
195                                 {
196                                 RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER,
197                                                 RSA_R_ALGORITHM_MISMATCH);
198                                 return 0;
199                                 }
200                         if (ret != EVP_MD_size(rctx->md))
201                                 {
202                                 RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER,
203                                         RSA_R_INVALID_DIGEST_LENGTH);
204                                 return 0;
205                                 }
206                         if (rout)
207                                 memcpy(rout, rctx->tbuf, ret);
208                         }
209                 else if (rctx->pad_mode == RSA_PKCS1_PADDING)
210                         {
211                         unsigned int sltmp;
212                         ret = int_rsa_verify(EVP_MD_type(rctx->md),
213                                                 NULL, 0, rout, &sltmp,
214                                         sig, siglen, ctx->pkey->pkey.rsa);
215                         ret = sltmp;
216                         }
217                 else
218                         return -1;
219                 }
220         else
221                 ret = RSA_public_decrypt(siglen, sig, rout, ctx->pkey->pkey.rsa,
222                                                         rctx->pad_mode);
223         if (ret < 0)
224                 return ret;
225         *routlen = ret;
226         return 1;
227         }
228
229 static int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
230                                         const unsigned char *sig, int siglen,
231                                         const unsigned char *tbs, int tbslen)
232         {
233         RSA_PKEY_CTX *rctx = ctx->data;
234         int rslen;
235         if (rctx->md)
236                 {
237                 if (rctx->pad_mode == RSA_PKCS1_PADDING)
238                         return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen,
239                                         sig, siglen, ctx->pkey->pkey.rsa);
240                 if (rctx->pad_mode == RSA_X931_PADDING)
241                         {
242                         if (pkey_rsa_verifyrecover(ctx, NULL, &rslen,
243                                         sig, siglen) <= 0)
244                                 return 0;
245                         }
246                 else
247                         return -1;
248                 }
249         else
250                 {
251                 if (!setup_tbuf(rctx, ctx))
252                         return -1;
253                 rslen = RSA_public_decrypt(siglen, sig, rctx->tbuf,
254                                         ctx->pkey->pkey.rsa, rctx->pad_mode);
255                 if (rslen <= 0)
256                         return 0;
257                 }
258
259         if ((rslen != tbslen) || memcmp(tbs, rctx->tbuf, rslen))
260                 return 0;
261
262         return 1;
263                         
264         }
265         
266
267 static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, int *outlen,
268                                         const unsigned char *in, int inlen)
269         {
270         int ret;
271         RSA_PKEY_CTX *rctx = ctx->data;
272         ret = RSA_public_encrypt(inlen, in, out, ctx->pkey->pkey.rsa,
273                                                         rctx->pad_mode);
274         if (ret < 0)
275                 return ret;
276         *outlen = ret;
277         return 1;
278         }
279
280 static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, int *outlen,
281                                         const unsigned char *in, int inlen)
282         {
283         int ret;
284         RSA_PKEY_CTX *rctx = ctx->data;
285         ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa,
286                                                         rctx->pad_mode);
287         if (ret < 0)
288                 return ret;
289         *outlen = ret;
290         return 1;
291         }
292
293 static int check_padding_md(const EVP_MD *md, int padding)
294         {
295         if (!md)
296                 return 1;
297         if (padding == RSA_NO_PADDING)
298                 {
299                 RSAerr(RSA_F_CHECK_PADDING_NID, RSA_R_INVALID_PADDING_MODE);
300                 return 0;
301                 }
302
303         if (padding == RSA_X931_PADDING)
304                 {
305                 if (RSA_X931_hash_id(EVP_MD_type(md)) == -1)
306                         {
307                         RSAerr(RSA_F_CHECK_PADDING_NID,
308                                                 RSA_R_INVALID_X931_DIGEST);
309                         return 0;
310                         }
311                 return 1;
312                 }
313
314         return 1;
315         }
316                         
317
318 static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
319         {
320         RSA_PKEY_CTX *rctx = ctx->data;
321         switch (type)
322                 {
323                 case EVP_PKEY_CTRL_RSA_PADDING:
324                 /* TODO: add PSS support */
325                 if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_X931_PADDING))
326                         {
327                         if (ctx->operation == EVP_PKEY_OP_KEYGEN)
328                                 return -2;
329                         if (!check_padding_md(rctx->md, p1))
330                                 return 0;
331                         rctx->pad_mode = p1;
332                         return 1;
333                         }
334                 return -2;
335
336                 case EVP_PKEY_CTRL_MD:
337                 if (!check_padding_md(p2, rctx->pad_mode))
338                         return 0;
339                 rctx->md = p2;
340                 return 1;
341
342                 default:
343                 return -2;
344
345                 }
346         }
347                         
348 static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
349                         const char *type, const char *value)
350         {
351         if (!strcmp(type, "rsa_padding_mode"))
352                 {
353                 int pm;
354                 if (!value)
355                         return 0;
356                 if (!strcmp(value, "pkcs1"))
357                         pm = RSA_PKCS1_PADDING;
358                 else if (!strcmp(value, "sslv23"))
359                         pm = RSA_SSLV23_PADDING;
360                 else if (!strcmp(value, "none"))
361                         pm = RSA_NO_PADDING;
362                 else if (!strcmp(value, "oeap"))
363                         pm = RSA_PKCS1_OAEP_PADDING;
364                 else if (!strcmp(value, "x931"))
365                         pm = RSA_X931_PADDING;
366                 else
367                         return -2;
368                 return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
369                 }
370         return -2;
371         }
372
373 const EVP_PKEY_METHOD rsa_pkey_meth = 
374         {
375         EVP_PKEY_RSA,
376         0,
377         pkey_rsa_init,
378         pkey_rsa_cleanup,
379
380         0,0,
381
382         0,0,
383
384         0,
385         pkey_rsa_sign,
386
387         0,
388         pkey_rsa_verify,
389
390         0,
391         pkey_rsa_verifyrecover,
392
393
394         0,0,0,0,
395
396         0,
397         pkey_rsa_encrypt,
398
399         0,
400         pkey_rsa_decrypt,
401
402         pkey_rsa_ctrl,
403         pkey_rsa_ctrl_str
404
405
406         };