Implementation of pkey_rsa_verify. Some constification.
[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                         }
216                 else
217                         return -1;
218                 }
219         else
220                 ret = RSA_public_decrypt(siglen, sig, rout, ctx->pkey->pkey.rsa,
221                                                         rctx->pad_mode);
222         if (ret < 0)
223                 return ret;
224         *routlen = ret;
225         return 1;
226         }
227
228 static int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
229                                         const unsigned char *sig, int siglen,
230                                         const unsigned char *tbs, int tbslen)
231         {
232         RSA_PKEY_CTX *rctx = ctx->data;
233         int rslen;
234         if (rctx->md)
235                 {
236                 if (rctx->pad_mode == RSA_PKCS1_PADDING)
237                         return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen,
238                                         sig, siglen, ctx->pkey->pkey.rsa);
239                 if (rctx->pad_mode == RSA_X931_PADDING)
240                         {
241                         if (pkey_rsa_verifyrecover(ctx, NULL, &rslen,
242                                         sig, siglen) <= 0)
243                                 return 0;
244                         }
245                 else
246                         return -1;
247                 }
248         else
249                 {
250                 if (!setup_tbuf(rctx, ctx))
251                         return -1;
252                 rslen = RSA_public_decrypt(siglen, sig, rctx->tbuf,
253                                         ctx->pkey->pkey.rsa, rctx->pad_mode);
254                 if (rslen <= 0)
255                         return 0;
256                 }
257
258         if ((rslen != tbslen) || memcmp(tbs, rctx->tbuf, rslen))
259                 return 0;
260
261         return 1;
262                         
263         }
264         
265
266 static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, int *outlen,
267                                         const unsigned char *in, int inlen)
268         {
269         int ret;
270         RSA_PKEY_CTX *rctx = ctx->data;
271         ret = RSA_public_encrypt(inlen, in, out, ctx->pkey->pkey.rsa,
272                                                         rctx->pad_mode);
273         if (ret < 0)
274                 return ret;
275         *outlen = ret;
276         return 1;
277         }
278
279 static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, int *outlen,
280                                         const unsigned char *in, int inlen)
281         {
282         int ret;
283         RSA_PKEY_CTX *rctx = ctx->data;
284         ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa,
285                                                         rctx->pad_mode);
286         if (ret < 0)
287                 return ret;
288         *outlen = ret;
289         return 1;
290         }
291
292 static int check_padding_md(const EVP_MD *md, int padding)
293         {
294         if (!md)
295                 return 1;
296         if (padding == RSA_NO_PADDING)
297                 {
298                 RSAerr(RSA_F_CHECK_PADDING_NID, RSA_R_INVALID_PADDING_MODE);
299                 return 0;
300                 }
301
302         if (padding == RSA_X931_PADDING)
303                 {
304                 if (RSA_X931_hash_id(EVP_MD_type(md)) == -1)
305                         {
306                         RSAerr(RSA_F_CHECK_PADDING_NID,
307                                                 RSA_R_INVALID_X931_DIGEST);
308                         return 0;
309                         }
310                 return 1;
311                 }
312
313         return 1;
314         }
315                         
316
317 static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
318         {
319         RSA_PKEY_CTX *rctx = ctx->data;
320         switch (type)
321                 {
322                 case EVP_PKEY_CTRL_RSA_PADDING:
323                 /* TODO: add PSS support */
324                 if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_X931_PADDING))
325                         {
326                         if (ctx->operation == EVP_PKEY_OP_KEYGEN)
327                                 return -2;
328                         if (!check_padding_md(rctx->md, p1))
329                                 return 0;
330                         rctx->pad_mode = p1;
331                         return 1;
332                         }
333                 return -2;
334
335                 case EVP_PKEY_CTRL_MD:
336                 if (!check_padding_md(p2, rctx->pad_mode))
337                         return 0;
338                 rctx->md = p2;
339                 return 1;
340
341                 default:
342                 return -2;
343
344                 }
345         }
346                         
347 static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
348                         const char *type, const char *value)
349         {
350         if (!strcmp(type, "rsa_padding_mode"))
351                 {
352                 int pm;
353                 if (!value)
354                         return 0;
355                 if (!strcmp(value, "pkcs1"))
356                         pm = RSA_PKCS1_PADDING;
357                 else if (!strcmp(value, "sslv23"))
358                         pm = RSA_SSLV23_PADDING;
359                 else if (!strcmp(value, "none"))
360                         pm = RSA_NO_PADDING;
361                 else if (!strcmp(value, "oeap"))
362                         pm = RSA_PKCS1_OAEP_PADDING;
363                 else if (!strcmp(value, "x931"))
364                         pm = RSA_X931_PADDING;
365                 else
366                         return -2;
367                 return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
368                 }
369         return -2;
370         }
371
372 const EVP_PKEY_METHOD rsa_pkey_meth = 
373         {
374         EVP_PKEY_RSA,
375         0,
376         pkey_rsa_init,
377         pkey_rsa_cleanup,
378
379         0,0,
380
381         0,0,
382
383         0,
384         pkey_rsa_sign,
385
386         0,
387         pkey_rsa_verify,
388
389         0,
390         pkey_rsa_verifyrecover,
391
392
393         0,0,0,0,
394
395         0,
396         pkey_rsa_encrypt,
397
398         0,
399         pkey_rsa_decrypt,
400
401         pkey_rsa_ctrl,
402         pkey_rsa_ctrl_str
403
404
405         };