a0db5ee2fa6f5bf0c129a8b9704e6e09b76794de
[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         /* nid for message digest */
81         int md_nid;
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_nid = NID_undef;
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_nid != NID_undef)
133                 {
134
135                 if (rctx->pad_mode == RSA_X931_PADDING)
136                         {
137                         if (!setup_tbuf(rctx, ctx))
138                                 return -1;
139                         memcpy(rctx->tbuf, tbs, tbslen);
140                         rctx->tbuf[tbslen] = RSA_X931_hash_id(rctx->md_nid);
141                         ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf,
142                                                 sig, ctx->pkey->pkey.rsa,
143                                                 RSA_X931_PADDING);
144                         }
145                 else if (rctx->pad_mode == RSA_PKCS1_PADDING)
146                         {
147                         unsigned int sltmp;
148                         ret = RSA_sign(rctx->md_nid, tbs, tbslen, sig, &sltmp,
149                                                         ctx->pkey->pkey.rsa);
150                         }
151                 else
152                         return -1;
153                 }
154         else
155                 ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa,
156                                                         rctx->pad_mode);
157         if (ret < 0)
158                 return ret;
159         *siglen = ret;
160         return 1;
161         }
162
163
164 static int pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx,
165                                         unsigned char *sig, int *siglen,
166                                         const unsigned char *tbs, int tbslen)
167         {
168         int ret;
169         RSA_PKEY_CTX *rctx = ctx->data;
170
171         if (rctx->md_nid != NID_undef)
172                 {
173                 if (rctx->pad_mode == RSA_X931_PADDING)
174                         {
175                         if (!setup_tbuf(rctx, ctx))
176                                 return -1;
177                         ret = RSA_public_decrypt(tbslen, tbs,
178                                                 rctx->tbuf, ctx->pkey->pkey.rsa,
179                                                 RSA_X931_PADDING);
180                         if (ret < 1)
181                                 return 0;
182                         ret--;
183                         if (rctx->tbuf[ret] != RSA_X931_hash_id(rctx->md_nid))
184                                 {
185                                 RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER,
186                                                 RSA_R_ALGORITHM_MISMATCH);
187                                 return 0;
188                                 }
189                         memcpy(sig, rctx->tbuf, ret);
190                         }
191                 else if (rctx->pad_mode == RSA_PKCS1_PADDING)
192                         {
193                         unsigned int sltmp;
194                         ret = int_rsa_verify(rctx->md_nid, NULL, 0, sig, &sltmp,
195                                         tbs, tbslen, ctx->pkey->pkey.rsa);
196                         }
197                 else
198                         return -1;
199                 }
200         else
201                 ret = RSA_public_decrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa,
202                                                         rctx->pad_mode);
203         if (ret < 0)
204                 return ret;
205         *siglen = ret;
206         return 1;
207         }
208
209 static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, int *outlen,
210                                         const unsigned char *in, int inlen)
211         {
212         int ret;
213         RSA_PKEY_CTX *rctx = ctx->data;
214         ret = RSA_public_encrypt(inlen, in, out, ctx->pkey->pkey.rsa,
215                                                         rctx->pad_mode);
216         if (ret < 0)
217                 return ret;
218         *outlen = ret;
219         return 1;
220         }
221
222 static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, int *outlen,
223                                         const unsigned char *in, int inlen)
224         {
225         int ret;
226         RSA_PKEY_CTX *rctx = ctx->data;
227         ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa,
228                                                         rctx->pad_mode);
229         if (ret < 0)
230                 return ret;
231         *outlen = ret;
232         return 1;
233         }
234
235 static int check_padding_nid(int nid, int padding)
236         {
237         if (nid == NID_undef)
238                 return 1;
239         if (padding == RSA_NO_PADDING)
240                 {
241                 RSAerr(RSA_F_CHECK_PADDING_NID, RSA_R_INVALID_PADDING_MODE);
242                 return 0;
243                 }
244
245         if (padding == RSA_X931_PADDING)
246                 {
247                 if (RSA_X931_hash_id(nid) == -1)
248                         {
249                         RSAerr(RSA_F_CHECK_PADDING_NID,
250                                                 RSA_R_INVALID_X931_DIGEST);
251                         return 0;
252                         }
253                 return 1;
254                 }
255
256         return 1;
257         }
258                         
259
260 static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
261         {
262         RSA_PKEY_CTX *rctx = ctx->data;
263         switch (type)
264                 {
265                 case EVP_PKEY_CTRL_RSA_PADDING:
266                 /* TODO: add PSS support */
267                 if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_X931_PADDING))
268                         {
269                         if (ctx->operation == EVP_PKEY_OP_KEYGEN)
270                                 return -2;
271                         if (!check_padding_nid(rctx->md_nid, p1))
272                                 return 0;
273                         rctx->pad_mode = p1;
274                         return 1;
275                         }
276                 return -2;
277
278                 case EVP_PKEY_CTRL_MD_NID:
279                 if (!check_padding_nid(p1, rctx->pad_mode))
280                         return 0;
281                 rctx->md_nid = p1;
282                 return 1;
283
284                 default:
285                 return -2;
286
287                 }
288         }
289                         
290 static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
291                         const char *type, const char *value)
292         {
293         if (!strcmp(type, "rsa_padding_mode"))
294                 {
295                 int pm;
296                 if (!value)
297                         return 0;
298                 if (!strcmp(value, "pkcs1"))
299                         pm = RSA_PKCS1_PADDING;
300                 else if (!strcmp(value, "sslv23"))
301                         pm = RSA_SSLV23_PADDING;
302                 else if (!strcmp(value, "none"))
303                         pm = RSA_NO_PADDING;
304                 else if (!strcmp(value, "oeap"))
305                         pm = RSA_PKCS1_OAEP_PADDING;
306                 else if (!strcmp(value, "x931"))
307                         pm = RSA_X931_PADDING;
308                 else
309                         return -2;
310                 return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
311                 }
312         return -2;
313         }
314
315 const EVP_PKEY_METHOD rsa_pkey_meth = 
316         {
317         EVP_PKEY_RSA,
318         0,
319         pkey_rsa_init,
320         pkey_rsa_cleanup,
321
322         0,0,
323
324         0,0,
325
326         0,
327         pkey_rsa_sign,
328
329         0,0,
330
331         0,
332         pkey_rsa_verifyrecover,
333
334
335         0,0,0,0,
336
337         0,
338         pkey_rsa_encrypt,
339
340         0,
341         pkey_rsa_decrypt,
342
343         pkey_rsa_ctrl,
344         pkey_rsa_ctrl_str
345
346
347         };