1/* 2 * Copyright (c) 2011-12 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24/* 25 * Copyright (c) 2006 Kungliga Tekniska Högskolan 26 * (Royal Institute of Technology, Stockholm, Sweden). 27 * All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 33 * 1. Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * 36 * 2. Redistributions in binary form must reproduce the above copyright 37 * notice, this list of conditions and the following disclaimer in the 38 * documentation and/or other materials provided with the distribution. 39 * 40 * 3. Neither the name of the Institute nor the names of its contributors 41 * may be used to endorse or promote products derived from this software 42 * without specific prior written permission. 43 * 44 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * SUCH DAMAGE. 55 */ 56 57#include "ossl-config.h" 58 59#include <stdio.h> 60#include <stdlib.h> 61#include <string.h> 62 63#include "ossl-engine.h" 64 65#ifdef HAVE_DLFCN_H 66#include <dlfcn.h> 67#ifndef RTLD_NOW 68#define RTLD_NOW 0 69#endif 70#endif 71 72#ifndef PACKAGE_VERSION 73#define PACKAGE_VERSION "0.9.0" 74#endif 75 76struct ossl_engine { 77 int references; 78 char * name; 79 char * id; 80 void (*destroy)(ENGINE *); 81 const DSA_METHOD * dsa; 82 const RSA_METHOD * rsa; 83 const DH_METHOD * dh; 84 const RAND_METHOD * rand; 85}; 86 87ENGINE * 88ENGINE_new(void) 89{ 90 ENGINE *engine; 91 92 engine = calloc(1, sizeof(*engine)); 93 engine->references = 1; 94 95 return (engine); 96} 97 98 99int 100ENGINE_free(ENGINE *engine) 101{ 102 return (ENGINE_finish(engine)); 103} 104 105 106int 107ENGINE_finish(ENGINE *engine) 108{ 109 if (engine->references-- <= 0) { 110 abort(); 111 } 112 if (engine->references > 0) { 113 return (1); 114 } 115 116 if (engine->name) { 117 free(engine->name); 118 } 119 if (engine->id) { 120 free(engine->id); 121 } 122 if (engine->destroy) { 123 (*engine->destroy)(engine); 124 } 125 126 memset(engine, 0, sizeof(*engine)); 127 engine->references = -1; 128 129 130 free(engine); 131 return (1); 132} 133 134 135int 136ENGINE_up_ref(ENGINE *engine) 137{ 138 if (engine->references < 0) { 139 abort(); 140 } 141 engine->references++; /* XXX atomic op */ 142 return (1); 143} 144 145 146int 147ENGINE_set_id(ENGINE *engine, const char *id) 148{ 149 engine->id = strdup(id); 150 return ((engine->id == NULL) ? 0 : 1); 151} 152 153 154int 155ENGINE_set_name(ENGINE *engine, const char *name) 156{ 157 engine->name = strdup(name); 158 return ((engine->name == NULL) ? 0 : 1); 159} 160 161 162int 163ENGINE_set_DSA(ENGINE *engine, const DSA_METHOD *method) 164{ 165 engine->dsa = method; 166 return (1); 167} 168 169 170int 171ENGINE_set_RSA(ENGINE *engine, const RSA_METHOD *method) 172{ 173 engine->rsa = method; 174 return (1); 175} 176 177 178int 179ENGINE_set_DH(ENGINE *engine, const DH_METHOD *method) 180{ 181 engine->dh = method; 182 return (1); 183} 184 185 186int 187ENGINE_set_destroy_function(ENGINE *e, void (*destroy)(ENGINE *)) 188{ 189 e->destroy = destroy; 190 return (1); 191} 192 193 194const char * 195ENGINE_get_id(const ENGINE *engine) 196{ 197 return (engine->id); 198} 199 200 201const char * 202ENGINE_get_name(const ENGINE *engine) 203{ 204 return (engine->name); 205} 206 207 208const DSA_METHOD * 209ENGINE_get_DSA(const ENGINE *engine) 210{ 211 return (engine->dsa); 212} 213 214 215const RSA_METHOD * 216ENGINE_get_RSA(const ENGINE *engine) 217{ 218 return (engine->rsa); 219} 220 221 222const DH_METHOD * 223ENGINE_get_DH(const ENGINE *engine) 224{ 225 return (engine->dh); 226} 227 228 229const RAND_METHOD * 230ENGINE_get_RAND(const ENGINE *engine) 231{ 232 return (engine->rand); 233} 234 235 236/* 237 * 238 */ 239 240#define SG_default_engine(type) \ 241 static ENGINE *type ## _engine; \ 242 int \ 243 ENGINE_set_default_ ## type(ENGINE *engine) \ 244 { \ 245 if (type ## _engine) { \ 246 ENGINE_finish(type ## _engine); } \ 247 type ## _engine = engine; \ 248 if (type ## _engine) { \ 249 ENGINE_up_ref(type ## _engine); } \ 250 return 1; \ 251 } \ 252 ENGINE * \ 253 ENGINE_get_default_ ## type(void) \ 254 { \ 255 if (type ## _engine) { \ 256 ENGINE_up_ref(type ## _engine); } \ 257 return type ## _engine; \ 258 } 259 260SG_default_engine(DSA) 261SG_default_engine(RSA) 262SG_default_engine(DH) 263 264#undef SG_default_engine 265 266/* 267 * 268 */ 269 270static ENGINE **engines; 271static unsigned int num_engines; 272 273static int 274add_engine(ENGINE *engine) 275{ 276 ENGINE **d, *dup; 277 278 dup = ENGINE_by_id(engine->id); 279 if (dup) { 280 return (0); 281 } 282 283 d = realloc(engines, (num_engines + 1) * sizeof(*engines)); 284 if (d == NULL) { 285 return (1); 286 } 287 engines = d; 288 engines[num_engines++] = engine; 289 290 return (1); 291} 292 293 294#if !defined(PR_10783242_FIXED) || !defined(PR_8174774_FIXED) || !defined(PR_10488503_FIXED) || !defined(PR_10771223_FIXED) || !defined(PR_10771188_FIXED) 295const DH_METHOD *DH_eay_method(void); 296const DSA_METHOD *DSA_eay_method(void); 297const RSA_METHOD *RSA_eay_method(void); 298 299#endif 300 301void 302ENGINE_load_builtin_engines(void) 303{ 304 ENGINE *engine; 305 int ret; 306 307 engine = ENGINE_new(); 308 if (engine == NULL) { 309 return; 310 } 311 312 ENGINE_set_id(engine, "builtin"); 313 ENGINE_set_name(engine, 314 "cryptoshims builtin engine version " PACKAGE_VERSION); 315 316/* 317 * XXX <radr://problem/107832242> and <rda://problem/8174874> are 318 * blocking the use of CommonCrypto's RSA code for OpenSSH. 319 * 320 * XXX <rdar://problem/10488503> is blocking the use of 321 * CommonCrypto's (non-existing) DSA. 322 * 323 * XXX <rdar://problem/10771223> and <rdar://problem/10771188> are 324 * blocking the use of CommonCrypto's DH code. 325 */ 326#if !defined(PR_10783242_FIXED) || !defined(PR_8174774_FIXED) || !defined(PR_10488503_FIXED) || !defined(PR_10771223_FIXED) || !defined(PR_10771188_FIXED) 327 ENGINE_set_DH(engine, DH_eay_method()); 328 ENGINE_set_DSA(engine, DSA_eay_method()); 329 ENGINE_set_RSA(engine, RSA_eay_method()); 330#elif defined(HAVE_COMMONCRYPTO_COMMONRSACRYPTOR_H) && defined(HAVE_COMMONCRYPTO_COMMONDH_H) && defined(HAVE_COMMONCRYPTO_COMMONDSACRYPTOR_H) 331 ENGINE_set_DH(engine, DH_eay_method()); 332 ENGINE_set_DSA(engine, DSA_eay_method()); 333 ENGINE_set_RSA(engine, RSA_cc_method()); 334#elif HAVE_CDSA 335 ENGINE_set_DH(engine, DH_cdsa_method()); 336 ENGINE_set_DSA(engine, DSA_null_method()); 337 ENGINE_set_RSA(engine, RSA_cdsa_method()); 338#elif defined(__APPLE_TARGET_EMBEDDED__) 339 ENGINE_set_DH(engine, DH_null_method()); 340 ENGINE_set_DSA(engine, DSA_null_method()); 341 ENGINE_set_RSA(engine, RSA_null_method()); 342#elif defined(HEIM_HC_SF) 343 ENGINE_set_RSA(engine, RSA_ltm_method()); 344 ENGINE_set_DH(engine, DH_sf_method()); 345 ENGINE_set_DSA(engine, DSA_null_method()); 346#elif defined(HEIM_HC_LTM) 347 ENGINE_set_RSA(engine, RSA_ltm_method()); 348 ENGINE_set_DH(engine, DH_ltm_method()); 349 ENGINE_set_DSA(engine, DSA_null_method()); 350#else 351 ENGINE_set_RSA(engine, RSA_tfm_method()); 352 ENGINE_set_DH(engine, DH_tfm_method()); 353 ENGINE_set_DSA(engine, DSA_null_method()); 354#endif 355 356 ret = add_engine(engine); 357 if (ret != 1) { 358 ENGINE_finish(engine); 359 } 360 361#if !defined(PR_10783242_FIXED) || !defined(PR_8174774_FIXED) || !defined(PR_1048850_FIXED) || !defined(PR_10771223_FIXED) || !defined(PR_10771188_FIXED) 362 363 /* 364 * EAY 365 */ 366 engine = ENGINE_new(); 367 if (engine == NULL) { 368 return; 369 } 370 371 ENGINE_set_id(engine, "eay"); 372 ENGINE_set_name(engine, 373 "ossl eay engine version " PACKAGE_VERSION); 374 ENGINE_set_RSA(engine, RSA_eay_method()); 375 ENGINE_set_DH(engine, DH_eay_method()); 376 ENGINE_set_DSA(engine, DSA_eay_method()); 377 378 ret = add_engine(engine); 379 if (ret != 1) { 380 ENGINE_finish(engine); 381 } 382#endif 383 384#if defined(HAVE_COMMONCRYPTO_COMMONRSACRYPTOR_H) && defined(HAVE_COMMONCRYPTO_COMMONDH_H) && defined(HAVE_COMMONCRYPTO_COMMONDSACRYPTOR_H) 385 386 /* 387 * CC 388 */ 389 engine = ENGINE_new(); 390 if (engine == NULL) { 391 return; 392 } 393 394 ENGINE_set_id(engine, "cc"); 395 ENGINE_set_name(engine, 396 "ossl cc engine version " PACKAGE_VERSION); 397 ENGINE_set_RSA(engine, RSA_cc_method()); 398 ENGINE_set_DH(engine, DH_cc_method()); 399 ENGINE_set_DSA(engine, DSA_eay_method()); 400 401 ret = add_engine(engine); 402 if (ret != 1) { 403 ENGINE_finish(engine); 404 } 405#endif /* COMMONCRYPTO */ 406 407#ifdef USE_HCRYPTO_TFM 408 409 /* 410 * TFM 411 */ 412 413 engine = ENGINE_new(); 414 if (engine == NULL) { 415 return; 416 } 417 418 ENGINE_set_id(engine, "tfm"); 419 ENGINE_set_name(engine, 420 "ossl tfm engine version " PACKAGE_VERSION); 421 ENGINE_set_RSA(engine, RSA_tfm_method()); 422 ENGINE_set_DH(engine, DH_tfm_method()); 423 424 ret = add_engine(engine); 425 if (ret != 1) { 426 ENGINE_finish(engine); 427 } 428#endif /* USE_HCRYPTO_TFM */ 429 430#ifdef USE_HCRYPTO_LTM 431 432 /* 433 * ltm 434 */ 435 436 engine = ENGINE_new(); 437 if (engine == NULL) { 438 return; 439 } 440 441 ENGINE_set_id(engine, "ltm"); 442 ENGINE_set_name(engine, 443 "ossl ltm engine version " PACKAGE_VERSION); 444 ENGINE_set_RSA(engine, RSA_ltm_method()); 445 ENGINE_set_DH(engine, DH_ltm_method()); 446 447 ret = add_engine(engine); 448 if (ret != 1) { 449 ENGINE_finish(engine); 450 } 451#endif 452 453#ifdef HAVE_GMP 454 455 /* 456 * gmp 457 */ 458 459 engine = ENGINE_new(); 460 if (engine == NULL) { 461 return; 462 } 463 464 ENGINE_set_id(engine, "gmp"); 465 ENGINE_set_name(engine, 466 "ossl gmp engine version " PACKAGE_VERSION); 467 ENGINE_set_RSA(engine, RSA_gmp_method()); 468 469 ret = add_engine(engine); 470 if (ret != 1) { 471 ENGINE_finish(engine); 472 } 473#endif 474} 475 476 477ENGINE * 478ENGINE_by_dso(const char *path, const char *id) 479{ 480#ifdef HAVE_DLOPEN 481 ENGINE *engine; 482 void *handle; 483 int ret; 484 485 engine = calloc(1, sizeof(*engine)); 486 if (engine == NULL) { 487 return (NULL); 488 } 489 490 handle = dlopen(path, RTLD_NOW); 491 if (handle == NULL) { 492 /* printf("error: %s\n", dlerror()); */ 493 free(engine); 494 return (NULL); 495 } 496 497 { 498 unsigned long version; 499 openssl_v_check v_check; 500 501 v_check = (openssl_v_check)dlsym(handle, "v_check"); 502 if (v_check == NULL) { 503 dlclose(handle); 504 free(engine); 505 return (NULL); 506 } 507 508 version = (*v_check)(OPENSSL_DYNAMIC_VERSION); 509 if (version == 0) { 510 dlclose(handle); 511 free(engine); 512 return (NULL); 513 } 514 } 515 516 { 517 openssl_bind_engine bind_engine; 518 519 bind_engine = (openssl_bind_engine)dlsym(handle, "bind_engine"); 520 if (bind_engine == NULL) { 521 dlclose(handle); 522 free(engine); 523 return (NULL); 524 } 525 526 ret = (*bind_engine)(engine, id, NULL); /* XXX fix third arg */ 527 if (ret != 1) { 528 dlclose(handle); 529 free(engine); 530 return (NULL); 531 } 532 } 533 534 ENGINE_up_ref(engine); 535 536 ret = add_engine(engine); 537 if (ret != 1) { 538 dlclose(handle); 539 ENGINE_finish(engine); 540 return (NULL); 541 } 542 543 return (engine); 544 545#else 546 return (NULL); 547#endif 548} 549 550 551ENGINE * 552ENGINE_by_id(const char *id) 553{ 554 int i; 555 556 for (i = 0; i < num_engines; i++) { 557 if (strcmp(id, engines[i]->id) == 0) { 558 ENGINE_up_ref(engines[i]); 559 return (engines[i]); 560 } 561 } 562 return (NULL); 563} 564 565 566void 567ENGINE_add_conf_module(void) 568{ 569} 570