Windows: include KX509 support
[heimdal.git] / lib / hcrypto / engine.c
blob04ba6b645f66a22bbee50857601022691acfa37e
1 /*
2 * Copyright (c) 2006 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
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.
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.
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.
34 #include <config.h>
35 #include <roken.h>
37 #include <engine.h>
39 #ifdef HAVE_DLFCN_H
40 #include <dlfcn.h>
41 #ifndef RTLD_NOW
42 #define RTLD_NOW 0
43 #endif
44 #endif
46 struct hc_engine {
47 int references;
48 char *name;
49 char *id;
50 void (*destroy)(ENGINE *);
51 const RSA_METHOD *rsa;
52 const DH_METHOD *dh;
53 const RAND_METHOD *rand;
56 ENGINE *
57 ENGINE_new(void)
59 ENGINE *engine;
61 engine = calloc(1, sizeof(*engine));
62 engine->references = 1;
64 return engine;
67 int
68 ENGINE_free(ENGINE *engine)
70 return ENGINE_finish(engine);
73 int
74 ENGINE_finish(ENGINE *engine)
76 if (engine->references-- <= 0)
77 abort();
78 if (engine->references > 0)
79 return 1;
81 if (engine->name)
82 free(engine->name);
83 if (engine->id)
84 free(engine->id);
85 if(engine->destroy)
86 (*engine->destroy)(engine);
88 memset(engine, 0, sizeof(*engine));
89 engine->references = -1;
92 free(engine);
93 return 1;
96 int
97 ENGINE_up_ref(ENGINE *engine)
99 if (engine->references < 0)
100 abort();
101 engine->references++;
102 return 1;
106 ENGINE_set_id(ENGINE *engine, const char *id)
108 engine->id = strdup(id);
109 return (engine->id == NULL) ? 0 : 1;
113 ENGINE_set_name(ENGINE *engine, const char *name)
115 engine->name = strdup(name);
116 return (engine->name == NULL) ? 0 : 1;
120 ENGINE_set_RSA(ENGINE *engine, const RSA_METHOD *method)
122 engine->rsa = method;
123 return 1;
127 ENGINE_set_DH(ENGINE *engine, const DH_METHOD *method)
129 engine->dh = method;
130 return 1;
134 ENGINE_set_destroy_function(ENGINE *e, void (*destroy)(ENGINE *))
136 e->destroy = destroy;
137 return 1;
140 const char *
141 ENGINE_get_id(const ENGINE *engine)
143 return engine->id;
146 const char *
147 ENGINE_get_name(const ENGINE *engine)
149 return engine->name;
152 const RSA_METHOD *
153 ENGINE_get_RSA(const ENGINE *engine)
155 return engine->rsa;
158 const DH_METHOD *
159 ENGINE_get_DH(const ENGINE *engine)
161 return engine->dh;
164 const RAND_METHOD *
165 ENGINE_get_RAND(const ENGINE *engine)
167 return engine->rand;
174 #define SG_default_engine(type) \
175 static ENGINE *type##_engine; \
176 int \
177 ENGINE_set_default_##type(ENGINE *engine) \
179 if (type##_engine) \
180 ENGINE_finish(type##_engine); \
181 type##_engine = engine; \
182 if (type##_engine) \
183 ENGINE_up_ref(type##_engine); \
184 return 1; \
186 ENGINE * \
187 ENGINE_get_default_##type(void) \
189 if (type##_engine) \
190 ENGINE_up_ref(type##_engine); \
191 return type##_engine; \
194 SG_default_engine(RSA)
195 SG_default_engine(DH)
197 #undef SG_default_engine
203 static ENGINE **engines;
204 static unsigned int num_engines;
206 static int
207 add_engine(ENGINE *engine)
209 ENGINE **d, *dup;
211 dup = ENGINE_by_id(engine->id);
212 if (dup)
213 return 0;
215 d = realloc(engines, (num_engines + 1) * sizeof(*engines));
216 if (d == NULL)
217 return 1;
218 engines = d;
219 engines[num_engines++] = engine;
221 return 1;
224 void
225 ENGINE_load_builtin_engines(void)
227 ENGINE *engine;
228 int ret;
230 engine = ENGINE_new();
231 if (engine == NULL)
232 return;
234 ENGINE_set_id(engine, "builtin");
235 ENGINE_set_name(engine,
236 "Heimdal crypto builtin (ltm) engine version " PACKAGE_VERSION);
237 ENGINE_set_RSA(engine, RSA_ltm_method());
238 ENGINE_set_DH(engine, DH_ltm_method());
240 ret = add_engine(engine);
241 if (ret != 1)
242 ENGINE_finish(engine);
244 #ifdef USE_HCRYPTO_TFM
246 * TFM
249 engine = ENGINE_new();
250 if (engine == NULL)
251 return;
253 ENGINE_set_id(engine, "tfm");
254 ENGINE_set_name(engine,
255 "Heimdal crypto tfm engine version " PACKAGE_VERSION);
256 ENGINE_set_RSA(engine, RSA_tfm_method());
257 ENGINE_set_DH(engine, DH_tfm_method());
259 ret = add_engine(engine);
260 if (ret != 1)
261 ENGINE_finish(engine);
262 #endif /* USE_HCRYPTO_TFM */
264 #ifdef USE_HCRYPTO_LTM
266 * ltm
269 engine = ENGINE_new();
270 if (engine == NULL)
271 return;
273 ENGINE_set_id(engine, "ltm");
274 ENGINE_set_name(engine,
275 "Heimdal crypto ltm engine version " PACKAGE_VERSION);
276 ENGINE_set_RSA(engine, RSA_ltm_method());
277 ENGINE_set_DH(engine, DH_ltm_method());
279 ret = add_engine(engine);
280 if (ret != 1)
281 ENGINE_finish(engine);
282 #endif
284 #ifdef HAVE_GMP
286 * gmp
289 engine = ENGINE_new();
290 if (engine == NULL)
291 return;
293 ENGINE_set_id(engine, "gmp");
294 ENGINE_set_name(engine,
295 "Heimdal crypto gmp engine version " PACKAGE_VERSION);
296 ENGINE_set_RSA(engine, RSA_gmp_method());
298 ret = add_engine(engine);
299 if (ret != 1)
300 ENGINE_finish(engine);
301 #endif
304 ENGINE *
305 ENGINE_by_dso(const char *path, const char *id)
307 #ifdef HAVE_DLOPEN
308 ENGINE *engine;
309 void *handle;
310 int ret;
312 engine = calloc(1, sizeof(*engine));
313 if (engine == NULL)
314 return NULL;
316 handle = dlopen(path, RTLD_NOW);
317 if (handle == NULL) {
318 /* printf("error: %s\n", dlerror()); */
319 free(engine);
320 return NULL;
324 unsigned long version;
325 openssl_v_check v_check;
327 v_check = (openssl_v_check)dlsym(handle, "v_check");
328 if (v_check == NULL) {
329 dlclose(handle);
330 free(engine);
331 return NULL;
334 version = (*v_check)(OPENSSL_DYNAMIC_VERSION);
335 if (version == 0) {
336 dlclose(handle);
337 free(engine);
338 return NULL;
343 openssl_bind_engine bind_engine;
345 bind_engine = (openssl_bind_engine)dlsym(handle, "bind_engine");
346 if (bind_engine == NULL) {
347 dlclose(handle);
348 free(engine);
349 return NULL;
352 ret = (*bind_engine)(engine, id, NULL); /* XXX fix third arg */
353 if (ret != 1) {
354 dlclose(handle);
355 free(engine);
356 return NULL;
360 ENGINE_up_ref(engine);
362 ret = add_engine(engine);
363 if (ret != 1) {
364 dlclose(handle);
365 ENGINE_finish(engine);
366 return NULL;
369 return engine;
370 #else
371 return NULL;
372 #endif
375 ENGINE *
376 ENGINE_by_id(const char *id)
378 int i;
380 for (i = 0; i < num_engines; i++) {
381 if (strcmp(id, engines[i]->id) == 0) {
382 ENGINE_up_ref(engines[i]);
383 return engines[i];
386 return NULL;
389 void
390 ENGINE_add_conf_module(void)