Line data Source code
1 : /*
2 : * Copyright (c) 2006 Kungliga Tekniska Högskolan
3 : * (Royal Institute of Technology, Stockholm, Sweden).
4 : * All rights reserved.
5 : *
6 : * Redistribution and use in source and binary forms, with or without
7 : * modification, are permitted provided that the following conditions
8 : * are met:
9 : *
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : *
13 : * 2. Redistributions in binary form must reproduce the above copyright
14 : * notice, this list of conditions and the following disclaimer in the
15 : * documentation and/or other materials provided with the distribution.
16 : *
17 : * 3. Neither the name of the Institute nor the names of its contributors
18 : * may be used to endorse or promote products derived from this software
19 : * without specific prior written permission.
20 : *
21 : * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 : * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 : * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 : * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 : * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 : * SUCH DAMAGE.
32 : */
33 :
34 : #include <config.h>
35 : #include <roken.h>
36 :
37 : #include <engine.h>
38 :
39 : struct hc_engine {
40 : int references;
41 : char *name;
42 : char *id;
43 : void (*destroy)(ENGINE *);
44 : const RSA_METHOD *rsa;
45 : const DH_METHOD *dh;
46 : const RAND_METHOD *rand;
47 : void *dso_handle;
48 : };
49 :
50 : ENGINE *
51 0 : ENGINE_new(void)
52 : {
53 0 : ENGINE *engine;
54 :
55 0 : engine = calloc(1, sizeof(*engine));
56 0 : if (engine == NULL)
57 0 : return NULL;
58 0 : engine->references = 1;
59 0 : engine->destroy = 0;
60 0 : engine->dh = 0;
61 0 : engine->rand = 0;
62 0 : engine->dso_handle = 0;
63 :
64 0 : return engine;
65 : }
66 :
67 : int
68 0 : ENGINE_free(ENGINE *engine)
69 : {
70 0 : return ENGINE_finish(engine);
71 : }
72 :
73 : int
74 0 : ENGINE_finish(ENGINE *engine)
75 : {
76 0 : if (engine->references-- <= 0)
77 0 : abort();
78 0 : if (engine->references > 0)
79 0 : return 1;
80 :
81 0 : if (engine->name)
82 0 : free(engine->name);
83 0 : if (engine->id)
84 0 : free(engine->id);
85 0 : if(engine->destroy)
86 0 : (*engine->destroy)(engine);
87 0 : if (engine->dso_handle)
88 0 : dlclose(engine->dso_handle);
89 :
90 0 : memset_s(engine, sizeof(*engine), 0, sizeof(*engine));
91 0 : engine->references = -1;
92 :
93 :
94 0 : free(engine);
95 0 : return 1;
96 : }
97 :
98 : int
99 0 : ENGINE_up_ref(ENGINE *engine)
100 : {
101 0 : if (engine->references < 0)
102 0 : abort();
103 0 : engine->references++;
104 0 : return 1;
105 : }
106 :
107 : int
108 0 : ENGINE_set_id(ENGINE *engine, const char *id)
109 : {
110 0 : engine->id = strdup(id);
111 0 : return (engine->id == NULL) ? 0 : 1;
112 : }
113 :
114 : int
115 0 : ENGINE_set_name(ENGINE *engine, const char *name)
116 : {
117 0 : engine->name = strdup(name);
118 0 : return (engine->name == NULL) ? 0 : 1;
119 : }
120 :
121 : int
122 0 : ENGINE_set_RSA(ENGINE *engine, const RSA_METHOD *method)
123 : {
124 0 : engine->rsa = method;
125 0 : return 1;
126 : }
127 :
128 : int
129 0 : ENGINE_set_DH(ENGINE *engine, const DH_METHOD *method)
130 : {
131 0 : engine->dh = method;
132 0 : return 1;
133 : }
134 :
135 : int
136 0 : ENGINE_set_destroy_function(ENGINE *e, void (*destroy)(ENGINE *))
137 : {
138 0 : e->destroy = destroy;
139 0 : return 1;
140 : }
141 :
142 : const char *
143 0 : ENGINE_get_id(const ENGINE *engine)
144 : {
145 0 : return engine->id;
146 : }
147 :
148 : const char *
149 0 : ENGINE_get_name(const ENGINE *engine)
150 : {
151 0 : return engine->name;
152 : }
153 :
154 : const RSA_METHOD *
155 0 : ENGINE_get_RSA(const ENGINE *engine)
156 : {
157 0 : return engine->rsa;
158 : }
159 :
160 : const DH_METHOD *
161 0 : ENGINE_get_DH(const ENGINE *engine)
162 : {
163 0 : return engine->dh;
164 : }
165 :
166 : const RAND_METHOD *
167 0 : ENGINE_get_RAND(const ENGINE *engine)
168 : {
169 0 : return engine->rand;
170 : }
171 :
172 : /*
173 : *
174 : */
175 :
176 : #define SG_default_engine(type) \
177 : static ENGINE *type##_engine; \
178 : int \
179 : ENGINE_set_default_##type(ENGINE *engine) \
180 : { \
181 : if (type##_engine) \
182 : ENGINE_finish(type##_engine); \
183 : type##_engine = engine; \
184 : if (type##_engine) \
185 : ENGINE_up_ref(type##_engine); \
186 : return 1; \
187 : } \
188 : ENGINE * \
189 : ENGINE_get_default_##type(void) \
190 : { \
191 : if (type##_engine) \
192 : ENGINE_up_ref(type##_engine); \
193 : return type##_engine; \
194 : }
195 :
196 394 : SG_default_engine(RSA)
197 156 : SG_default_engine(DH)
198 :
199 : #undef SG_default_engine
200 :
201 : /*
202 : *
203 : */
204 :
205 : static ENGINE **engines;
206 : static unsigned int num_engines;
207 :
208 : static int
209 0 : add_engine(ENGINE *engine)
210 : {
211 0 : ENGINE **d, *dup;
212 :
213 0 : dup = ENGINE_by_id(engine->id);
214 0 : if (dup)
215 0 : return 0;
216 :
217 0 : d = realloc(engines, (num_engines + 1) * sizeof(*engines));
218 0 : if (d == NULL)
219 0 : return 1;
220 0 : engines = d;
221 0 : engines[num_engines++] = engine;
222 :
223 0 : return 1;
224 : }
225 :
226 : void
227 0 : ENGINE_load_builtin_engines(void)
228 : {
229 0 : ENGINE *engine;
230 0 : int ret;
231 :
232 0 : engine = ENGINE_new();
233 0 : if (engine == NULL)
234 0 : return;
235 :
236 0 : ENGINE_set_id(engine, "builtin");
237 0 : ENGINE_set_name(engine,
238 : "Heimdal crypto builtin (ltm) engine version " PACKAGE_VERSION);
239 0 : ENGINE_set_RSA(engine, RSA_ltm_method());
240 0 : ENGINE_set_DH(engine, DH_ltm_method());
241 :
242 0 : ret = add_engine(engine);
243 0 : if (ret != 1)
244 0 : ENGINE_finish(engine);
245 :
246 : #ifdef USE_HCRYPTO_TFM
247 : /*
248 : * TFM
249 : */
250 :
251 : engine = ENGINE_new();
252 : if (engine == NULL)
253 : return;
254 :
255 : ENGINE_set_id(engine, "tfm");
256 : ENGINE_set_name(engine,
257 : "Heimdal crypto tfm engine version " PACKAGE_VERSION);
258 : ENGINE_set_RSA(engine, RSA_tfm_method());
259 : ENGINE_set_DH(engine, DH_tfm_method());
260 :
261 : ret = add_engine(engine);
262 : if (ret != 1)
263 : ENGINE_finish(engine);
264 : #endif /* USE_HCRYPTO_TFM */
265 :
266 : #ifdef USE_HCRYPTO_LTM
267 : /*
268 : * ltm
269 : */
270 :
271 : engine = ENGINE_new();
272 : if (engine == NULL)
273 : return;
274 :
275 : ENGINE_set_id(engine, "ltm");
276 : ENGINE_set_name(engine,
277 : "Heimdal crypto ltm engine version " PACKAGE_VERSION);
278 : ENGINE_set_RSA(engine, RSA_ltm_method());
279 : ENGINE_set_DH(engine, DH_ltm_method());
280 :
281 : ret = add_engine(engine);
282 : if (ret != 1)
283 : ENGINE_finish(engine);
284 : #endif
285 :
286 : #ifdef HAVE_GMP
287 : /*
288 : * gmp
289 : */
290 :
291 : engine = ENGINE_new();
292 : if (engine == NULL)
293 : return;
294 :
295 : ENGINE_set_id(engine, "gmp");
296 : ENGINE_set_name(engine,
297 : "Heimdal crypto gmp engine version " PACKAGE_VERSION);
298 : ENGINE_set_RSA(engine, RSA_gmp_method());
299 :
300 : ret = add_engine(engine);
301 : if (ret != 1)
302 : ENGINE_finish(engine);
303 : #endif
304 : }
305 :
306 : ENGINE *
307 0 : ENGINE_by_dso(const char *path, const char *id)
308 : {
309 : #ifdef HAVE_DLOPEN
310 : ENGINE *engine;
311 : int ret;
312 :
313 : engine = calloc(1, sizeof(*engine));
314 : if (engine == NULL)
315 : return NULL;
316 : engine->references = 0; /* ref will be added below */
317 : engine->destroy = 0;
318 : engine->dh = 0;
319 : engine->rand = 0;
320 : engine->dso_handle = dlopen(path, RTLD_NOW | RTLD_LOCAL | RTLD_GROUP);
321 : if (engine->dso_handle == NULL) {
322 : /* printf("error: %s\n", dlerror()); */
323 : free(engine);
324 : return NULL;
325 : }
326 :
327 : {
328 : unsigned long version;
329 : openssl_v_check v_check;
330 :
331 : v_check = (openssl_v_check)dlsym(engine->dso_handle, "v_check");
332 : if (v_check == NULL) {
333 : dlclose(engine->dso_handle);
334 : free(engine);
335 : return NULL;
336 : }
337 :
338 : version = (*v_check)(OPENSSL_DYNAMIC_VERSION);
339 : if (version == 0) {
340 : dlclose(engine->dso_handle);
341 : free(engine);
342 : return NULL;
343 : }
344 : }
345 :
346 : {
347 : openssl_bind_engine bind_engine;
348 :
349 : bind_engine =
350 : (openssl_bind_engine)dlsym(engine->dso_handle, "bind_engine");
351 : if (bind_engine == NULL) {
352 : dlclose(engine->dso_handle);
353 : free(engine);
354 : return NULL;
355 : }
356 :
357 : ret = (*bind_engine)(engine, id, NULL); /* XXX fix third arg */
358 : if (ret != 1) {
359 : dlclose(engine->dso_handle);
360 : free(engine);
361 : return NULL;
362 : }
363 : }
364 :
365 : ENGINE_up_ref(engine);
366 :
367 : ret = add_engine(engine);
368 : if (ret != 1) {
369 : ENGINE_finish(engine);
370 : return NULL;
371 : }
372 :
373 : return engine;
374 : #else
375 0 : return NULL;
376 : #endif
377 : }
378 :
379 : ENGINE *
380 0 : ENGINE_by_id(const char *id)
381 : {
382 0 : int i;
383 :
384 0 : for (i = 0; i < num_engines; i++) {
385 0 : if (strcmp(id, engines[i]->id) == 0) {
386 0 : ENGINE_up_ref(engines[i]);
387 0 : return engines[i];
388 : }
389 : }
390 0 : return NULL;
391 : }
392 :
393 : void
394 33851 : ENGINE_add_conf_module(void)
395 : {
396 33851 : }
|