6caf7955e458adb29537637c942818c1c597c248
[openssl.git] / crypto / evp / pmeth_lib.c
1 /* pmeth_lib.c */
2 /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3  * project 2006.
4  */
5 /* ====================================================================
6  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer. 
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    licensing@OpenSSL.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include "cryptlib.h"
62 #include <openssl/objects.h>
63 #include <openssl/evp.h>
64 #ifndef OPENSSL_NO_ENGINE
65 #include <openssl/engine.h>
66 #endif
67 #include "asn1_locl.h"
68 #include "evp_locl.h"
69
70 typedef int sk_cmp_fn_type(const char * const *a, const char * const *b);
71 STACK *app_pkey_methods = NULL;
72
73 extern EVP_PKEY_METHOD rsa_pkey_meth, dh_pkey_meth, dsa_pkey_meth, ec_pkey_meth;
74
75 static const EVP_PKEY_METHOD *standard_methods[] =
76         {
77         &rsa_pkey_meth,
78         &dh_pkey_meth,
79         &dsa_pkey_meth,
80         &ec_pkey_meth
81         };
82
83 static int pmeth_cmp(const EVP_PKEY_METHOD * const *a,
84                 const EVP_PKEY_METHOD * const *b)
85         {
86         return ((*a)->pkey_id - (*b)->pkey_id);
87         }
88
89 const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type)
90         {
91         EVP_PKEY_METHOD tmp, *t = &tmp, **ret;
92         tmp.pkey_id = type;
93         if (app_pkey_methods)
94                 {
95                 int idx;
96                 idx = sk_find(app_pkey_methods, (char *)&tmp);
97                 if (idx >= 0)
98                         return (EVP_PKEY_METHOD *)
99                                 sk_value(app_pkey_methods, idx);
100                 }
101         ret = (EVP_PKEY_METHOD **) OBJ_bsearch((char *)&t,
102                         (char *)standard_methods,
103                         sizeof(standard_methods)/sizeof(EVP_PKEY_METHOD *),
104                         sizeof(EVP_PKEY_METHOD *),
105                         (int (*)(const void *, const void *))pmeth_cmp);
106         if (!ret || !*ret)
107                 return NULL;
108         return *ret;
109         }
110
111 static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id)
112         {
113         EVP_PKEY_CTX *ret;
114         const EVP_PKEY_METHOD *pmeth;
115         if (id == -1)
116                 {
117                 if (!pkey || !pkey->ameth)
118                         return NULL;
119                 id = pkey->ameth->pkey_id;
120                 }
121         /* Try to find an ENGINE which implements this method */
122         if (e)
123                 {
124                 if (!ENGINE_init(e))
125                         {
126                         EVPerr(EVP_F_INT_CTX_NEW,ERR_R_ENGINE_LIB);
127                         return NULL;
128                         }
129                 else
130                         e = ENGINE_get_pkey_meth_engine(id);
131                 }
132
133         /* If an ENGINE handled this method look it up. Othewise
134          * use internal table.S
135          */
136
137         if (e)
138                 pmeth = ENGINE_get_pkey_meth(e, id);
139         else
140                 pmeth = EVP_PKEY_meth_find(id);
141
142         if (pmeth == NULL)
143                 return NULL;
144
145         ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
146         ret->engine = e;
147         ret->pmeth = pmeth;
148         ret->operation = EVP_PKEY_OP_UNDEFINED;
149         ret->pkey = pkey;
150         ret->peerkey = NULL;
151         if (pkey)
152                 CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
153         ret->data = NULL;
154
155         if (pmeth->init)
156                 {
157                 if (pmeth->init(ret) <= 0)
158                         {
159                         EVP_PKEY_CTX_free(ret);
160                         return NULL;
161                         }
162                 }
163
164         return ret;
165         }
166
167 EVP_PKEY_METHOD* EVP_PKEY_meth_new(int id, int flags)
168         {
169         EVP_PKEY_METHOD *pmeth;
170         pmeth = OPENSSL_malloc(sizeof(EVP_PKEY_METHOD));
171         if (!pmeth)
172                 return NULL;
173
174         pmeth->pkey_id = id;
175         pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC;
176
177         pmeth->init = 0;
178         pmeth->copy = 0;
179         pmeth->cleanup = 0;
180         pmeth->paramgen_init = 0;
181         pmeth->paramgen = 0;
182         pmeth->keygen_init = 0;
183         pmeth->keygen = 0;
184         pmeth->sign_init = 0;
185         pmeth->sign = 0;
186         pmeth->verify_init = 0;
187         pmeth->verify = 0;
188         pmeth->verify_recover_init = 0;
189         pmeth->verify_recover = 0;
190         pmeth->signctx_init = 0;
191         pmeth->signctx = 0;
192         pmeth->verifyctx_init = 0;
193         pmeth->verifyctx = 0;
194         pmeth->encrypt_init = 0;
195         pmeth->encrypt = 0;
196         pmeth->decrypt_init = 0;
197         pmeth->decrypt = 0;
198         pmeth->derive_init = 0;
199         pmeth->derive = 0;
200         pmeth->ctrl = 0;
201         pmeth->ctrl_str = 0;
202
203         return pmeth;
204         }
205
206 void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth)
207         {
208         if (pmeth && (pmeth->flags & EVP_PKEY_FLAG_DYNAMIC))
209                 OPENSSL_free(pmeth);
210         }
211
212 EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e)
213         {
214         return int_ctx_new(pkey, e, -1);
215         }
216
217 EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e)
218         {
219         return int_ctx_new(NULL, e, id);
220         }
221
222 EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx)
223         {
224         EVP_PKEY_CTX *rctx;
225         if (!pctx->pmeth || !pctx->pmeth->copy)
226                 return NULL;
227 #ifndef OPENSSL_NO_ENGINE
228         /* Make sure it's safe to copy a pkey context using an ENGINE */
229         if (pctx->engine && !ENGINE_init(pctx->engine))
230                 {
231                 EVPerr(EVP_F_EVP_PKEY_CTX_DUP,ERR_R_ENGINE_LIB);
232                 return 0;
233                 }
234 #endif
235         rctx = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
236         if (!rctx)
237                 return NULL;
238
239         rctx->pmeth = pctx->pmeth;
240 #ifndef OPENSSL_NO_ENGINE
241         rctx->engine = pctx->engine;
242 #endif
243
244         if (pctx->pkey)
245                 {
246                 CRYPTO_add(&pctx->pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
247                 rctx->pkey = pctx->pkey;
248                 }
249
250         if (pctx->peerkey)
251                 {
252                 CRYPTO_add(&pctx->peerkey->references,1,CRYPTO_LOCK_EVP_PKEY);
253                 rctx->peerkey = pctx->peerkey;
254                 }
255
256         rctx->data = NULL;
257         rctx->app_data = NULL;
258         rctx->operation = pctx->operation;
259
260         if (pctx->pmeth->copy(rctx, pctx) > 0)
261                 return pctx;
262
263         EVP_PKEY_CTX_free(rctx);
264         return NULL;
265
266         }
267
268 int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth)
269         {
270         if (app_pkey_methods == NULL)
271                 {
272                 app_pkey_methods = sk_new((sk_cmp_fn_type *)pmeth_cmp);
273                 if (!app_pkey_methods)
274                         return 0;
275                 }
276         if (!sk_push(app_pkey_methods, (char *)pmeth))
277                 return 0;
278         sk_sort(app_pkey_methods);
279         return 1;
280         }
281
282 void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
283         {
284         if (ctx->pmeth && ctx->pmeth->cleanup)
285                 ctx->pmeth->cleanup(ctx);
286         if (ctx->pkey)
287                 EVP_PKEY_free(ctx->pkey);
288         if (ctx->peerkey)
289                 EVP_PKEY_free(ctx->peerkey);
290 #ifndef OPENSSL_NO_ENGINE
291         if(ctx->engine)
292                 /* The EVP_PKEY_CTX we used belongs to an ENGINE, release the
293                  * functional reference we held for this reason. */
294                 ENGINE_finish(ctx->engine);
295 #endif
296         OPENSSL_free(ctx);
297         }
298
299 int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
300                                 int cmd, int p1, void *p2)
301         {
302         int ret;
303         if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl)
304                 {
305                 EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
306                 return -2;
307                 }
308         if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype))
309                 return -1;
310
311         if (ctx->operation == EVP_PKEY_OP_UNDEFINED)
312                 {
313                 EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET);
314                 return -1;
315                 }
316
317         if ((optype != -1) && !(ctx->operation & optype))
318                 {
319                 EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_INVALID_OPERATION);
320                 return -1;
321                 }
322
323         ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2);
324
325         if (ret == -2)
326                 EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED);
327
328         return ret;
329
330         }
331
332 int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx,
333                                         const char *name, const char *value)
334         {
335         if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str)
336                 {
337                 EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR,
338                                                 EVP_R_COMMAND_NOT_SUPPORTED);
339                 return -2;
340                 }
341         if (!strcmp(name, "digest"))
342                 {
343                 const EVP_MD *md;
344                 if (!value || !(md = EVP_get_digestbyname(value)))
345                         {
346                         EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR,
347                                                 EVP_R_INVALID_DIGEST);
348                         return 0;
349                         }
350                 return EVP_PKEY_CTX_set_signature_md(ctx, md);
351                 }
352         return ctx->pmeth->ctrl_str(ctx, name, value);
353         }
354
355 int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx)
356         {
357         return ctx->operation;
358         }
359
360 void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen)
361         {
362         ctx->keygen_info = dat;
363         ctx->keygen_info_count = datlen;
364         }
365
366 void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data)
367         {
368         ctx->data = data;
369         }
370
371 void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx)
372         {
373         return ctx->data;
374         }
375
376 EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx)
377         {
378         return ctx->pkey;
379         }
380
381 void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data)
382         {
383         ctx->app_data = data;
384         }
385
386 void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx)
387         {
388         return ctx->app_data;
389         }
390
391 void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
392         int (*init)(EVP_PKEY_CTX *ctx))
393         {
394         pmeth->init = init;
395         }
396
397 void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth,
398         int (*copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src))
399         {
400         pmeth->copy = copy;
401         }
402
403 void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth,
404         void (*cleanup)(EVP_PKEY_CTX *ctx))
405         {
406         pmeth->cleanup = cleanup;
407         }
408
409 void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth,
410         int (*paramgen_init)(EVP_PKEY_CTX *ctx),
411         int (*paramgen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey))
412         {
413         pmeth->paramgen_init = paramgen_init;
414         pmeth->paramgen = paramgen;
415         }
416
417 void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth,
418         int (*keygen_init)(EVP_PKEY_CTX *ctx),
419         int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey))
420         {
421         pmeth->keygen_init = keygen_init;
422         pmeth->keygen = keygen;
423         }
424
425 void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth,
426         int (*sign_init)(EVP_PKEY_CTX *ctx),
427         int (*sign)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
428                                         const unsigned char *tbs, size_t tbslen))
429         {
430         pmeth->sign_init = sign_init;
431         pmeth->sign = sign;
432         }
433
434 void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth,
435         int (*verify_init)(EVP_PKEY_CTX *ctx),
436         int (*verify)(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
437                                         const unsigned char *tbs, size_t tbslen))
438         {
439         pmeth->verify_init = verify_init;
440         pmeth->verify = verify;
441         }
442
443 void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth,
444         int (*verify_recover_init)(EVP_PKEY_CTX *ctx),
445         int (*verify_recover)(EVP_PKEY_CTX *ctx,
446                                         unsigned char *sig, size_t *siglen,
447                                         const unsigned char *tbs, size_t tbslen))
448         {
449         pmeth->verify_recover_init = verify_recover_init;
450         pmeth->verify_recover = verify_recover;
451         }
452
453 void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth,
454         int (*signctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx),
455         int (*signctx)(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
456                                         EVP_MD_CTX *mctx))
457         {
458         pmeth->signctx_init = signctx_init;
459         pmeth->signctx = signctx;
460         }
461
462 void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth,
463         int (*verifyctx_init)(EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx),
464         int (*verifyctx)(EVP_PKEY_CTX *ctx, const unsigned char *sig,int siglen,
465                                         EVP_MD_CTX *mctx))
466         {
467         pmeth->verifyctx_init = verifyctx_init;
468         pmeth->verifyctx = verifyctx;
469         }
470
471 void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth,
472         int (*encrypt_init)(EVP_PKEY_CTX *ctx),
473         int (*encrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
474                                         const unsigned char *in, size_t inlen))
475         {
476         pmeth->encrypt_init = encrypt_init;
477         pmeth->encrypt = encrypt;
478         }
479
480 void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth,
481         int (*decrypt_init)(EVP_PKEY_CTX *ctx),
482         int (*decrypt)(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
483                                         const unsigned char *in, size_t inlen))
484         {
485         pmeth->decrypt_init = decrypt_init;
486         pmeth->decrypt = decrypt;
487         }
488
489 void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth,
490         int (*derive_init)(EVP_PKEY_CTX *ctx),
491         int (*derive)(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen))
492         {
493         pmeth->derive_init = derive_init;
494         pmeth->derive = derive;
495         }
496
497 void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
498         int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2),
499         int (*ctrl_str)(EVP_PKEY_CTX *ctx, const char *type, const char *value))
500         {
501         pmeth->ctrl = ctrl;
502         pmeth->ctrl_str = ctrl_str;
503         }