Run util/openssl-format-source -v -c .
[openssl.git] / crypto / asn1 / ameth_lib.c
1 /*
2  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
3  * 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 "cryptlib.h"
61 #include <openssl/asn1t.h>
62 #include <openssl/x509.h>
63 #ifndef OPENSSL_NO_ENGINE
64 # include <openssl/engine.h>
65 #endif
66 #include "asn1_locl.h"
67
68 extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
69 extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
70 extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
71 extern const EVP_PKEY_ASN1_METHOD dhx_asn1_meth;
72 extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
73 extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
74 extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;
75
76 /* Keep this sorted in type order !! */
77 static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
78 #ifndef OPENSSL_NO_RSA
79     &rsa_asn1_meths[0],
80     &rsa_asn1_meths[1],
81 #endif
82 #ifndef OPENSSL_NO_DH
83     &dh_asn1_meth,
84 #endif
85 #ifndef OPENSSL_NO_DSA
86     &dsa_asn1_meths[0],
87     &dsa_asn1_meths[1],
88     &dsa_asn1_meths[2],
89     &dsa_asn1_meths[3],
90     &dsa_asn1_meths[4],
91 #endif
92 #ifndef OPENSSL_NO_EC
93     &eckey_asn1_meth,
94 #endif
95     &hmac_asn1_meth,
96     &cmac_asn1_meth,
97 #ifndef OPENSSL_NO_DH
98     &dhx_asn1_meth
99 #endif
100 };
101
102 typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
103 DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD)
104 static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL;
105
106 #ifdef TEST
107 void main()
108 {
109     int i;
110     for (i = 0;
111          i < sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *); i++)
112         fprintf(stderr, "Number %d id=%d (%s)\n", i,
113                 standard_methods[i]->pkey_id,
114                 OBJ_nid2sn(standard_methods[i]->pkey_id));
115 }
116 #endif
117
118 DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
119                            const EVP_PKEY_ASN1_METHOD *, ameth);
120
121 static int ameth_cmp(const EVP_PKEY_ASN1_METHOD *const *a,
122                      const EVP_PKEY_ASN1_METHOD *const *b)
123 {
124     return ((*a)->pkey_id - (*b)->pkey_id);
125 }
126
127 IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
128                              const EVP_PKEY_ASN1_METHOD *, ameth);
129
130 int EVP_PKEY_asn1_get_count(void)
131 {
132     int num = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *);
133     if (app_methods)
134         num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods);
135     return num;
136 }
137
138 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
139 {
140     int num = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *);
141     if (idx < 0)
142         return NULL;
143     if (idx < num)
144         return standard_methods[idx];
145     idx -= num;
146     return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
147 }
148
149 static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
150 {
151     EVP_PKEY_ASN1_METHOD tmp;
152     const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
153     tmp.pkey_id = type;
154     if (app_methods) {
155         int idx;
156         idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp);
157         if (idx >= 0)
158             return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
159     }
160     ret = OBJ_bsearch_ameth(&t, standard_methods, sizeof(standard_methods)
161                             / sizeof(EVP_PKEY_ASN1_METHOD *));
162     if (!ret || !*ret)
163         return NULL;
164     return *ret;
165 }
166
167 /*
168  * Find an implementation of an ASN1 algorithm. If 'pe' is not NULL also
169  * search through engines and set *pe to a functional reference to the engine
170  * implementing 'type' or NULL if no engine implements it.
171  */
172
173 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type)
174 {
175     const EVP_PKEY_ASN1_METHOD *t;
176
177     for (;;) {
178         t = pkey_asn1_find(type);
179         if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS))
180             break;
181         type = t->pkey_base_id;
182     }
183     if (pe) {
184 #ifndef OPENSSL_NO_ENGINE
185         ENGINE *e;
186         /* type will contain the final unaliased type */
187         e = ENGINE_get_pkey_asn1_meth_engine(type);
188         if (e) {
189             *pe = e;
190             return ENGINE_get_pkey_asn1_meth(e, type);
191         }
192 #endif
193         *pe = NULL;
194     }
195     return t;
196 }
197
198 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
199                                                    const char *str, int len)
200 {
201     int i;
202     const EVP_PKEY_ASN1_METHOD *ameth;
203     if (len == -1)
204         len = strlen(str);
205     if (pe) {
206 #ifndef OPENSSL_NO_ENGINE
207         ENGINE *e;
208         ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
209         if (ameth) {
210             /*
211              * Convert structural into functional reference
212              */
213             if (!ENGINE_init(e))
214                 ameth = NULL;
215             ENGINE_free(e);
216             *pe = e;
217             return ameth;
218         }
219 #endif
220         *pe = NULL;
221     }
222     for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
223         ameth = EVP_PKEY_asn1_get0(i);
224         if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
225             continue;
226         if (((int)strlen(ameth->pem_str) == len) &&
227             !strncasecmp(ameth->pem_str, str, len))
228             return ameth;
229     }
230     return NULL;
231 }
232
233 int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
234 {
235     if (app_methods == NULL) {
236         app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
237         if (!app_methods)
238             return 0;
239     }
240     if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
241         return 0;
242     sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
243     return 1;
244 }
245
246 int EVP_PKEY_asn1_add_alias(int to, int from)
247 {
248     EVP_PKEY_ASN1_METHOD *ameth;
249     ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
250     if (!ameth)
251         return 0;
252     ameth->pkey_base_id = to;
253     if (!EVP_PKEY_asn1_add0(ameth)) {
254         EVP_PKEY_asn1_free(ameth);
255         return 0;
256     }
257     return 1;
258 }
259
260 int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id,
261                             int *ppkey_flags, const char **pinfo,
262                             const char **ppem_str,
263                             const EVP_PKEY_ASN1_METHOD *ameth)
264 {
265     if (!ameth)
266         return 0;
267     if (ppkey_id)
268         *ppkey_id = ameth->pkey_id;
269     if (ppkey_base_id)
270         *ppkey_base_id = ameth->pkey_base_id;
271     if (ppkey_flags)
272         *ppkey_flags = ameth->pkey_flags;
273     if (pinfo)
274         *pinfo = ameth->info;
275     if (ppem_str)
276         *ppem_str = ameth->pem_str;
277     return 1;
278 }
279
280 const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(EVP_PKEY *pkey)
281 {
282     return pkey->ameth;
283 }
284
285 EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
286                                         const char *pem_str, const char *info)
287 {
288     EVP_PKEY_ASN1_METHOD *ameth;
289     ameth = OPENSSL_malloc(sizeof(EVP_PKEY_ASN1_METHOD));
290     if (!ameth)
291         return NULL;
292
293     memset(ameth, 0, sizeof(EVP_PKEY_ASN1_METHOD));
294
295     ameth->pkey_id = id;
296     ameth->pkey_base_id = id;
297     ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
298
299     if (info) {
300         ameth->info = BUF_strdup(info);
301         if (!ameth->info)
302             goto err;
303     } else
304         ameth->info = NULL;
305
306     if (pem_str) {
307         ameth->pem_str = BUF_strdup(pem_str);
308         if (!ameth->pem_str)
309             goto err;
310     } else
311         ameth->pem_str = NULL;
312
313     ameth->pub_decode = 0;
314     ameth->pub_encode = 0;
315     ameth->pub_cmp = 0;
316     ameth->pub_print = 0;
317
318     ameth->priv_decode = 0;
319     ameth->priv_encode = 0;
320     ameth->priv_print = 0;
321
322     ameth->old_priv_encode = 0;
323     ameth->old_priv_decode = 0;
324
325     ameth->item_verify = 0;
326     ameth->item_sign = 0;
327
328     ameth->pkey_size = 0;
329     ameth->pkey_bits = 0;
330
331     ameth->param_decode = 0;
332     ameth->param_encode = 0;
333     ameth->param_missing = 0;
334     ameth->param_copy = 0;
335     ameth->param_cmp = 0;
336     ameth->param_print = 0;
337
338     ameth->pkey_free = 0;
339     ameth->pkey_ctrl = 0;
340
341     return ameth;
342
343  err:
344
345     EVP_PKEY_asn1_free(ameth);
346     return NULL;
347
348 }
349
350 void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
351                         const EVP_PKEY_ASN1_METHOD *src)
352 {
353
354     dst->pub_decode = src->pub_decode;
355     dst->pub_encode = src->pub_encode;
356     dst->pub_cmp = src->pub_cmp;
357     dst->pub_print = src->pub_print;
358
359     dst->priv_decode = src->priv_decode;
360     dst->priv_encode = src->priv_encode;
361     dst->priv_print = src->priv_print;
362
363     dst->old_priv_encode = src->old_priv_encode;
364     dst->old_priv_decode = src->old_priv_decode;
365
366     dst->pkey_size = src->pkey_size;
367     dst->pkey_bits = src->pkey_bits;
368
369     dst->param_decode = src->param_decode;
370     dst->param_encode = src->param_encode;
371     dst->param_missing = src->param_missing;
372     dst->param_copy = src->param_copy;
373     dst->param_cmp = src->param_cmp;
374     dst->param_print = src->param_print;
375
376     dst->pkey_free = src->pkey_free;
377     dst->pkey_ctrl = src->pkey_ctrl;
378
379     dst->item_sign = src->item_sign;
380     dst->item_verify = src->item_verify;
381
382 }
383
384 void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
385 {
386     if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) {
387         if (ameth->pem_str)
388             OPENSSL_free(ameth->pem_str);
389         if (ameth->info)
390             OPENSSL_free(ameth->info);
391         OPENSSL_free(ameth);
392     }
393 }
394
395 void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
396                               int (*pub_decode) (EVP_PKEY *pk,
397                                                  X509_PUBKEY *pub),
398                               int (*pub_encode) (X509_PUBKEY *pub,
399                                                  const EVP_PKEY *pk),
400                               int (*pub_cmp) (const EVP_PKEY *a,
401                                               const EVP_PKEY *b),
402                               int (*pub_print) (BIO *out,
403                                                 const EVP_PKEY *pkey,
404                                                 int indent, ASN1_PCTX *pctx),
405                               int (*pkey_size) (const EVP_PKEY *pk),
406                               int (*pkey_bits) (const EVP_PKEY *pk))
407 {
408     ameth->pub_decode = pub_decode;
409     ameth->pub_encode = pub_encode;
410     ameth->pub_cmp = pub_cmp;
411     ameth->pub_print = pub_print;
412     ameth->pkey_size = pkey_size;
413     ameth->pkey_bits = pkey_bits;
414 }
415
416 void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
417                                int (*priv_decode) (EVP_PKEY *pk,
418                                                    PKCS8_PRIV_KEY_INFO
419                                                    *p8inf),
420                                int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8,
421                                                    const EVP_PKEY *pk),
422                                int (*priv_print) (BIO *out,
423                                                   const EVP_PKEY *pkey,
424                                                   int indent,
425                                                   ASN1_PCTX *pctx))
426 {
427     ameth->priv_decode = priv_decode;
428     ameth->priv_encode = priv_encode;
429     ameth->priv_print = priv_print;
430 }
431
432 void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
433                              int (*param_decode) (EVP_PKEY *pkey,
434                                                   const unsigned char **pder,
435                                                   int derlen),
436                              int (*param_encode) (const EVP_PKEY *pkey,
437                                                   unsigned char **pder),
438                              int (*param_missing) (const EVP_PKEY *pk),
439                              int (*param_copy) (EVP_PKEY *to,
440                                                 const EVP_PKEY *from),
441                              int (*param_cmp) (const EVP_PKEY *a,
442                                                const EVP_PKEY *b),
443                              int (*param_print) (BIO *out,
444                                                  const EVP_PKEY *pkey,
445                                                  int indent, ASN1_PCTX *pctx))
446 {
447     ameth->param_decode = param_decode;
448     ameth->param_encode = param_encode;
449     ameth->param_missing = param_missing;
450     ameth->param_copy = param_copy;
451     ameth->param_cmp = param_cmp;
452     ameth->param_print = param_print;
453 }
454
455 void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
456                             void (*pkey_free) (EVP_PKEY *pkey))
457 {
458     ameth->pkey_free = pkey_free;
459 }
460
461 void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
462                             int (*pkey_ctrl) (EVP_PKEY *pkey, int op,
463                                               long arg1, void *arg2))
464 {
465     ameth->pkey_ctrl = pkey_ctrl;
466 }
467
468 void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
469                                      int (*pkey_security_bits) (const EVP_PKEY
470                                                                 *pk))
471 {
472     ameth->pkey_security_bits = pkey_security_bits;
473 }