Import LibreSSL v2.4.2 to vendor branch
[dragonfly.git] / crypto / libressl / crypto / engine / tb_asnmth.c
1 /* $OpenBSD: tb_asnmth.c,v 1.4 2014/07/10 13:58:22 jsing Exp $ */
2 /* ====================================================================
3  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * 3. All advertising materials mentioning features or use of this
18  *    software must display the following acknowledgment:
19  *    "This product includes software developed by the OpenSSL Project
20  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21  *
22  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23  *    endorse or promote products derived from this software without
24  *    prior written permission. For written permission, please contact
25  *    licensing@OpenSSL.org.
26  *
27  * 5. Products derived from this software may not be called "OpenSSL"
28  *    nor may "OpenSSL" appear in their names without prior written
29  *    permission of the OpenSSL Project.
30  *
31  * 6. Redistributions of any form whatsoever must retain the following
32  *    acknowledgment:
33  *    "This product includes software developed by the OpenSSL Project
34  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35  *
36  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47  * OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This product includes cryptographic software written by Eric Young
51  * (eay@cryptsoft.com).  This product includes software written by Tim
52  * Hudson (tjh@cryptsoft.com).
53  *
54  */
55
56 #include <string.h>
57
58 #include <openssl/err.h>
59
60 #include "eng_int.h"
61 #include "asn1_locl.h"
62 #include <openssl/evp.h>
63
64 /* If this symbol is defined then ENGINE_get_pkey_asn1_meth_engine(), the
65  * function that is used by EVP to hook in pkey_asn1_meth code and cache
66  * defaults (etc), will display brief debugging summaries to stderr with the
67  * 'nid'. */
68 /* #define ENGINE_PKEY_ASN1_METH_DEBUG */
69
70 static ENGINE_TABLE *pkey_asn1_meth_table = NULL;
71
72 void
73 ENGINE_unregister_pkey_asn1_meths(ENGINE *e)
74 {
75         engine_table_unregister(&pkey_asn1_meth_table, e);
76 }
77
78 static void
79 engine_unregister_all_pkey_asn1_meths(void)
80 {
81         engine_table_cleanup(&pkey_asn1_meth_table);
82 }
83
84 int
85 ENGINE_register_pkey_asn1_meths(ENGINE *e)
86 {
87         if (e->pkey_asn1_meths) {
88                 const int *nids;
89                 int num_nids = e->pkey_asn1_meths(e, NULL, &nids, 0);
90                 if (num_nids > 0)
91                         return engine_table_register(&pkey_asn1_meth_table,
92                             engine_unregister_all_pkey_asn1_meths, e, nids,
93                             num_nids, 0);
94         }
95         return 1;
96 }
97
98 void
99 ENGINE_register_all_pkey_asn1_meths(void)
100 {
101         ENGINE *e;
102
103         for (e = ENGINE_get_first(); e; e = ENGINE_get_next(e))
104                 ENGINE_register_pkey_asn1_meths(e);
105 }
106
107 int
108 ENGINE_set_default_pkey_asn1_meths(ENGINE *e)
109 {
110         if (e->pkey_asn1_meths) {
111                 const int *nids;
112                 int num_nids = e->pkey_asn1_meths(e, NULL, &nids, 0);
113                 if (num_nids > 0)
114                         return engine_table_register(&pkey_asn1_meth_table,
115                             engine_unregister_all_pkey_asn1_meths, e, nids,
116                             num_nids, 1);
117         }
118         return 1;
119 }
120
121 /* Exposed API function to get a functional reference from the implementation
122  * table (ie. try to get a functional reference from the tabled structural
123  * references) for a given pkey_asn1_meth 'nid' */
124 ENGINE *
125 ENGINE_get_pkey_asn1_meth_engine(int nid)
126 {
127         return engine_table_select(&pkey_asn1_meth_table, nid);
128 }
129
130 /* Obtains a pkey_asn1_meth implementation from an ENGINE functional reference */
131 const EVP_PKEY_ASN1_METHOD *
132 ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid)
133 {
134         EVP_PKEY_ASN1_METHOD *ret;
135         ENGINE_PKEY_ASN1_METHS_PTR fn = ENGINE_get_pkey_asn1_meths(e);
136
137         if (!fn || !fn(e, &ret, NULL, nid)) {
138                 ENGINEerr(ENGINE_F_ENGINE_GET_PKEY_ASN1_METH,
139                     ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD);
140                 return NULL;
141         }
142         return ret;
143 }
144
145 /* Gets the pkey_asn1_meth callback from an ENGINE structure */
146 ENGINE_PKEY_ASN1_METHS_PTR
147 ENGINE_get_pkey_asn1_meths(const ENGINE *e)
148 {
149         return e->pkey_asn1_meths;
150 }
151
152 /* Sets the pkey_asn1_meth callback in an ENGINE structure */
153 int
154 ENGINE_set_pkey_asn1_meths(ENGINE *e, ENGINE_PKEY_ASN1_METHS_PTR f)
155 {
156         e->pkey_asn1_meths = f;
157         return 1;
158 }
159
160 /* Internal function to free up EVP_PKEY_ASN1_METHOD structures before an
161  * ENGINE is destroyed
162  */
163
164 void
165 engine_pkey_asn1_meths_free(ENGINE *e)
166 {
167         int i;
168         EVP_PKEY_ASN1_METHOD *pkm;
169
170         if (e->pkey_asn1_meths) {
171                 const int *pknids;
172                 int npknids;
173                 npknids = e->pkey_asn1_meths(e, NULL, &pknids, 0);
174                 for (i = 0; i < npknids; i++) {
175                         if (e->pkey_asn1_meths(e, &pkm, NULL, pknids[i])) {
176                                 EVP_PKEY_asn1_free(pkm);
177                         }
178                 }
179         }
180 }
181
182 /* Find a method based on a string. This does a linear search through
183  * all implemented algorithms. This is OK in practice because only
184  * a small number of algorithms are likely to be implemented in an engine
185  * and it is not used for speed critical operations.
186  */
187
188 const EVP_PKEY_ASN1_METHOD *
189 ENGINE_get_pkey_asn1_meth_str(ENGINE *e, const char *str, int len)
190 {
191         int i, nidcount;
192         const int *nids;
193         EVP_PKEY_ASN1_METHOD *ameth;
194
195         if (!e->pkey_asn1_meths)
196                 return NULL;
197         if (len == -1)
198                 len = strlen(str);
199         nidcount = e->pkey_asn1_meths(e, NULL, &nids, 0);
200         for (i = 0; i < nidcount; i++) {
201                 e->pkey_asn1_meths(e, &ameth, NULL, nids[i]);
202                 if (((int)strlen(ameth->pem_str) == len) &&
203                     !strncasecmp(ameth->pem_str, str, len))
204                         return ameth;
205         }
206         return NULL;
207 }
208
209 typedef struct {
210         ENGINE *e;
211         const EVP_PKEY_ASN1_METHOD *ameth;
212         const char *str;
213         int len;
214 } ENGINE_FIND_STR;
215
216 static void
217 look_str_cb(int nid, STACK_OF(ENGINE) *sk, ENGINE *def, void *arg)
218 {
219         ENGINE_FIND_STR *lk = arg;
220         int i;
221
222         if (lk->ameth)
223                 return;
224         for (i = 0; i < sk_ENGINE_num(sk); i++) {
225                 ENGINE *e = sk_ENGINE_value(sk, i);
226                 EVP_PKEY_ASN1_METHOD *ameth;
227                 e->pkey_asn1_meths(e, &ameth, NULL, nid);
228                 if (((int)strlen(ameth->pem_str) == lk->len) &&
229                     !strncasecmp(ameth->pem_str, lk->str, lk->len)) {
230                         lk->e = e;
231                         lk->ameth = ameth;
232                         return;
233                 }
234         }
235 }
236
237 const EVP_PKEY_ASN1_METHOD *
238 ENGINE_pkey_asn1_find_str(ENGINE **pe, const char *str, int len)
239 {
240         ENGINE_FIND_STR fstr;
241
242         fstr.e = NULL;
243         fstr.ameth = NULL;
244         fstr.str = str;
245         fstr.len = len;
246         CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
247         engine_table_doall(pkey_asn1_meth_table, look_str_cb, &fstr);
248         /* If found obtain a structural reference to engine */
249         if (fstr.e) {
250                 fstr.e->struct_ref++;
251                 engine_ref_debug(fstr.e, 0, 1)
252         }
253         *pe = fstr.e;
254         CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
255         return fstr.ameth;
256 }