hcrypto: Use memset_s() when clearing sensitive buffers
[heimdal.git] / lib / hcrypto / engine.c
blob6a79b7c9907928964ff6a86ba50d9ab366f4019e
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 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;
50 ENGINE *
51 ENGINE_new(void)
53 ENGINE *engine;
55 engine = calloc(1, sizeof(*engine));
56 if (engine == NULL)
57 return NULL;
58 engine->references = 1;
59 engine->destroy = 0;
60 engine->dh = 0;
61 engine->rand = 0;
62 engine->dso_handle = 0;
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);
87 if (engine->dso_handle)
88 dlclose(engine->dso_handle);
90 memset_s(engine, sizeof(*engine), 0, sizeof(*engine));
91 engine->references = -1;
94 free(engine);
95 return 1;
98 int
99 ENGINE_up_ref(ENGINE *engine)
101 if (engine->references < 0)
102 abort();
103 engine->references++;
104 return 1;
108 ENGINE_set_id(ENGINE *engine, const char *id)
110 engine->id = strdup(id);
111 return (engine->id == NULL) ? 0 : 1;
115 ENGINE_set_name(ENGINE *engine, const char *name)
117 engine->name = strdup(name);
118 return (engine->name == NULL) ? 0 : 1;
122 ENGINE_set_RSA(ENGINE *engine, const RSA_METHOD *method)
124 engine->rsa = method;
125 return 1;
129 ENGINE_set_DH(ENGINE *engine, const DH_METHOD *method)
131 engine->dh = method;
132 return 1;
136 ENGINE_set_destroy_function(ENGINE *e, void (*destroy)(ENGINE *))
138 e->destroy = destroy;
139 return 1;
142 const char *
143 ENGINE_get_id(const ENGINE *engine)
145 return engine->id;
148 const char *
149 ENGINE_get_name(const ENGINE *engine)
151 return engine->name;
154 const RSA_METHOD *
155 ENGINE_get_RSA(const ENGINE *engine)
157 return engine->rsa;
160 const DH_METHOD *
161 ENGINE_get_DH(const ENGINE *engine)
163 return engine->dh;
166 const RAND_METHOD *
167 ENGINE_get_RAND(const ENGINE *engine)
169 return engine->rand;
176 #define SG_default_engine(type) \
177 static ENGINE *type##_engine; \
178 int \
179 ENGINE_set_default_##type(ENGINE *engine) \
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; \
188 ENGINE * \
189 ENGINE_get_default_##type(void) \
191 if (type##_engine) \
192 ENGINE_up_ref(type##_engine); \
193 return type##_engine; \
196 SG_default_engine(RSA)
197 SG_default_engine(DH)
199 #undef SG_default_engine
205 static ENGINE **engines;
206 static unsigned int num_engines;
208 static int
209 add_engine(ENGINE *engine)
211 ENGINE **d, *dup;
213 dup = ENGINE_by_id(engine->id);
214 if (dup)
215 return 0;
217 d = realloc(engines, (num_engines + 1) * sizeof(*engines));
218 if (d == NULL)
219 return 1;
220 engines = d;
221 engines[num_engines++] = engine;
223 return 1;
226 void
227 ENGINE_load_builtin_engines(void)
229 ENGINE *engine;
230 int ret;
232 engine = ENGINE_new();
233 if (engine == NULL)
234 return;
236 ENGINE_set_id(engine, "builtin");
237 ENGINE_set_name(engine,
238 "Heimdal crypto builtin (ltm) engine version " PACKAGE_VERSION);
239 ENGINE_set_RSA(engine, RSA_ltm_method());
240 ENGINE_set_DH(engine, DH_ltm_method());
242 ret = add_engine(engine);
243 if (ret != 1)
244 ENGINE_finish(engine);
246 #ifdef USE_HCRYPTO_TFM
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);
264 #endif /* USE_HCRYPTO_TFM */
266 #ifdef USE_HCRYPTO_LTM
268 * ltm
271 engine = ENGINE_new();
272 if (engine == NULL)
273 return;
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());
281 ret = add_engine(engine);
282 if (ret != 1)
283 ENGINE_finish(engine);
284 #endif
286 #ifdef HAVE_GMP
288 * gmp
291 engine = ENGINE_new();
292 if (engine == NULL)
293 return;
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());
300 ret = add_engine(engine);
301 if (ret != 1)
302 ENGINE_finish(engine);
303 #endif
306 ENGINE *
307 ENGINE_by_dso(const char *path, const char *id)
309 #ifdef HAVE_DLOPEN
310 ENGINE *engine;
311 int ret;
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;
328 unsigned long version;
329 openssl_v_check v_check;
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;
338 version = (*v_check)(OPENSSL_DYNAMIC_VERSION);
339 if (version == 0) {
340 dlclose(engine->dso_handle);
341 free(engine);
342 return NULL;
347 openssl_bind_engine bind_engine;
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;
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;
365 ENGINE_up_ref(engine);
367 ret = add_engine(engine);
368 if (ret != 1) {
369 ENGINE_finish(engine);
370 return NULL;
373 return engine;
374 #else
375 return NULL;
376 #endif
379 ENGINE *
380 ENGINE_by_id(const char *id)
382 int i;
384 for (i = 0; i < num_engines; i++) {
385 if (strcmp(id, engines[i]->id) == 0) {
386 ENGINE_up_ref(engines[i]);
387 return engines[i];
390 return NULL;
393 void
394 ENGINE_add_conf_module(void)