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