1/* 2 * Copyright (c) 2006 Kungliga Tekniska Högskolan 3 * (Royal Institute of Technology, Stockholm, Sweden). 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 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. 16 * 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. 20 * 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. 32 */ 33 34#include <config.h> 35 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39 40#include <engine.h> 41 42#ifdef HAVE_DLFCN_H 43#include <dlfcn.h> 44#ifndef RTLD_NOW 45#define RTLD_NOW 0 46#endif 47#endif 48 49struct 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; 57}; 58 59ENGINE * 60ENGINE_new(void) 61{ 62 ENGINE *engine; 63 64 engine = calloc(1, sizeof(*engine)); 65 engine->references = 1; 66 67 return engine; 68} 69 70int 71ENGINE_free(ENGINE *engine) 72{ 73 return ENGINE_finish(engine); 74} 75 76int 77ENGINE_finish(ENGINE *engine) 78{ 79 if (engine->references-- <= 0) 80 abort(); 81 if (engine->references > 0) 82 return 1; 83 84 if (engine->name) 85 free(engine->name); 86 if (engine->id) 87 free(engine->id); 88 if(engine->destroy) 89 (*engine->destroy)(engine); 90 91 memset(engine, 0, sizeof(*engine)); 92 engine->references = -1; 93 94 95 free(engine); 96 return 1; 97} 98 99int 100ENGINE_up_ref(ENGINE *engine) 101{ 102 if (engine->references < 0) 103 abort(); 104 engine->references++; 105 return 1; 106} 107 108int 109ENGINE_set_id(ENGINE *engine, const char *id) 110{ 111 engine->id = strdup(id); 112 return (engine->id == NULL) ? 0 : 1; 113} 114 115int 116ENGINE_set_name(ENGINE *engine, const char *name) 117{ 118 engine->name = strdup(name); 119 return (engine->name == NULL) ? 0 : 1; 120} 121 122int 123ENGINE_set_RSA(ENGINE *engine, const RSA_METHOD *method) 124{ 125 engine->rsa = method; 126 return 1; 127} 128 129int 130ENGINE_set_DH(ENGINE *engine, const DH_METHOD *method) 131{ 132 engine->dh = method; 133 return 1; 134} 135 136int 137ENGINE_set_destroy_function(ENGINE *e, void (*destroy)(ENGINE *)) 138{ 139 e->destroy = destroy; 140 return 1; 141} 142 143const char * 144ENGINE_get_id(const ENGINE *engine) 145{ 146 return engine->id; 147} 148 149const char * 150ENGINE_get_name(const ENGINE *engine) 151{ 152 return engine->name; 153} 154 155const RSA_METHOD * 156ENGINE_get_RSA(const ENGINE *engine) 157{ 158 return engine->rsa; 159} 160 161const DH_METHOD * 162ENGINE_get_DH(const ENGINE *engine) 163{ 164 return engine->dh; 165} 166 167const RAND_METHOD * 168ENGINE_get_RAND(const ENGINE *engine) 169{ 170 return engine->rand; 171} 172 173/* 174 * 175 */ 176 177#define SG_default_engine(type) \ 178static ENGINE *type##_engine; \ 179int \ 180ENGINE_set_default_##type(ENGINE *engine) \ 181{ \ 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; \ 188} \ 189ENGINE * \ 190ENGINE_get_default_##type(void) \ 191{ \ 192 if (type##_engine) \ 193 ENGINE_up_ref(type##_engine); \ 194 return type##_engine; \ 195} 196 197SG_default_engine(RSA) 198SG_default_engine(DH) 199 200#undef SG_default_engine 201 202/* 203 * 204 */ 205 206static ENGINE **engines; 207static unsigned int num_engines; 208 209static int 210add_engine(ENGINE *engine) 211{ 212 ENGINE **d, *dup; 213 214 dup = ENGINE_by_id(engine->id); 215 if (dup) 216 return 0; 217 218 d = realloc(engines, (num_engines + 1) * sizeof(*engines)); 219 if (d == NULL) 220 return 1; 221 engines = d; 222 engines[num_engines++] = engine; 223 224 return 1; 225} 226 227void 228ENGINE_load_builtin_engines(void) 229{ 230 ENGINE *engine; 231 int ret; 232 233 engine = ENGINE_new(); 234 if (engine == NULL) 235 return; 236 237 ENGINE_set_id(engine, "builtin"); 238 ENGINE_set_name(engine, 239 "Heimdal crypto builtin engine version " PACKAGE_VERSION); 240#ifdef HAVE_CDSA 241 ENGINE_set_DH(engine, DH_cdsa_method()); 242 ENGINE_set_RSA(engine, RSA_cdsa_method()); 243#elif defined(HEIM_HC_SF) 244 ENGINE_set_RSA(engine, RSA_sf_method()); 245 ENGINE_set_DH(engine, DH_sf_method()); 246#elif defined(HEIM_HC_LTM) 247 ENGINE_set_RSA(engine, RSA_ltm_method()); 248 ENGINE_set_DH(engine, DH_ltm_method()); 249#else 250 ENGINE_set_RSA(engine, RSA_tfm_method()); 251 ENGINE_set_DH(engine, DH_tfm_method()); 252#endif 253 254 ret = add_engine(engine); 255 if (ret != 1) 256 ENGINE_finish(engine); 257 258#ifdef USE_HCRYPTO_TFM 259 /* 260 * TFM 261 */ 262 263 engine = ENGINE_new(); 264 if (engine == NULL) 265 return; 266 267 ENGINE_set_id(engine, "tfm"); 268 ENGINE_set_name(engine, 269 "Heimdal crypto tfm engine version " PACKAGE_VERSION); 270 ENGINE_set_RSA(engine, RSA_tfm_method()); 271 ENGINE_set_DH(engine, DH_tfm_method()); 272 273 ret = add_engine(engine); 274 if (ret != 1) 275 ENGINE_finish(engine); 276#endif /* USE_HCRYPTO_TFM */ 277 278#ifdef USE_HCRYPTO_LTM 279 /* 280 * ltm 281 */ 282 283 engine = ENGINE_new(); 284 if (engine == NULL) 285 return; 286 287 ENGINE_set_id(engine, "ltm"); 288 ENGINE_set_name(engine, 289 "Heimdal crypto ltm engine version " PACKAGE_VERSION); 290 ENGINE_set_RSA(engine, RSA_ltm_method()); 291 ENGINE_set_DH(engine, DH_ltm_method()); 292 293 ret = add_engine(engine); 294 if (ret != 1) 295 ENGINE_finish(engine); 296#endif 297 298#ifdef HAVE_GMP 299 /* 300 * gmp 301 */ 302 303 engine = ENGINE_new(); 304 if (engine == NULL) 305 return; 306 307 ENGINE_set_id(engine, "gmp"); 308 ENGINE_set_name(engine, 309 "Heimdal crypto gmp engine version " PACKAGE_VERSION); 310 ENGINE_set_RSA(engine, RSA_gmp_method()); 311 312 ret = add_engine(engine); 313 if (ret != 1) 314 ENGINE_finish(engine); 315#endif 316} 317 318ENGINE * 319ENGINE_by_dso(const char *path, const char *id) 320{ 321#ifdef HAVE_DLOPEN 322 ENGINE *engine; 323 void *handle; 324 int ret; 325 326 engine = calloc(1, sizeof(*engine)); 327 if (engine == NULL) 328 return NULL; 329 330 handle = dlopen(path, RTLD_NOW); 331 if (handle == NULL) { 332 /* printf("error: %s\n", dlerror()); */ 333 free(engine); 334 return NULL; 335 } 336 337 { 338 unsigned long version; 339 openssl_v_check v_check; 340 341 v_check = (openssl_v_check)dlsym(handle, "v_check"); 342 if (v_check == NULL) { 343 dlclose(handle); 344 free(engine); 345 return NULL; 346 } 347 348 version = (*v_check)(OPENSSL_DYNAMIC_VERSION); 349 if (version == 0) { 350 dlclose(handle); 351 free(engine); 352 return NULL; 353 } 354 } 355 356 { 357 openssl_bind_engine bind_engine; 358 359 bind_engine = (openssl_bind_engine)dlsym(handle, "bind_engine"); 360 if (bind_engine == NULL) { 361 dlclose(handle); 362 free(engine); 363 return NULL; 364 } 365 366 ret = (*bind_engine)(engine, id, NULL); /* XXX fix third arg */ 367 if (ret != 1) { 368 dlclose(handle); 369 free(engine); 370 return NULL; 371 } 372 } 373 374 ENGINE_up_ref(engine); 375 376 ret = add_engine(engine); 377 if (ret != 1) { 378 dlclose(handle); 379 ENGINE_finish(engine); 380 return NULL; 381 } 382 383 return engine; 384#else 385 return NULL; 386#endif 387} 388 389ENGINE * 390ENGINE_by_id(const char *id) 391{ 392 size_t i; 393 394 for (i = 0; i < num_engines; i++) { 395 if (strcmp(id, engines[i]->id) == 0) { 396 ENGINE_up_ref(engines[i]); 397 return engines[i]; 398 } 399 } 400 return NULL; 401} 402 403void 404ENGINE_add_conf_module(void) 405{ 406} 407