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