1 /* $NetBSD: engine.c,v 1.3 2014/04/24 13:45:34 pettai Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Kungliga Tekniska Högskolan 5 * (Royal Institute of Technology, Stockholm, Sweden). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * 3. Neither the name of the Institute nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <config.h> 37 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 42 #include <engine.h> 43 44 #ifdef HAVE_DLFCN_H 45 #include <dlfcn.h> 46 #ifndef RTLD_NOW 47 #define RTLD_NOW 0 48 #endif 49 #endif 50 51 struct hc_engine { 52 int references; 53 char *name; 54 char *id; 55 void (*destroy)(ENGINE *); 56 const RSA_METHOD *rsa; 57 const DH_METHOD *dh; 58 const RAND_METHOD *rand; 59 }; 60 61 ENGINE * 62 ENGINE_new(void) 63 { 64 ENGINE *engine; 65 66 engine = calloc(1, sizeof(*engine)); 67 engine->references = 1; 68 69 return engine; 70 } 71 72 int 73 ENGINE_free(ENGINE *engine) 74 { 75 return ENGINE_finish(engine); 76 } 77 78 int 79 ENGINE_finish(ENGINE *engine) 80 { 81 if (engine->references-- <= 0) 82 abort(); 83 if (engine->references > 0) 84 return 1; 85 86 if (engine->name) 87 free(engine->name); 88 if (engine->id) 89 free(engine->id); 90 if(engine->destroy) 91 (*engine->destroy)(engine); 92 93 memset(engine, 0, sizeof(*engine)); 94 engine->references = -1; 95 96 97 free(engine); 98 return 1; 99 } 100 101 int 102 ENGINE_up_ref(ENGINE *engine) 103 { 104 if (engine->references < 0) 105 abort(); 106 engine->references++; 107 return 1; 108 } 109 110 int 111 ENGINE_set_id(ENGINE *engine, const char *id) 112 { 113 engine->id = strdup(id); 114 return (engine->id == NULL) ? 0 : 1; 115 } 116 117 int 118 ENGINE_set_name(ENGINE *engine, const char *name) 119 { 120 engine->name = strdup(name); 121 return (engine->name == NULL) ? 0 : 1; 122 } 123 124 int 125 ENGINE_set_RSA(ENGINE *engine, const RSA_METHOD *method) 126 { 127 engine->rsa = method; 128 return 1; 129 } 130 131 int 132 ENGINE_set_DH(ENGINE *engine, const DH_METHOD *method) 133 { 134 engine->dh = method; 135 return 1; 136 } 137 138 int 139 ENGINE_set_destroy_function(ENGINE *e, void (*destroy)(ENGINE *)) 140 { 141 e->destroy = destroy; 142 return 1; 143 } 144 145 const char * 146 ENGINE_get_id(const ENGINE *engine) 147 { 148 return engine->id; 149 } 150 151 const char * 152 ENGINE_get_name(const ENGINE *engine) 153 { 154 return engine->name; 155 } 156 157 const RSA_METHOD * 158 ENGINE_get_RSA(const ENGINE *engine) 159 { 160 return engine->rsa; 161 } 162 163 const DH_METHOD * 164 ENGINE_get_DH(const ENGINE *engine) 165 { 166 return engine->dh; 167 } 168 169 const RAND_METHOD * 170 ENGINE_get_RAND(const ENGINE *engine) 171 { 172 return engine->rand; 173 } 174 175 /* 176 * 177 */ 178 179 #define SG_default_engine(type) \ 180 static ENGINE *type##_engine; \ 181 int \ 182 ENGINE_set_default_##type(ENGINE *engine) \ 183 { \ 184 if (type##_engine) \ 185 ENGINE_finish(type##_engine); \ 186 type##_engine = engine; \ 187 if (type##_engine) \ 188 ENGINE_up_ref(type##_engine); \ 189 return 1; \ 190 } \ 191 ENGINE * \ 192 ENGINE_get_default_##type(void) \ 193 { \ 194 if (type##_engine) \ 195 ENGINE_up_ref(type##_engine); \ 196 return type##_engine; \ 197 } 198 199 SG_default_engine(RSA) 200 SG_default_engine(DH) 201 202 #undef SG_default_engine 203 204 /* 205 * 206 */ 207 208 static ENGINE **engines; 209 static unsigned int num_engines; 210 211 static int 212 add_engine(ENGINE *engine) 213 { 214 ENGINE **d, *dup; 215 216 dup = ENGINE_by_id(engine->id); 217 if (dup) 218 return 0; 219 220 d = realloc(engines, (num_engines + 1) * sizeof(*engines)); 221 if (d == NULL) 222 return 1; 223 engines = d; 224 engines[num_engines++] = engine; 225 226 return 1; 227 } 228 229 void 230 ENGINE_load_builtin_engines(void) 231 { 232 ENGINE *engine; 233 int ret; 234 235 engine = ENGINE_new(); 236 if (engine == NULL) 237 return; 238 239 ENGINE_set_id(engine, "builtin"); 240 ENGINE_set_name(engine, 241 "Heimdal crypto builtin (ltm) engine version " PACKAGE_VERSION); 242 ENGINE_set_RSA(engine, RSA_ltm_method()); 243 ENGINE_set_DH(engine, DH_ltm_method()); 244 245 ret = add_engine(engine); 246 if (ret != 1) 247 ENGINE_finish(engine); 248 249 #ifdef USE_HCRYPTO_TFM 250 /* 251 * TFM 252 */ 253 254 engine = ENGINE_new(); 255 if (engine == NULL) 256 return; 257 258 ENGINE_set_id(engine, "tfm"); 259 ENGINE_set_name(engine, 260 "Heimdal crypto tfm engine version " PACKAGE_VERSION); 261 ENGINE_set_RSA(engine, RSA_tfm_method()); 262 ENGINE_set_DH(engine, DH_tfm_method()); 263 264 ret = add_engine(engine); 265 if (ret != 1) 266 ENGINE_finish(engine); 267 #endif /* USE_HCRYPTO_TFM */ 268 269 #ifdef USE_HCRYPTO_LTM 270 /* 271 * ltm 272 */ 273 274 engine = ENGINE_new(); 275 if (engine == NULL) 276 return; 277 278 ENGINE_set_id(engine, "ltm"); 279 ENGINE_set_name(engine, 280 "Heimdal crypto ltm engine version " PACKAGE_VERSION); 281 ENGINE_set_RSA(engine, RSA_ltm_method()); 282 ENGINE_set_DH(engine, DH_ltm_method()); 283 284 ret = add_engine(engine); 285 if (ret != 1) 286 ENGINE_finish(engine); 287 #endif 288 289 #ifdef HAVE_GMP 290 /* 291 * gmp 292 */ 293 294 engine = ENGINE_new(); 295 if (engine == NULL) 296 return; 297 298 ENGINE_set_id(engine, "gmp"); 299 ENGINE_set_name(engine, 300 "Heimdal crypto gmp engine version " PACKAGE_VERSION); 301 ENGINE_set_RSA(engine, RSA_gmp_method()); 302 303 ret = add_engine(engine); 304 if (ret != 1) 305 ENGINE_finish(engine); 306 #endif 307 } 308 309 ENGINE * 310 ENGINE_by_dso(const char *path, const char *id) 311 { 312 #ifdef HAVE_DLOPEN 313 ENGINE *engine; 314 void *handle; 315 int ret; 316 317 engine = calloc(1, sizeof(*engine)); 318 if (engine == NULL) 319 return NULL; 320 321 handle = dlopen(path, RTLD_NOW); 322 if (handle == NULL) { 323 /* printf("error: %s\n", dlerror()); */ 324 free(engine); 325 return NULL; 326 } 327 328 { 329 unsigned long version; 330 openssl_v_check v_check; 331 332 v_check = (openssl_v_check)dlsym(handle, "v_check"); 333 if (v_check == NULL) { 334 dlclose(handle); 335 free(engine); 336 return NULL; 337 } 338 339 version = (*v_check)(OPENSSL_DYNAMIC_VERSION); 340 if (version == 0) { 341 dlclose(handle); 342 free(engine); 343 return NULL; 344 } 345 } 346 347 { 348 openssl_bind_engine bind_engine; 349 350 bind_engine = (openssl_bind_engine)dlsym(handle, "bind_engine"); 351 if (bind_engine == NULL) { 352 dlclose(handle); 353 free(engine); 354 return NULL; 355 } 356 357 ret = (*bind_engine)(engine, id, NULL); /* XXX fix third arg */ 358 if (ret != 1) { 359 dlclose(handle); 360 free(engine); 361 return NULL; 362 } 363 } 364 365 ENGINE_up_ref(engine); 366 367 ret = add_engine(engine); 368 if (ret != 1) { 369 dlclose(handle); 370 ENGINE_finish(engine); 371 return NULL; 372 } 373 374 return engine; 375 #else 376 return NULL; 377 #endif 378 } 379 380 ENGINE * 381 ENGINE_by_id(const char *id) 382 { 383 int i; 384 385 for (i = 0; i < num_engines; i++) { 386 if (strcmp(id, engines[i]->id) == 0) { 387 ENGINE_up_ref(engines[i]); 388 return engines[i]; 389 } 390 } 391 return NULL; 392 } 393 394 void 395 ENGINE_add_conf_module(void) 396 { 397 } 398