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