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