[HEIMDAL-646] malloc(0) checks for AIX
[heimdal.git] / lib / hcrypto / engine.c
blob8066d59cf89f2350c42524cbb2d8d83cd5692a7d
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 int
60 ENGINE_finish(ENGINE *engine)
62 if (engine->references-- <= 0)
63 abort();
64 if (engine->references > 0)
65 return 1;
67 if (engine->name)
68 free(engine->name);
69 if (engine->id)
70 free(engine->id);
71 if(engine->destroy)
72 (*engine->destroy)(engine);
74 memset(engine, 0, sizeof(engine));
75 engine->references = -1;
78 free(engine);
79 return 1;
82 int
83 ENGINE_up_ref(ENGINE *engine)
85 if (engine->references < 0)
86 abort();
87 engine->references++;
88 return 1;
91 int
92 ENGINE_set_id(ENGINE *engine, const char *id)
94 engine->id = strdup(id);
95 return (engine->id == NULL) ? 0 : 1;
98 int
99 ENGINE_set_name(ENGINE *engine, const char *name)
101 engine->name = strdup(name);
102 return (engine->name == NULL) ? 0 : 1;
106 ENGINE_set_RSA(ENGINE *engine, const RSA_METHOD *method)
108 engine->rsa = method;
109 return 1;
113 ENGINE_set_DH(ENGINE *engine, const DH_METHOD *method)
115 engine->dh = method;
116 return 1;
120 ENGINE_set_destroy_function(ENGINE *e, void (*destroy)(ENGINE *))
122 e->destroy = destroy;
123 return 1;
126 const char *
127 ENGINE_get_id(const ENGINE *engine)
129 return engine->id;
132 const char *
133 ENGINE_get_name(const ENGINE *engine)
135 return engine->name;
138 const RSA_METHOD *
139 ENGINE_get_RSA(const ENGINE *engine)
141 return engine->rsa;
144 const DH_METHOD *
145 ENGINE_get_DH(const ENGINE *engine)
147 return engine->dh;
150 const RAND_METHOD *
151 ENGINE_get_RAND(const ENGINE *engine)
153 return engine->rand;
160 #define SG_default_engine(type) \
161 static ENGINE *type##_engine; \
162 int \
163 ENGINE_set_default_##type(ENGINE *engine) \
165 if (type##_engine) \
166 ENGINE_finish(type##_engine); \
167 type##_engine = engine; \
168 if (type##_engine) \
169 ENGINE_up_ref(type##_engine); \
170 return 1; \
172 ENGINE * \
173 ENGINE_get_default_##type(void) \
175 if (type##_engine) \
176 ENGINE_up_ref(type##_engine); \
177 return type##_engine; \
180 SG_default_engine(RSA)
181 SG_default_engine(DH)
183 #undef SG_default_engine
189 static ENGINE **engines;
190 static unsigned int num_engines;
192 static int
193 add_engine(ENGINE *engine)
195 ENGINE **d, *dup;
197 dup = ENGINE_by_id(engine->id);
198 if (dup) {
199 ENGINE_finish(dup);
200 return 0;
203 d = realloc(engines, (num_engines + 1) * sizeof(*engines));
204 if (d == NULL)
205 return 1;
206 engines = d;
207 engines[num_engines++] = engine;
209 return 1;
212 void
213 ENGINE_load_builtin_engines(void)
215 ENGINE *engine;
216 int ret;
218 engine = calloc(1, sizeof(*engine));
219 if (engine == NULL)
220 return;
222 ENGINE_set_id(engine, "builtin");
223 ENGINE_set_name(engine,
224 "Heimdal crypto builtin engine version " PACKAGE_VERSION);
225 ENGINE_set_RSA(engine, RSA_imath_method());
226 ENGINE_set_DH(engine, DH_imath_method());
228 ret = add_engine(engine);
229 if (ret != 1)
230 ENGINE_finish(engine);
233 ENGINE *
234 ENGINE_by_dso(const char *path, const char *id)
236 #ifdef HAVE_DLOPEN
237 ENGINE *engine;
238 void *handle;
239 int ret;
241 engine = calloc(1, sizeof(*engine));
242 if (engine == NULL)
243 return NULL;
245 handle = dlopen(path, RTLD_NOW);
246 if (handle == NULL) {
247 /* printf("error: %s\n", dlerror()); */
248 free(engine);
249 return NULL;
253 unsigned long version;
254 openssl_v_check v_check;
256 v_check = (openssl_v_check)dlsym(handle, "v_check");
257 if (v_check == NULL) {
258 dlclose(handle);
259 free(engine);
260 return NULL;
263 version = (*v_check)(OPENSSL_DYNAMIC_VERSION);
264 if (version == 0) {
265 dlclose(handle);
266 free(engine);
267 return NULL;
272 openssl_bind_engine bind_engine;
274 bind_engine = (openssl_bind_engine)dlsym(handle, "bind_engine");
275 if (bind_engine == NULL) {
276 dlclose(handle);
277 free(engine);
278 return NULL;
281 ret = (*bind_engine)(engine, id, NULL); /* XXX fix third arg */
282 if (ret != 1) {
283 dlclose(handle);
284 free(engine);
285 return NULL;
289 ENGINE_up_ref(engine);
291 ret = add_engine(engine);
292 if (ret != 1) {
293 dlclose(handle);
294 ENGINE_finish(engine);
295 return NULL;
298 return engine;
299 #else
300 return NULL;
301 #endif
304 ENGINE *
305 ENGINE_by_id(const char *id)
307 int i;
309 for (i = 0; i < num_engines; i++) {
310 if (strcmp(id, engines[i]->id) == 0) {
311 ENGINE_up_ref(engines[i]);
312 return engines[i];
315 return NULL;
318 void
319 ENGINE_add_conf_module(void)