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 59int 60ENGINE_finish(ENGINE *engine) 61{ 62 if (engine->references-- <= 0) 63 abort(); 64 if (engine->references > 0) 65 return 1; 66 67 if (engine->name) 68 free(engine->name); 69 if (engine->id) 70 free(engine->id); 71 if(engine->destroy) 72 (*engine->destroy)(engine); 73 74 memset(engine, 0, sizeof(engine)); 75 engine->references = -1; 76 77 78 free(engine); 79 return 1; 80} 81 82int 83ENGINE_up_ref(ENGINE *engine) 84{ 85 if (engine->references < 0) 86 abort(); 87 engine->references++; 88 return 1; 89} 90 91int 92ENGINE_set_id(ENGINE *engine, const char *id) 93{ 94 engine->id = strdup(id); 95 return (engine->id == NULL) ? 0 : 1; 96} 97 98int 99ENGINE_set_name(ENGINE *engine, const char *name) 100{ 101 engine->name = strdup(name); 102 return (engine->name == NULL) ? 0 : 1; 103} 104 105int 106ENGINE_set_RSA(ENGINE *engine, const RSA_METHOD *method) 107{ 108 engine->rsa = method; 109 return 1; 110} 111 112int 113ENGINE_set_DH(ENGINE *engine, const DH_METHOD *method) 114{ 115 engine->dh = method; 116 return 1; 117} 118 119int 120ENGINE_set_destroy_function(ENGINE *e, void (*destroy)(ENGINE *)) 121{ 122 e->destroy = destroy; 123 return 1; 124} 125 126const char * 127ENGINE_get_id(const ENGINE *engine) 128{ 129 return engine->id; 130} 131 132const char * 133ENGINE_get_name(const ENGINE *engine) 134{ 135 return engine->name; 136} 137 138const RSA_METHOD * 139ENGINE_get_RSA(const ENGINE *engine) 140{ 141 return engine->rsa; 142} 143 144const DH_METHOD * 145ENGINE_get_DH(const ENGINE *engine) 146{ 147 return engine->dh; 148} 149 150const RAND_METHOD * 151ENGINE_get_RAND(const ENGINE *engine) 152{ 153 return engine->rand; 154} 155 156/* 157 * 158 */ 159 160#define SG_default_engine(type) \ 161static ENGINE *type##_engine; \ 162int \ 163ENGINE_set_default_##type(ENGINE *engine) \ 164{ \ 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; \ 171} \ 172ENGINE * \ 173ENGINE_get_default_##type(void) \ 174{ \ 175 if (type##_engine) \ 176 ENGINE_up_ref(type##_engine); \ 177 return type##_engine; \ 178} 179 180SG_default_engine(RSA) 181SG_default_engine(DH) 182 183#undef SG_default_engine 184 185/* 186 * 187 */ 188 189static ENGINE **engines; 190static unsigned int num_engines; 191 192static int 193add_engine(ENGINE *engine) 194{ 195 ENGINE **d, *dup; 196 197 dup = ENGINE_by_id(engine->id); 198 if (dup) { 199 ENGINE_finish(dup); 200 return 0; 201 } 202 203 d = realloc(engines, (num_engines + 1) * sizeof(*engines)); 204 if (d == NULL) 205 return 1; 206 engines = d; 207 engines[num_engines++] = engine; 208 209 return 1; 210} 211 212void 213ENGINE_load_builtin_engines(void) 214{ 215 ENGINE *engine; 216 int ret; 217 218 engine = calloc(1, sizeof(*engine)); 219 if (engine == NULL) 220 return; 221 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()); 227 228 ret = add_engine(engine); 229 if (ret != 1) 230 ENGINE_finish(engine); 231} 232 233ENGINE * 234ENGINE_by_dso(const char *path, const char *id) 235{ 236#ifdef HAVE_DLOPEN 237 ENGINE *engine; 238 void *handle; 239 int ret; 240 241 engine = calloc(1, sizeof(*engine)); 242 if (engine == NULL) 243 return NULL; 244 245 handle = dlopen(path, RTLD_NOW); 246 if (handle == NULL) { 247 /* printf("error: %s\n", dlerror()); */ 248 free(engine); 249 return NULL; 250 } 251 252 { 253 unsigned long version; 254 openssl_v_check v_check; 255 256 v_check = (openssl_v_check)dlsym(handle, "v_check"); 257 if (v_check == NULL) { 258 dlclose(handle); 259 free(engine); 260 return NULL; 261 } 262 263 version = (*v_check)(OPENSSL_DYNAMIC_VERSION); 264 if (version == 0) { 265 dlclose(handle); 266 free(engine); 267 return NULL; 268 } 269 } 270 271 { 272 openssl_bind_engine bind_engine; 273 274 bind_engine = (openssl_bind_engine)dlsym(handle, "bind_engine"); 275 if (bind_engine == NULL) { 276 dlclose(handle); 277 free(engine); 278 return NULL; 279 } 280 281 ret = (*bind_engine)(engine, id, NULL); /* XXX fix third arg */ 282 if (ret != 1) { 283 dlclose(handle); 284 free(engine); 285 return NULL; 286 } 287 } 288 289 ENGINE_up_ref(engine); 290 291 ret = add_engine(engine); 292 if (ret != 1) { 293 dlclose(handle); 294 ENGINE_finish(engine); 295 return NULL; 296 } 297 298 return engine; 299#else 300 return NULL; 301#endif 302} 303 304ENGINE * 305ENGINE_by_id(const char *id) 306{ 307 int i; 308 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]; 313 } 314 } 315 return NULL; 316} 317 318void 319ENGINE_add_conf_module(void) 320{ 321} 322