e_chil.c revision 306195
1/* crypto/engine/e_chil.c */ 2/* 3 * Written by Richard Levitte (richard@levitte.org), Geoff Thorpe 4 * (geoff@geoffthorpe.net) and Dr Stephen N Henson (steve@openssl.org) for 5 * the OpenSSL project 2000. 6 */ 7/* ==================================================================== 8 * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in 19 * the documentation and/or other materials provided with the 20 * distribution. 21 * 22 * 3. All advertising materials mentioning features or use of this 23 * software must display the following acknowledgment: 24 * "This product includes software developed by the OpenSSL Project 25 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 26 * 27 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 28 * endorse or promote products derived from this software without 29 * prior written permission. For written permission, please contact 30 * licensing@OpenSSL.org. 31 * 32 * 5. Products derived from this software may not be called "OpenSSL" 33 * nor may "OpenSSL" appear in their names without prior written 34 * permission of the OpenSSL Project. 35 * 36 * 6. Redistributions of any form whatsoever must retain the following 37 * acknowledgment: 38 * "This product includes software developed by the OpenSSL Project 39 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 42 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 44 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 48 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 50 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 51 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 52 * OF THE POSSIBILITY OF SUCH DAMAGE. 53 * ==================================================================== 54 * 55 * This product includes cryptographic software written by Eric Young 56 * (eay@cryptsoft.com). This product includes software written by Tim 57 * Hudson (tjh@cryptsoft.com). 58 * 59 */ 60 61#include <stdio.h> 62#include <string.h> 63#include <openssl/crypto.h> 64#include <openssl/pem.h> 65#include <openssl/dso.h> 66#include <openssl/engine.h> 67#include <openssl/ui.h> 68#include <openssl/rand.h> 69#ifndef OPENSSL_NO_RSA 70# include <openssl/rsa.h> 71#endif 72#ifndef OPENSSL_NO_DH 73# include <openssl/dh.h> 74#endif 75#include <openssl/bn.h> 76 77#ifndef OPENSSL_NO_HW 78# ifndef OPENSSL_NO_HW_CHIL 79 80/*- 81 * Attribution notice: nCipher have said several times that it's OK for 82 * us to implement a general interface to their boxes, and recently declared 83 * their HWCryptoHook to be public, and therefore available for us to use. 84 * Thanks, nCipher. 85 * 86 * The hwcryptohook.h included here is from May 2000. 87 * [Richard Levitte] 88 */ 89# ifdef FLAT_INC 90# include "hwcryptohook.h" 91# else 92# include "vendor_defns/hwcryptohook.h" 93# endif 94 95# define HWCRHK_LIB_NAME "CHIL engine" 96# include "e_chil_err.c" 97 98static int hwcrhk_destroy(ENGINE *e); 99static int hwcrhk_init(ENGINE *e); 100static int hwcrhk_finish(ENGINE *e); 101static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)); 102 103/* Functions to handle mutexes */ 104static int hwcrhk_mutex_init(HWCryptoHook_Mutex *, 105 HWCryptoHook_CallerContext *); 106static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *); 107static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex *); 108static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *); 109 110/* BIGNUM stuff */ 111static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 112 const BIGNUM *m, BN_CTX *ctx); 113 114# ifndef OPENSSL_NO_RSA 115/* RSA stuff */ 116static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, 117 BN_CTX *ctx); 118/* This function is aliased to mod_exp (with the mont stuff dropped). */ 119static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 120 const BIGNUM *m, BN_CTX *ctx, 121 BN_MONT_CTX *m_ctx); 122static int hwcrhk_rsa_finish(RSA *rsa); 123# endif 124 125# ifndef OPENSSL_NO_DH 126/* DH stuff */ 127/* This function is alised to mod_exp (with the DH and mont dropped). */ 128static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r, 129 const BIGNUM *a, const BIGNUM *p, 130 const BIGNUM *m, BN_CTX *ctx, 131 BN_MONT_CTX *m_ctx); 132# endif 133 134/* RAND stuff */ 135static int hwcrhk_rand_bytes(unsigned char *buf, int num); 136static int hwcrhk_rand_status(void); 137 138/* KM stuff */ 139static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id, 140 UI_METHOD *ui_method, 141 void *callback_data); 142static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id, 143 UI_METHOD *ui_method, 144 void *callback_data); 145 146/* Interaction stuff */ 147static int hwcrhk_insert_card(const char *prompt_info, 148 const char *wrong_info, 149 HWCryptoHook_PassphraseContext * ppctx, 150 HWCryptoHook_CallerContext * cactx); 151static int hwcrhk_get_pass(const char *prompt_info, 152 int *len_io, char *buf, 153 HWCryptoHook_PassphraseContext * ppctx, 154 HWCryptoHook_CallerContext * cactx); 155static void hwcrhk_log_message(void *logstr, const char *message); 156 157/* The definitions for control commands specific to this engine */ 158# define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE 159# define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1) 160# define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2) 161# define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3) 162# define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4) 163static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = { 164 {HWCRHK_CMD_SO_PATH, 165 "SO_PATH", 166 "Specifies the path to the 'hwcrhk' shared library", 167 ENGINE_CMD_FLAG_STRING}, 168 {HWCRHK_CMD_FORK_CHECK, 169 "FORK_CHECK", 170 "Turns fork() checking on (non-zero) or off (zero)", 171 ENGINE_CMD_FLAG_NUMERIC}, 172 {HWCRHK_CMD_THREAD_LOCKING, 173 "THREAD_LOCKING", 174 "Turns thread-safe locking on (zero) or off (non-zero)", 175 ENGINE_CMD_FLAG_NUMERIC}, 176 {HWCRHK_CMD_SET_USER_INTERFACE, 177 "SET_USER_INTERFACE", 178 "Set the global user interface (internal)", 179 ENGINE_CMD_FLAG_INTERNAL}, 180 {HWCRHK_CMD_SET_CALLBACK_DATA, 181 "SET_CALLBACK_DATA", 182 "Set the global user interface extra data (internal)", 183 ENGINE_CMD_FLAG_INTERNAL}, 184 {0, NULL, NULL, 0} 185}; 186 187# ifndef OPENSSL_NO_RSA 188/* Our internal RSA_METHOD that we provide pointers to */ 189static RSA_METHOD hwcrhk_rsa = { 190 "CHIL RSA method", 191 NULL, 192 NULL, 193 NULL, 194 NULL, 195 hwcrhk_rsa_mod_exp, 196 hwcrhk_mod_exp_mont, 197 NULL, 198 hwcrhk_rsa_finish, 199 0, 200 NULL, 201 NULL, 202 NULL, 203 NULL 204}; 205# endif 206 207# ifndef OPENSSL_NO_DH 208/* Our internal DH_METHOD that we provide pointers to */ 209static DH_METHOD hwcrhk_dh = { 210 "CHIL DH method", 211 NULL, 212 NULL, 213 hwcrhk_mod_exp_dh, 214 NULL, 215 NULL, 216 0, 217 NULL, 218 NULL 219}; 220# endif 221 222static RAND_METHOD hwcrhk_rand = { 223 /* "CHIL RAND method", */ 224 NULL, 225 hwcrhk_rand_bytes, 226 NULL, 227 NULL, 228 hwcrhk_rand_bytes, 229 hwcrhk_rand_status, 230}; 231 232/* Constants used when creating the ENGINE */ 233static const char *engine_hwcrhk_id = "chil"; 234static const char *engine_hwcrhk_name = "CHIL hardware engine support"; 235# ifndef OPENSSL_NO_DYNAMIC_ENGINE 236/* Compatibility hack, the dynamic library uses this form in the path */ 237static const char *engine_hwcrhk_id_alt = "ncipher"; 238# endif 239 240/* Internal stuff for HWCryptoHook */ 241 242/* Some structures needed for proper use of thread locks */ 243/* 244 * hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue 245 * into HWCryptoHook_Mutex 246 */ 247struct HWCryptoHook_MutexValue { 248 int lockid; 249}; 250 251/* 252 * hwcryptohook.h has some typedefs that turn struct 253 * HWCryptoHook_PassphraseContextValue into HWCryptoHook_PassphraseContext 254 */ 255struct HWCryptoHook_PassphraseContextValue { 256 UI_METHOD *ui_method; 257 void *callback_data; 258}; 259 260/* 261 * hwcryptohook.h has some typedefs that turn struct 262 * HWCryptoHook_CallerContextValue into HWCryptoHook_CallerContext 263 */ 264struct HWCryptoHook_CallerContextValue { 265 pem_password_cb *password_callback; /* Deprecated! Only present for 266 * backward compatibility! */ 267 UI_METHOD *ui_method; 268 void *callback_data; 269}; 270 271/* 272 * The MPI structure in HWCryptoHook is pretty compatible with OpenSSL 273 * BIGNUM's, so lets define a couple of conversion macros 274 */ 275# define BN2MPI(mp, bn) \ 276 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;} 277# define MPI2BN(bn, mp) \ 278 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;} 279 280static BIO *logstream = NULL; 281static int disable_mutex_callbacks = 0; 282 283/* 284 * One might wonder why these are needed, since one can pass down at least a 285 * UI_METHOD and a pointer to callback data to the key-loading functions. The 286 * thing is that the ModExp and RSAImmed functions can load keys as well, if 287 * the data they get is in a special, nCipher-defined format (hint: if you 288 * look at the private exponent of the RSA data as a string, you'll see this 289 * string: "nCipher KM tool key id", followed by some bytes, followed a key 290 * identity string, followed by more bytes. This happens when you use 291 * "embed" keys instead of "hwcrhk" keys). Unfortunately, those functions do 292 * not take any passphrase or caller context, and our functions can't really 293 * take any callback data either. Still, the "insert_card" and 294 * "get_passphrase" callbacks may be called down the line, and will need to 295 * know what user interface callbacks to call, and having callback data from 296 * the application may be a nice thing as well, so we need to keep track of 297 * that globally. 298 */ 299static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL }; 300 301/* Stuff to pass to the HWCryptoHook library */ 302static HWCryptoHook_InitInfo hwcrhk_globals = { 303 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */ 304 &logstream, /* logstream */ 305 sizeof(BN_ULONG), /* limbsize */ 306 0, /* mslimb first: false for BNs */ 307 -1, /* msbyte first: use native */ 308 0, /* Max mutexes, 0 = no small limit */ 309 0, /* Max simultaneous, 0 = default */ 310 311 /* 312 * The next few are mutex stuff: we write wrapper functions around the OS 313 * mutex functions. We initialise them to 0 here, and change that to 314 * actual function pointers in hwcrhk_init() if dynamic locks are 315 * supported (that is, if the application programmer has made sure of 316 * setting up callbacks bafore starting this engine) *and* if 317 * disable_mutex_callbacks hasn't been set by a call to 318 * ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). 319 */ 320 sizeof(HWCryptoHook_Mutex), 321 0, 322 0, 323 0, 324 0, 325 326 /* 327 * The next few are condvar stuff: we write wrapper functions round the 328 * OS functions. Currently not implemented and not and absolute 329 * necessity even in threaded programs, therefore 0'ed. Will hopefully 330 * be implemented some day, since it enhances the efficiency of 331 * HWCryptoHook. 332 */ 333 0, /* sizeof(HWCryptoHook_CondVar), */ 334 0, /* hwcrhk_cv_init, */ 335 0, /* hwcrhk_cv_wait, */ 336 0, /* hwcrhk_cv_signal, */ 337 0, /* hwcrhk_cv_broadcast, */ 338 0, /* hwcrhk_cv_destroy, */ 339 340 hwcrhk_get_pass, /* pass phrase */ 341 hwcrhk_insert_card, /* insert a card */ 342 hwcrhk_log_message /* Log message */ 343}; 344 345/* Now, to our own code */ 346 347/* 348 * This internal function is used by ENGINE_chil() and possibly by the 349 * "dynamic" ENGINE support too 350 */ 351static int bind_helper(ENGINE *e) 352{ 353# ifndef OPENSSL_NO_RSA 354 const RSA_METHOD *meth1; 355# endif 356# ifndef OPENSSL_NO_DH 357 const DH_METHOD *meth2; 358# endif 359 if (!ENGINE_set_id(e, engine_hwcrhk_id) || 360 !ENGINE_set_name(e, engine_hwcrhk_name) || 361# ifndef OPENSSL_NO_RSA 362 !ENGINE_set_RSA(e, &hwcrhk_rsa) || 363# endif 364# ifndef OPENSSL_NO_DH 365 !ENGINE_set_DH(e, &hwcrhk_dh) || 366# endif 367 !ENGINE_set_RAND(e, &hwcrhk_rand) || 368 !ENGINE_set_destroy_function(e, hwcrhk_destroy) || 369 !ENGINE_set_init_function(e, hwcrhk_init) || 370 !ENGINE_set_finish_function(e, hwcrhk_finish) || 371 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) || 372 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) || 373 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) || 374 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns)) 375 return 0; 376 377# ifndef OPENSSL_NO_RSA 378 /* 379 * We know that the "PKCS1_SSLeay()" functions hook properly to the 380 * cswift-specific mod_exp and mod_exp_crt so we use those functions. NB: 381 * We don't use ENGINE_openssl() or anything "more generic" because 382 * something like the RSAref code may not hook properly, and if you own 383 * one of these cards then you have the right to do RSA operations on it 384 * anyway! 385 */ 386 meth1 = RSA_PKCS1_SSLeay(); 387 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc; 388 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec; 389 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc; 390 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec; 391# endif 392 393# ifndef OPENSSL_NO_DH 394 /* Much the same for Diffie-Hellman */ 395 meth2 = DH_OpenSSL(); 396 hwcrhk_dh.generate_key = meth2->generate_key; 397 hwcrhk_dh.compute_key = meth2->compute_key; 398# endif 399 400 /* Ensure the hwcrhk error handling is set up */ 401 ERR_load_HWCRHK_strings(); 402 return 1; 403} 404 405# ifdef OPENSSL_NO_DYNAMIC_ENGINE 406static ENGINE *engine_chil(void) 407{ 408 ENGINE *ret = ENGINE_new(); 409 if (!ret) 410 return NULL; 411 if (!bind_helper(ret)) { 412 ENGINE_free(ret); 413 return NULL; 414 } 415 return ret; 416} 417 418void ENGINE_load_chil(void) 419{ 420 /* Copied from eng_[openssl|dyn].c */ 421 ENGINE *toadd = engine_chil(); 422 if (!toadd) 423 return; 424 ENGINE_add(toadd); 425 ENGINE_free(toadd); 426 ERR_clear_error(); 427} 428# endif 429 430/* 431 * This is a process-global DSO handle used for loading and unloading the 432 * HWCryptoHook library. NB: This is only set (or unset) during an init() or 433 * finish() call (reference counts permitting) and they're operating with 434 * global locks, so this should be thread-safe implicitly. 435 */ 436static DSO *hwcrhk_dso = NULL; 437static HWCryptoHook_ContextHandle hwcrhk_context = 0; 438# ifndef OPENSSL_NO_RSA 439/* Index for KM handle. Not really used yet. */ 440static int hndidx_rsa = -1; 441# endif 442 443/* 444 * These are the function pointers that are (un)set when the library has 445 * successfully (un)loaded. 446 */ 447static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL; 448static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL; 449static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL; 450# ifndef OPENSSL_NO_RSA 451static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL; 452# endif 453static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL; 454# ifndef OPENSSL_NO_RSA 455static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL; 456static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL; 457static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL; 458# endif 459static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL; 460 461/* Used in the DSO operations. */ 462static const char *HWCRHK_LIBNAME = NULL; 463static void free_HWCRHK_LIBNAME(void) 464{ 465 if (HWCRHK_LIBNAME) 466 OPENSSL_free((void *)HWCRHK_LIBNAME); 467 HWCRHK_LIBNAME = NULL; 468} 469 470static const char *get_HWCRHK_LIBNAME(void) 471{ 472 if (HWCRHK_LIBNAME) 473 return HWCRHK_LIBNAME; 474 return "nfhwcrhk"; 475} 476 477static long set_HWCRHK_LIBNAME(const char *name) 478{ 479 free_HWCRHK_LIBNAME(); 480 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0); 481} 482 483static const char *n_hwcrhk_Init = "HWCryptoHook_Init"; 484static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish"; 485static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp"; 486# ifndef OPENSSL_NO_RSA 487static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA"; 488# endif 489static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes"; 490# ifndef OPENSSL_NO_RSA 491static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey"; 492static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey"; 493static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey"; 494# endif 495static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT"; 496 497/* 498 * HWCryptoHook library functions and mechanics - these are used by the 499 * higher-level functions further down. NB: As and where there's no error 500 * checking, take a look lower down where these functions are called, the 501 * checking and error handling is probably down there. 502 */ 503 504/* utility function to obtain a context */ 505static int get_context(HWCryptoHook_ContextHandle * hac, 506 HWCryptoHook_CallerContext * cac) 507{ 508 char tempbuf[1024]; 509 HWCryptoHook_ErrMsgBuf rmsg; 510 511 rmsg.buf = tempbuf; 512 rmsg.size = sizeof(tempbuf); 513 514 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg, cac); 515 if (!*hac) 516 return 0; 517 return 1; 518} 519 520/* similarly to release one. */ 521static void release_context(HWCryptoHook_ContextHandle hac) 522{ 523 p_hwcrhk_Finish(hac); 524} 525 526/* Destructor (complements the "ENGINE_chil()" constructor) */ 527static int hwcrhk_destroy(ENGINE *e) 528{ 529 free_HWCRHK_LIBNAME(); 530 ERR_unload_HWCRHK_strings(); 531 return 1; 532} 533 534/* (de)initialisation functions. */ 535static int hwcrhk_init(ENGINE *e) 536{ 537 HWCryptoHook_Init_t *p1; 538 HWCryptoHook_Finish_t *p2; 539 HWCryptoHook_ModExp_t *p3; 540# ifndef OPENSSL_NO_RSA 541 HWCryptoHook_RSA_t *p4; 542 HWCryptoHook_RSALoadKey_t *p5; 543 HWCryptoHook_RSAGetPublicKey_t *p6; 544 HWCryptoHook_RSAUnloadKey_t *p7; 545# endif 546 HWCryptoHook_RandomBytes_t *p8; 547 HWCryptoHook_ModExpCRT_t *p9; 548 549 if (hwcrhk_dso != NULL) { 550 HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_ALREADY_LOADED); 551 goto err; 552 } 553 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */ 554 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0); 555 if (hwcrhk_dso == NULL) { 556 HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE); 557 goto err; 558 } 559 if (!(p1 = (HWCryptoHook_Init_t *) 560 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) || 561 !(p2 = (HWCryptoHook_Finish_t *) 562 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) || 563 !(p3 = (HWCryptoHook_ModExp_t *) 564 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) || 565# ifndef OPENSSL_NO_RSA 566 !(p4 = (HWCryptoHook_RSA_t *) 567 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) || 568 !(p5 = (HWCryptoHook_RSALoadKey_t *) 569 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) || 570 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *) 571 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) || 572 !(p7 = (HWCryptoHook_RSAUnloadKey_t *) 573 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) || 574# endif 575 !(p8 = (HWCryptoHook_RandomBytes_t *) 576 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) || 577 !(p9 = (HWCryptoHook_ModExpCRT_t *) 578 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT))) { 579 HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE); 580 goto err; 581 } 582 /* Copy the pointers */ 583 p_hwcrhk_Init = p1; 584 p_hwcrhk_Finish = p2; 585 p_hwcrhk_ModExp = p3; 586# ifndef OPENSSL_NO_RSA 587 p_hwcrhk_RSA = p4; 588 p_hwcrhk_RSALoadKey = p5; 589 p_hwcrhk_RSAGetPublicKey = p6; 590 p_hwcrhk_RSAUnloadKey = p7; 591# endif 592 p_hwcrhk_RandomBytes = p8; 593 p_hwcrhk_ModExpCRT = p9; 594 595 /* 596 * Check if the application decided to support dynamic locks, and if it 597 * does, use them. 598 */ 599 if (disable_mutex_callbacks == 0) { 600 if (CRYPTO_get_dynlock_create_callback() != NULL && 601 CRYPTO_get_dynlock_lock_callback() != NULL && 602 CRYPTO_get_dynlock_destroy_callback() != NULL) { 603 hwcrhk_globals.mutex_init = hwcrhk_mutex_init; 604 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock; 605 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock; 606 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy; 607 } 608 } 609 610 /* 611 * Try and get a context - if not, we may have a DSO but no accelerator! 612 */ 613 if (!get_context(&hwcrhk_context, &password_context)) { 614 HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_UNIT_FAILURE); 615 goto err; 616 } 617 /* Everything's fine. */ 618# ifndef OPENSSL_NO_RSA 619 if (hndidx_rsa == -1) 620 hndidx_rsa = RSA_get_ex_new_index(0, 621 "nFast HWCryptoHook RSA key handle", 622 NULL, NULL, NULL); 623# endif 624 return 1; 625 err: 626 if (hwcrhk_dso) 627 DSO_free(hwcrhk_dso); 628 hwcrhk_dso = NULL; 629 p_hwcrhk_Init = NULL; 630 p_hwcrhk_Finish = NULL; 631 p_hwcrhk_ModExp = NULL; 632# ifndef OPENSSL_NO_RSA 633 p_hwcrhk_RSA = NULL; 634 p_hwcrhk_RSALoadKey = NULL; 635 p_hwcrhk_RSAGetPublicKey = NULL; 636 p_hwcrhk_RSAUnloadKey = NULL; 637# endif 638 p_hwcrhk_ModExpCRT = NULL; 639 p_hwcrhk_RandomBytes = NULL; 640 return 0; 641} 642 643static int hwcrhk_finish(ENGINE *e) 644{ 645 int to_return = 1; 646 free_HWCRHK_LIBNAME(); 647 if (hwcrhk_dso == NULL) { 648 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_NOT_LOADED); 649 to_return = 0; 650 goto err; 651 } 652 release_context(hwcrhk_context); 653 if (!DSO_free(hwcrhk_dso)) { 654 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_DSO_FAILURE); 655 to_return = 0; 656 goto err; 657 } 658 err: 659 if (logstream) 660 BIO_free(logstream); 661 hwcrhk_dso = NULL; 662 p_hwcrhk_Init = NULL; 663 p_hwcrhk_Finish = NULL; 664 p_hwcrhk_ModExp = NULL; 665# ifndef OPENSSL_NO_RSA 666 p_hwcrhk_RSA = NULL; 667 p_hwcrhk_RSALoadKey = NULL; 668 p_hwcrhk_RSAGetPublicKey = NULL; 669 p_hwcrhk_RSAUnloadKey = NULL; 670# endif 671 p_hwcrhk_ModExpCRT = NULL; 672 p_hwcrhk_RandomBytes = NULL; 673 return to_return; 674} 675 676static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) 677{ 678 int to_return = 1; 679 680 switch (cmd) { 681 case HWCRHK_CMD_SO_PATH: 682 if (hwcrhk_dso) { 683 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_ALREADY_LOADED); 684 return 0; 685 } 686 if (p == NULL) { 687 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, ERR_R_PASSED_NULL_PARAMETER); 688 return 0; 689 } 690 return set_HWCRHK_LIBNAME((const char *)p); 691 case ENGINE_CTRL_SET_LOGSTREAM: 692 { 693 BIO *bio = (BIO *)p; 694 695 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 696 if (logstream) { 697 BIO_free(logstream); 698 logstream = NULL; 699 } 700 if (CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO) > 1) 701 logstream = bio; 702 else 703 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_BIO_WAS_FREED); 704 } 705 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 706 break; 707 case ENGINE_CTRL_SET_PASSWORD_CALLBACK: 708 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 709 password_context.password_callback = (pem_password_cb *)f; 710 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 711 break; 712 case ENGINE_CTRL_SET_USER_INTERFACE: 713 case HWCRHK_CMD_SET_USER_INTERFACE: 714 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 715 password_context.ui_method = (UI_METHOD *)p; 716 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 717 break; 718 case ENGINE_CTRL_SET_CALLBACK_DATA: 719 case HWCRHK_CMD_SET_CALLBACK_DATA: 720 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 721 password_context.callback_data = p; 722 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 723 break; 724 /* 725 * this enables or disables the "SimpleForkCheck" flag used in the 726 * initialisation structure. 727 */ 728 case ENGINE_CTRL_CHIL_SET_FORKCHECK: 729 case HWCRHK_CMD_FORK_CHECK: 730 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 731 if (i) 732 hwcrhk_globals.flags |= HWCryptoHook_InitFlags_SimpleForkCheck; 733 else 734 hwcrhk_globals.flags &= ~HWCryptoHook_InitFlags_SimpleForkCheck; 735 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 736 break; 737 /* 738 * This will prevent the initialisation function from "installing" 739 * the mutex-handling callbacks, even if they are available from 740 * within the library (or were provided to the library from the 741 * calling application). This is to remove any baggage for 742 * applications not using multithreading. 743 */ 744 case ENGINE_CTRL_CHIL_NO_LOCKING: 745 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 746 disable_mutex_callbacks = 1; 747 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 748 break; 749 case HWCRHK_CMD_THREAD_LOCKING: 750 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 751 disable_mutex_callbacks = ((i == 0) ? 0 : 1); 752 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 753 break; 754 755 /* The command isn't understood by this engine */ 756 default: 757 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, 758 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED); 759 to_return = 0; 760 break; 761 } 762 763 return to_return; 764} 765 766static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id, 767 UI_METHOD *ui_method, 768 void *callback_data) 769{ 770# ifndef OPENSSL_NO_RSA 771 RSA *rtmp = NULL; 772# endif 773 EVP_PKEY *res = NULL; 774# ifndef OPENSSL_NO_RSA 775 HWCryptoHook_MPI e, n; 776 HWCryptoHook_RSAKeyHandle *hptr; 777# endif 778# if !defined(OPENSSL_NO_RSA) 779 char tempbuf[1024]; 780 HWCryptoHook_ErrMsgBuf rmsg; 781 HWCryptoHook_PassphraseContext ppctx; 782# endif 783 784# if !defined(OPENSSL_NO_RSA) 785 rmsg.buf = tempbuf; 786 rmsg.size = sizeof(tempbuf); 787# endif 788 789 if (!hwcrhk_context) { 790 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NOT_INITIALISED); 791 goto err; 792 } 793# ifndef OPENSSL_NO_RSA 794 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle)); 795 if (!hptr) { 796 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE); 797 goto err; 798 } 799 ppctx.ui_method = ui_method; 800 ppctx.callback_data = callback_data; 801 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr, &rmsg, &ppctx)) { 802 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR); 803 ERR_add_error_data(1, rmsg.buf); 804 goto err; 805 } 806 if (!*hptr) { 807 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NO_KEY); 808 goto err; 809 } 810# endif 811# ifndef OPENSSL_NO_RSA 812 rtmp = RSA_new_method(eng); 813 if (rtmp == NULL) { 814 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE); 815 goto err; 816 } 817 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr); 818 rtmp->e = BN_new(); 819 rtmp->n = BN_new(); 820 if (rtmp->e == NULL || rtmp->n == NULL) { 821 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE); 822 goto err; 823 } 824 rtmp->flags |= RSA_FLAG_EXT_PKEY; 825 MPI2BN(rtmp->e, e); 826 MPI2BN(rtmp->n, n); 827 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg) 828 != HWCRYPTOHOOK_ERROR_MPISIZE) { 829 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR); 830 ERR_add_error_data(1, rmsg.buf); 831 goto err; 832 } 833 834 if (bn_expand2(rtmp->e, e.size / sizeof(BN_ULONG)) == NULL) { 835 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE); 836 goto err; 837 } 838 if (bn_expand2(rtmp->n, n.size / sizeof(BN_ULONG)) == NULL) { 839 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE); 840 goto err; 841 } 842 MPI2BN(rtmp->e, e); 843 MPI2BN(rtmp->n, n); 844 845 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)) { 846 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR); 847 ERR_add_error_data(1, rmsg.buf); 848 goto err; 849 } 850 rtmp->e->top = e.size / sizeof(BN_ULONG); 851 bn_fix_top(rtmp->e); 852 rtmp->n->top = n.size / sizeof(BN_ULONG); 853 bn_fix_top(rtmp->n); 854 855 res = EVP_PKEY_new(); 856 if (res == NULL) { 857 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR); 858 goto err; 859 } 860 EVP_PKEY_assign_RSA(res, rtmp); 861# endif 862 863 if (!res) 864 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, 865 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED); 866 867 return res; 868 err: 869# ifndef OPENSSL_NO_RSA 870 if (rtmp) 871 RSA_free(rtmp); 872# endif 873 return NULL; 874} 875 876static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id, 877 UI_METHOD *ui_method, void *callback_data) 878{ 879 EVP_PKEY *res = NULL; 880 881# ifndef OPENSSL_NO_RSA 882 res = hwcrhk_load_privkey(eng, key_id, ui_method, callback_data); 883# endif 884 885 if (res) 886 switch (res->type) { 887# ifndef OPENSSL_NO_RSA 888 case EVP_PKEY_RSA: 889 { 890 RSA *rsa = NULL; 891 892 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); 893 rsa = res->pkey.rsa; 894 res->pkey.rsa = RSA_new(); 895 res->pkey.rsa->n = rsa->n; 896 res->pkey.rsa->e = rsa->e; 897 rsa->n = NULL; 898 rsa->e = NULL; 899 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); 900 RSA_free(rsa); 901 } 902 break; 903# endif 904 default: 905 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY, 906 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED); 907 goto err; 908 } 909 910 return res; 911 err: 912 if (res) 913 EVP_PKEY_free(res); 914 return NULL; 915} 916 917/* A little mod_exp */ 918static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 919 const BIGNUM *m, BN_CTX *ctx) 920{ 921 char tempbuf[1024]; 922 HWCryptoHook_ErrMsgBuf rmsg; 923 /* 924 * Since HWCryptoHook_MPI is pretty compatible with BIGNUM's, we use them 925 * directly, plus a little macro magic. We only thing we need to make 926 * sure of is that enough space is allocated. 927 */ 928 HWCryptoHook_MPI m_a, m_p, m_n, m_r; 929 int to_return, ret; 930 931 to_return = 0; /* expect failure */ 932 rmsg.buf = tempbuf; 933 rmsg.size = sizeof(tempbuf); 934 935 if (!hwcrhk_context) { 936 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_NOT_INITIALISED); 937 goto err; 938 } 939 /* Prepare the params */ 940 if (bn_expand2(r, m->top) == NULL) { /* Check for error !! */ 941 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, ERR_R_MALLOC_FAILURE); 942 goto err; 943 } 944 BN2MPI(m_a, a); 945 BN2MPI(m_p, p); 946 BN2MPI(m_n, m); 947 MPI2BN(r, m_r); 948 949 /* Perform the operation */ 950 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg); 951 952 /* Convert the response */ 953 r->top = m_r.size / sizeof(BN_ULONG); 954 bn_fix_top(r); 955 956 if (ret < 0) { 957 /* 958 * FIXME: When this error is returned, HWCryptoHook is telling us 959 * that falling back to software computation might be a good thing. 960 */ 961 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 962 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FALLBACK); 963 } else { 964 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FAILED); 965 } 966 ERR_add_error_data(1, rmsg.buf); 967 goto err; 968 } 969 970 to_return = 1; 971 err: 972 return to_return; 973} 974 975# ifndef OPENSSL_NO_RSA 976static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, 977 BN_CTX *ctx) 978{ 979 char tempbuf[1024]; 980 HWCryptoHook_ErrMsgBuf rmsg; 981 HWCryptoHook_RSAKeyHandle *hptr; 982 int to_return = 0, ret; 983 984 rmsg.buf = tempbuf; 985 rmsg.size = sizeof(tempbuf); 986 987 if (!hwcrhk_context) { 988 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, HWCRHK_R_NOT_INITIALISED); 989 goto err; 990 } 991 992 /* 993 * This provides support for nForce keys. Since that's opaque data all 994 * we do is provide a handle to the proper key and let HWCryptoHook take 995 * care of the rest. 996 */ 997 if ((hptr = 998 (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa)) 999 != NULL) { 1000 HWCryptoHook_MPI m_a, m_r; 1001 1002 if (!rsa->n) { 1003 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1004 HWCRHK_R_MISSING_KEY_COMPONENTS); 1005 goto err; 1006 } 1007 1008 /* Prepare the params */ 1009 if (bn_expand2(r, rsa->n->top) == NULL) { /* Check for error !! */ 1010 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, ERR_R_MALLOC_FAILURE); 1011 goto err; 1012 } 1013 BN2MPI(m_a, I); 1014 MPI2BN(r, m_r); 1015 1016 /* Perform the operation */ 1017 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg); 1018 1019 /* Convert the response */ 1020 r->top = m_r.size / sizeof(BN_ULONG); 1021 bn_fix_top(r); 1022 1023 if (ret < 0) { 1024 /* 1025 * FIXME: When this error is returned, HWCryptoHook is telling us 1026 * that falling back to software computation might be a good 1027 * thing. 1028 */ 1029 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 1030 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1031 HWCRHK_R_REQUEST_FALLBACK); 1032 } else { 1033 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1034 HWCRHK_R_REQUEST_FAILED); 1035 } 1036 ERR_add_error_data(1, rmsg.buf); 1037 goto err; 1038 } 1039 } else { 1040 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r; 1041 1042 if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) { 1043 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1044 HWCRHK_R_MISSING_KEY_COMPONENTS); 1045 goto err; 1046 } 1047 1048 /* Prepare the params */ 1049 if (bn_expand2(r, rsa->n->top) == NULL) { /* Check for error !! */ 1050 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, ERR_R_MALLOC_FAILURE); 1051 goto err; 1052 } 1053 BN2MPI(m_a, I); 1054 BN2MPI(m_p, rsa->p); 1055 BN2MPI(m_q, rsa->q); 1056 BN2MPI(m_dmp1, rsa->dmp1); 1057 BN2MPI(m_dmq1, rsa->dmq1); 1058 BN2MPI(m_iqmp, rsa->iqmp); 1059 MPI2BN(r, m_r); 1060 1061 /* Perform the operation */ 1062 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q, 1063 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg); 1064 1065 /* Convert the response */ 1066 r->top = m_r.size / sizeof(BN_ULONG); 1067 bn_fix_top(r); 1068 1069 if (ret < 0) { 1070 /* 1071 * FIXME: When this error is returned, HWCryptoHook is telling us 1072 * that falling back to software computation might be a good 1073 * thing. 1074 */ 1075 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 1076 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1077 HWCRHK_R_REQUEST_FALLBACK); 1078 } else { 1079 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1080 HWCRHK_R_REQUEST_FAILED); 1081 } 1082 ERR_add_error_data(1, rmsg.buf); 1083 goto err; 1084 } 1085 } 1086 /* 1087 * If we're here, we must be here with some semblance of success :-) 1088 */ 1089 to_return = 1; 1090 err: 1091 return to_return; 1092} 1093# endif 1094 1095# ifndef OPENSSL_NO_RSA 1096/* This function is aliased to mod_exp (with the mont stuff dropped). */ 1097static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 1098 const BIGNUM *m, BN_CTX *ctx, 1099 BN_MONT_CTX *m_ctx) 1100{ 1101 return hwcrhk_mod_exp(r, a, p, m, ctx); 1102} 1103 1104static int hwcrhk_rsa_finish(RSA *rsa) 1105{ 1106 HWCryptoHook_RSAKeyHandle *hptr; 1107 1108 hptr = RSA_get_ex_data(rsa, hndidx_rsa); 1109 if (hptr) { 1110 p_hwcrhk_RSAUnloadKey(*hptr, NULL); 1111 OPENSSL_free(hptr); 1112 RSA_set_ex_data(rsa, hndidx_rsa, NULL); 1113 } 1114 return 1; 1115} 1116 1117# endif 1118 1119# ifndef OPENSSL_NO_DH 1120/* This function is aliased to mod_exp (with the dh and mont dropped). */ 1121static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r, 1122 const BIGNUM *a, const BIGNUM *p, 1123 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) 1124{ 1125 return hwcrhk_mod_exp(r, a, p, m, ctx); 1126} 1127# endif 1128 1129/* Random bytes are good */ 1130static int hwcrhk_rand_bytes(unsigned char *buf, int num) 1131{ 1132 char tempbuf[1024]; 1133 HWCryptoHook_ErrMsgBuf rmsg; 1134 int to_return = 0; /* assume failure */ 1135 int ret; 1136 1137 rmsg.buf = tempbuf; 1138 rmsg.size = sizeof(tempbuf); 1139 1140 if (!hwcrhk_context) { 1141 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_NOT_INITIALISED); 1142 goto err; 1143 } 1144 1145 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg); 1146 if (ret < 0) { 1147 /* 1148 * FIXME: When this error is returned, HWCryptoHook is telling us 1149 * that falling back to software computation might be a good thing. 1150 */ 1151 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 1152 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FALLBACK); 1153 } else { 1154 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FAILED); 1155 } 1156 ERR_add_error_data(1, rmsg.buf); 1157 goto err; 1158 } 1159 to_return = 1; 1160 err: 1161 return to_return; 1162} 1163 1164static int hwcrhk_rand_status(void) 1165{ 1166 return 1; 1167} 1168 1169/* 1170 * Mutex calls: since the HWCryptoHook model closely follows the POSIX model 1171 * these just wrap the POSIX functions and add some logging. 1172 */ 1173 1174static int hwcrhk_mutex_init(HWCryptoHook_Mutex * mt, 1175 HWCryptoHook_CallerContext * cactx) 1176{ 1177 mt->lockid = CRYPTO_get_new_dynlockid(); 1178 if (mt->lockid == 0) 1179 return 1; /* failure */ 1180 return 0; /* success */ 1181} 1182 1183static int hwcrhk_mutex_lock(HWCryptoHook_Mutex * mt) 1184{ 1185 CRYPTO_w_lock(mt->lockid); 1186 return 0; 1187} 1188 1189static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt) 1190{ 1191 CRYPTO_w_unlock(mt->lockid); 1192} 1193 1194static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex * mt) 1195{ 1196 CRYPTO_destroy_dynlockid(mt->lockid); 1197} 1198 1199static int hwcrhk_get_pass(const char *prompt_info, 1200 int *len_io, char *buf, 1201 HWCryptoHook_PassphraseContext * ppctx, 1202 HWCryptoHook_CallerContext * cactx) 1203{ 1204 pem_password_cb *callback = NULL; 1205 void *callback_data = NULL; 1206 UI_METHOD *ui_method = NULL; 1207 /* 1208 * Despite what the documentation says prompt_info can be an empty 1209 * string. 1210 */ 1211 if (prompt_info && !*prompt_info) 1212 prompt_info = NULL; 1213 1214 if (cactx) { 1215 if (cactx->ui_method) 1216 ui_method = cactx->ui_method; 1217 if (cactx->password_callback) 1218 callback = cactx->password_callback; 1219 if (cactx->callback_data) 1220 callback_data = cactx->callback_data; 1221 } 1222 if (ppctx) { 1223 if (ppctx->ui_method) { 1224 ui_method = ppctx->ui_method; 1225 callback = NULL; 1226 } 1227 if (ppctx->callback_data) 1228 callback_data = ppctx->callback_data; 1229 } 1230 if (callback == NULL && ui_method == NULL) { 1231 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS, HWCRHK_R_NO_CALLBACK); 1232 return -1; 1233 } 1234 1235 if (ui_method) { 1236 UI *ui = UI_new_method(ui_method); 1237 if (ui) { 1238 int ok; 1239 char *prompt = UI_construct_prompt(ui, 1240 "pass phrase", prompt_info); 1241 1242 ok = UI_add_input_string(ui, prompt, 1243 UI_INPUT_FLAG_DEFAULT_PWD, 1244 buf, 0, (*len_io) - 1); 1245 UI_add_user_data(ui, callback_data); 1246 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); 1247 1248 if (ok >= 0) 1249 do { 1250 ok = UI_process(ui); 1251 } 1252 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); 1253 1254 if (ok >= 0) 1255 *len_io = strlen(buf); 1256 1257 UI_free(ui); 1258 OPENSSL_free(prompt); 1259 } 1260 } else { 1261 *len_io = callback(buf, *len_io, 0, callback_data); 1262 } 1263 if (!*len_io) 1264 return -1; 1265 return 0; 1266} 1267 1268static int hwcrhk_insert_card(const char *prompt_info, 1269 const char *wrong_info, 1270 HWCryptoHook_PassphraseContext * ppctx, 1271 HWCryptoHook_CallerContext * cactx) 1272{ 1273 int ok = -1; 1274 UI *ui; 1275 void *callback_data = NULL; 1276 UI_METHOD *ui_method = NULL; 1277 1278 if (cactx) { 1279 if (cactx->ui_method) 1280 ui_method = cactx->ui_method; 1281 if (cactx->callback_data) 1282 callback_data = cactx->callback_data; 1283 } 1284 if (ppctx) { 1285 if (ppctx->ui_method) 1286 ui_method = ppctx->ui_method; 1287 if (ppctx->callback_data) 1288 callback_data = ppctx->callback_data; 1289 } 1290 if (ui_method == NULL) { 1291 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD, HWCRHK_R_NO_CALLBACK); 1292 return -1; 1293 } 1294 1295 ui = UI_new_method(ui_method); 1296 1297 if (ui) { 1298 char answer = '\0'; 1299 char buf[BUFSIZ]; 1300 /* 1301 * Despite what the documentation says wrong_info can be an empty 1302 * string. 1303 */ 1304 if (wrong_info && *wrong_info) 1305 BIO_snprintf(buf, sizeof(buf) - 1, 1306 "Current card: \"%s\"\n", wrong_info); 1307 else 1308 buf[0] = 0; 1309 ok = UI_dup_info_string(ui, buf); 1310 if (ok >= 0 && prompt_info) { 1311 BIO_snprintf(buf, sizeof(buf) - 1, 1312 "Insert card \"%s\"", prompt_info); 1313 ok = UI_dup_input_boolean(ui, buf, 1314 "\n then hit <enter> or C<enter> to cancel\n", 1315 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, 1316 &answer); 1317 } 1318 UI_add_user_data(ui, callback_data); 1319 1320 if (ok >= 0) 1321 ok = UI_process(ui); 1322 UI_free(ui); 1323 1324 if (ok == -2 || (ok >= 0 && answer == 'C')) 1325 ok = 1; 1326 else if (ok < 0) 1327 ok = -1; 1328 else 1329 ok = 0; 1330 } 1331 return ok; 1332} 1333 1334static void hwcrhk_log_message(void *logstr, const char *message) 1335{ 1336 BIO *lstream = NULL; 1337 1338 CRYPTO_w_lock(CRYPTO_LOCK_BIO); 1339 if (logstr) 1340 lstream = *(BIO **)logstr; 1341 if (lstream) { 1342 BIO_printf(lstream, "%s\n", message); 1343 } 1344 CRYPTO_w_unlock(CRYPTO_LOCK_BIO); 1345} 1346 1347/* 1348 * This stuff is needed if this ENGINE is being compiled into a 1349 * self-contained shared-library. 1350 */ 1351# ifndef OPENSSL_NO_DYNAMIC_ENGINE 1352static int bind_fn(ENGINE *e, const char *id) 1353{ 1354 if (id && (strcmp(id, engine_hwcrhk_id) != 0) && 1355 (strcmp(id, engine_hwcrhk_id_alt) != 0)) 1356 return 0; 1357 if (!bind_helper(e)) 1358 return 0; 1359 return 1; 1360} 1361 1362IMPLEMENT_DYNAMIC_CHECK_FN() 1363 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) 1364# endif /* OPENSSL_NO_DYNAMIC_ENGINE */ 1365# endif /* !OPENSSL_NO_HW_CHIL */ 1366#endif /* !OPENSSL_NO_HW */ 1367