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