add gmp
[heimdal.git] / lib / hcrypto / engine.c
blobc3979fd639950adfb6d80db511c8e52ea6af3efb
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>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
40 #include <engine.h>
42 #ifdef HAVE_DLFCN_H
43 #include <dlfcn.h>
44 #ifndef RTLD_NOW
45 #define RTLD_NOW 0
46 #endif
47 #endif
49 struct hc_engine {
50 int references;
51 char *name;
52 char *id;
53 void (*destroy)(ENGINE *);
54 const RSA_METHOD *rsa;
55 const DH_METHOD *dh;
56 const RAND_METHOD *rand;
59 ENGINE *
60 ENGINE_new(void)
62 ENGINE *engine;
64 engine = calloc(1, sizeof(*engine));
65 engine->references = 1;
67 return engine;
70 int
71 ENGINE_free(ENGINE *engine)
73 return ENGINE_finish(engine);
76 int
77 ENGINE_finish(ENGINE *engine)
79 if (engine->references-- <= 0)
80 abort();
81 if (engine->references > 0)
82 return 1;
84 if (engine->name)
85 free(engine->name);
86 if (engine->id)
87 free(engine->id);
88 if(engine->destroy)
89 (*engine->destroy)(engine);
91 memset(engine, 0, sizeof(engine));
92 engine->references = -1;
95 free(engine);
96 return 1;
99 int
100 ENGINE_up_ref(ENGINE *engine)
102 if (engine->references < 0)
103 abort();
104 engine->references++;
105 return 1;
109 ENGINE_set_id(ENGINE *engine, const char *id)
111 engine->id = strdup(id);
112 return (engine->id == NULL) ? 0 : 1;
116 ENGINE_set_name(ENGINE *engine, const char *name)
118 engine->name = strdup(name);
119 return (engine->name == NULL) ? 0 : 1;
123 ENGINE_set_RSA(ENGINE *engine, const RSA_METHOD *method)
125 engine->rsa = method;
126 return 1;
130 ENGINE_set_DH(ENGINE *engine, const DH_METHOD *method)
132 engine->dh = method;
133 return 1;
137 ENGINE_set_destroy_function(ENGINE *e, void (*destroy)(ENGINE *))
139 e->destroy = destroy;
140 return 1;
143 const char *
144 ENGINE_get_id(const ENGINE *engine)
146 return engine->id;
149 const char *
150 ENGINE_get_name(const ENGINE *engine)
152 return engine->name;
155 const RSA_METHOD *
156 ENGINE_get_RSA(const ENGINE *engine)
158 return engine->rsa;
161 const DH_METHOD *
162 ENGINE_get_DH(const ENGINE *engine)
164 return engine->dh;
167 const RAND_METHOD *
168 ENGINE_get_RAND(const ENGINE *engine)
170 return engine->rand;
177 #define SG_default_engine(type) \
178 static ENGINE *type##_engine; \
179 int \
180 ENGINE_set_default_##type(ENGINE *engine) \
182 if (type##_engine) \
183 ENGINE_finish(type##_engine); \
184 type##_engine = engine; \
185 if (type##_engine) \
186 ENGINE_up_ref(type##_engine); \
187 return 1; \
189 ENGINE * \
190 ENGINE_get_default_##type(void) \
192 if (type##_engine) \
193 ENGINE_up_ref(type##_engine); \
194 return type##_engine; \
197 SG_default_engine(RSA)
198 SG_default_engine(DH)
200 #undef SG_default_engine
206 static ENGINE **engines;
207 static unsigned int num_engines;
209 static int
210 add_engine(ENGINE *engine)
212 ENGINE **d, *dup;
214 dup = ENGINE_by_id(engine->id);
215 if (dup)
216 return 0;
218 d = realloc(engines, (num_engines + 1) * sizeof(*engines));
219 if (d == NULL)
220 return 1;
221 engines = d;
222 engines[num_engines++] = engine;
224 return 1;
227 void
228 ENGINE_load_builtin_engines(void)
230 ENGINE *engine;
231 int ret;
233 engine = ENGINE_new();
234 if (engine == NULL)
235 return;
237 ENGINE_set_id(engine, "builtin");
238 ENGINE_set_name(engine,
239 "Heimdal crypto builtin engine version " PACKAGE_VERSION);
240 ENGINE_set_RSA(engine, RSA_tfm_method());
241 ENGINE_set_DH(engine, DH_tfm_method());
243 ret = add_engine(engine);
244 if (ret != 1)
245 ENGINE_finish(engine);
248 * TFM
251 engine = ENGINE_new();
252 if (engine == NULL)
253 return;
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());
261 ret = add_engine(engine);
262 if (ret != 1)
263 ENGINE_finish(engine);
266 * imath
269 engine = ENGINE_new();
270 if (engine == NULL)
271 return;
273 ENGINE_set_id(engine, "imath");
274 ENGINE_set_name(engine,
275 "Heimdal crypto imath engine version " PACKAGE_VERSION);
276 ENGINE_set_RSA(engine, RSA_imath_method());
277 ENGINE_set_DH(engine, DH_imath_method());
279 ret = add_engine(engine);
280 if (ret != 1)
281 ENGINE_finish(engine);
283 #ifdef HAVE_GMP
285 * gmp
288 engine = ENGINE_new();
289 if (engine == NULL)
290 return;
292 ENGINE_set_id(engine, "gmp");
293 ENGINE_set_name(engine,
294 "Heimdal crypto gmp engine version " PACKAGE_VERSION);
295 ENGINE_set_RSA(engine, RSA_gmp_method());
297 ret = add_engine(engine);
298 if (ret != 1)
299 ENGINE_finish(engine);
300 #endif
303 ENGINE *
304 ENGINE_by_dso(const char *path, const char *id)
306 #ifdef HAVE_DLOPEN
307 ENGINE *engine;
308 void *handle;
309 int ret;
311 engine = calloc(1, sizeof(*engine));
312 if (engine == NULL)
313 return NULL;
315 handle = dlopen(path, RTLD_NOW);
316 if (handle == NULL) {
317 /* printf("error: %s\n", dlerror()); */
318 free(engine);
319 return NULL;
323 unsigned long version;
324 openssl_v_check v_check;
326 v_check = (openssl_v_check)dlsym(handle, "v_check");
327 if (v_check == NULL) {
328 dlclose(handle);
329 free(engine);
330 return NULL;
333 version = (*v_check)(OPENSSL_DYNAMIC_VERSION);
334 if (version == 0) {
335 dlclose(handle);
336 free(engine);
337 return NULL;
342 openssl_bind_engine bind_engine;
344 bind_engine = (openssl_bind_engine)dlsym(handle, "bind_engine");
345 if (bind_engine == NULL) {
346 dlclose(handle);
347 free(engine);
348 return NULL;
351 ret = (*bind_engine)(engine, id, NULL); /* XXX fix third arg */
352 if (ret != 1) {
353 dlclose(handle);
354 free(engine);
355 return NULL;
359 ENGINE_up_ref(engine);
361 ret = add_engine(engine);
362 if (ret != 1) {
363 dlclose(handle);
364 ENGINE_finish(engine);
365 return NULL;
368 return engine;
369 #else
370 return NULL;
371 #endif
374 ENGINE *
375 ENGINE_by_id(const char *id)
377 int i;
379 for (i = 0; i < num_engines; i++) {
380 if (strcmp(id, engines[i]->id) == 0) {
381 ENGINE_up_ref(engines[i]);
382 return engines[i];
385 return NULL;
388 void
389 ENGINE_add_conf_module(void)