1/* crypto/engine/e_chil.c -*- mode: C; c-file-style: "eay" -*- */ 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 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr); 814 rtmp->e = BN_new(); 815 rtmp->n = BN_new(); 816 rtmp->flags |= RSA_FLAG_EXT_PKEY; 817 MPI2BN(rtmp->e, e); 818 MPI2BN(rtmp->n, n); 819 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg) 820 != HWCRYPTOHOOK_ERROR_MPISIZE) { 821 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR); 822 ERR_add_error_data(1, rmsg.buf); 823 goto err; 824 } 825 826 bn_expand2(rtmp->e, e.size / sizeof(BN_ULONG)); 827 bn_expand2(rtmp->n, n.size / sizeof(BN_ULONG)); 828 MPI2BN(rtmp->e, e); 829 MPI2BN(rtmp->n, n); 830 831 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)) { 832 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR); 833 ERR_add_error_data(1, rmsg.buf); 834 goto err; 835 } 836 rtmp->e->top = e.size / sizeof(BN_ULONG); 837 bn_fix_top(rtmp->e); 838 rtmp->n->top = n.size / sizeof(BN_ULONG); 839 bn_fix_top(rtmp->n); 840 841 res = EVP_PKEY_new(); 842 EVP_PKEY_assign_RSA(res, rtmp); 843# endif 844 845 if (!res) 846 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, 847 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED); 848 849 return res; 850 err: 851# ifndef OPENSSL_NO_RSA 852 if (rtmp) 853 RSA_free(rtmp); 854# endif 855 return NULL; 856} 857 858static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id, 859 UI_METHOD *ui_method, void *callback_data) 860{ 861 EVP_PKEY *res = NULL; 862 863# ifndef OPENSSL_NO_RSA 864 res = hwcrhk_load_privkey(eng, key_id, ui_method, callback_data); 865# endif 866 867 if (res) 868 switch (res->type) { 869# ifndef OPENSSL_NO_RSA 870 case EVP_PKEY_RSA: 871 { 872 RSA *rsa = NULL; 873 874 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); 875 rsa = res->pkey.rsa; 876 res->pkey.rsa = RSA_new(); 877 res->pkey.rsa->n = rsa->n; 878 res->pkey.rsa->e = rsa->e; 879 rsa->n = NULL; 880 rsa->e = NULL; 881 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); 882 RSA_free(rsa); 883 } 884 break; 885# endif 886 default: 887 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY, 888 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED); 889 goto err; 890 } 891 892 return res; 893 err: 894 if (res) 895 EVP_PKEY_free(res); 896 return NULL; 897} 898 899/* A little mod_exp */ 900static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 901 const BIGNUM *m, BN_CTX *ctx) 902{ 903 char tempbuf[1024]; 904 HWCryptoHook_ErrMsgBuf rmsg; 905 /* 906 * Since HWCryptoHook_MPI is pretty compatible with BIGNUM's, we use them 907 * directly, plus a little macro magic. We only thing we need to make 908 * sure of is that enough space is allocated. 909 */ 910 HWCryptoHook_MPI m_a, m_p, m_n, m_r; 911 int to_return, ret; 912 913 to_return = 0; /* expect failure */ 914 rmsg.buf = tempbuf; 915 rmsg.size = sizeof(tempbuf); 916 917 if (!hwcrhk_context) { 918 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_NOT_INITIALISED); 919 goto err; 920 } 921 /* Prepare the params */ 922 bn_expand2(r, m->top); /* Check for error !! */ 923 BN2MPI(m_a, a); 924 BN2MPI(m_p, p); 925 BN2MPI(m_n, m); 926 MPI2BN(r, m_r); 927 928 /* Perform the operation */ 929 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg); 930 931 /* Convert the response */ 932 r->top = m_r.size / sizeof(BN_ULONG); 933 bn_fix_top(r); 934 935 if (ret < 0) { 936 /* 937 * FIXME: When this error is returned, HWCryptoHook is telling us 938 * that falling back to software computation might be a good thing. 939 */ 940 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 941 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FALLBACK); 942 } else { 943 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FAILED); 944 } 945 ERR_add_error_data(1, rmsg.buf); 946 goto err; 947 } 948 949 to_return = 1; 950 err: 951 return to_return; 952} 953 954# ifndef OPENSSL_NO_RSA 955static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, 956 BN_CTX *ctx) 957{ 958 char tempbuf[1024]; 959 HWCryptoHook_ErrMsgBuf rmsg; 960 HWCryptoHook_RSAKeyHandle *hptr; 961 int to_return = 0, ret; 962 963 rmsg.buf = tempbuf; 964 rmsg.size = sizeof(tempbuf); 965 966 if (!hwcrhk_context) { 967 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, HWCRHK_R_NOT_INITIALISED); 968 goto err; 969 } 970 971 /* 972 * This provides support for nForce keys. Since that's opaque data all 973 * we do is provide a handle to the proper key and let HWCryptoHook take 974 * care of the rest. 975 */ 976 if ((hptr = 977 (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa)) 978 != NULL) { 979 HWCryptoHook_MPI m_a, m_r; 980 981 if (!rsa->n) { 982 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 983 HWCRHK_R_MISSING_KEY_COMPONENTS); 984 goto err; 985 } 986 987 /* Prepare the params */ 988 bn_expand2(r, rsa->n->top); /* Check for error !! */ 989 BN2MPI(m_a, I); 990 MPI2BN(r, m_r); 991 992 /* Perform the operation */ 993 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg); 994 995 /* Convert the response */ 996 r->top = m_r.size / sizeof(BN_ULONG); 997 bn_fix_top(r); 998 999 if (ret < 0) { 1000 /* 1001 * FIXME: When this error is returned, HWCryptoHook is telling us 1002 * that falling back to software computation might be a good 1003 * thing. 1004 */ 1005 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 1006 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1007 HWCRHK_R_REQUEST_FALLBACK); 1008 } else { 1009 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1010 HWCRHK_R_REQUEST_FAILED); 1011 } 1012 ERR_add_error_data(1, rmsg.buf); 1013 goto err; 1014 } 1015 } else { 1016 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r; 1017 1018 if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) { 1019 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1020 HWCRHK_R_MISSING_KEY_COMPONENTS); 1021 goto err; 1022 } 1023 1024 /* Prepare the params */ 1025 bn_expand2(r, rsa->n->top); /* Check for error !! */ 1026 BN2MPI(m_a, I); 1027 BN2MPI(m_p, rsa->p); 1028 BN2MPI(m_q, rsa->q); 1029 BN2MPI(m_dmp1, rsa->dmp1); 1030 BN2MPI(m_dmq1, rsa->dmq1); 1031 BN2MPI(m_iqmp, rsa->iqmp); 1032 MPI2BN(r, m_r); 1033 1034 /* Perform the operation */ 1035 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q, 1036 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg); 1037 1038 /* Convert the response */ 1039 r->top = m_r.size / sizeof(BN_ULONG); 1040 bn_fix_top(r); 1041 1042 if (ret < 0) { 1043 /* 1044 * FIXME: When this error is returned, HWCryptoHook is telling us 1045 * that falling back to software computation might be a good 1046 * thing. 1047 */ 1048 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 1049 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1050 HWCRHK_R_REQUEST_FALLBACK); 1051 } else { 1052 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1053 HWCRHK_R_REQUEST_FAILED); 1054 } 1055 ERR_add_error_data(1, rmsg.buf); 1056 goto err; 1057 } 1058 } 1059 /* 1060 * If we're here, we must be here with some semblance of success :-) 1061 */ 1062 to_return = 1; 1063 err: 1064 return to_return; 1065} 1066# endif 1067 1068# ifndef OPENSSL_NO_RSA 1069/* This function is aliased to mod_exp (with the mont stuff dropped). */ 1070static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 1071 const BIGNUM *m, BN_CTX *ctx, 1072 BN_MONT_CTX *m_ctx) 1073{ 1074 return hwcrhk_mod_exp(r, a, p, m, ctx); 1075} 1076 1077static int hwcrhk_rsa_finish(RSA *rsa) 1078{ 1079 HWCryptoHook_RSAKeyHandle *hptr; 1080 1081 hptr = RSA_get_ex_data(rsa, hndidx_rsa); 1082 if (hptr) { 1083 p_hwcrhk_RSAUnloadKey(*hptr, NULL); 1084 OPENSSL_free(hptr); 1085 RSA_set_ex_data(rsa, hndidx_rsa, NULL); 1086 } 1087 return 1; 1088} 1089 1090# endif 1091 1092# ifndef OPENSSL_NO_DH 1093/* This function is aliased to mod_exp (with the dh and mont dropped). */ 1094static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r, 1095 const BIGNUM *a, const BIGNUM *p, 1096 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) 1097{ 1098 return hwcrhk_mod_exp(r, a, p, m, ctx); 1099} 1100# endif 1101 1102/* Random bytes are good */ 1103static int hwcrhk_rand_bytes(unsigned char *buf, int num) 1104{ 1105 char tempbuf[1024]; 1106 HWCryptoHook_ErrMsgBuf rmsg; 1107 int to_return = 0; /* assume failure */ 1108 int ret; 1109 1110 rmsg.buf = tempbuf; 1111 rmsg.size = sizeof(tempbuf); 1112 1113 if (!hwcrhk_context) { 1114 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_NOT_INITIALISED); 1115 goto err; 1116 } 1117 1118 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg); 1119 if (ret < 0) { 1120 /* 1121 * FIXME: When this error is returned, HWCryptoHook is telling us 1122 * that falling back to software computation might be a good thing. 1123 */ 1124 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 1125 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FALLBACK); 1126 } else { 1127 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FAILED); 1128 } 1129 ERR_add_error_data(1, rmsg.buf); 1130 goto err; 1131 } 1132 to_return = 1; 1133 err: 1134 return to_return; 1135} 1136 1137static int hwcrhk_rand_status(void) 1138{ 1139 return 1; 1140} 1141 1142/* 1143 * Mutex calls: since the HWCryptoHook model closely follows the POSIX model 1144 * these just wrap the POSIX functions and add some logging. 1145 */ 1146 1147static int hwcrhk_mutex_init(HWCryptoHook_Mutex * mt, 1148 HWCryptoHook_CallerContext * cactx) 1149{ 1150 mt->lockid = CRYPTO_get_new_dynlockid(); 1151 if (mt->lockid == 0) 1152 return 1; /* failure */ 1153 return 0; /* success */ 1154} 1155 1156static int hwcrhk_mutex_lock(HWCryptoHook_Mutex * mt) 1157{ 1158 CRYPTO_w_lock(mt->lockid); 1159 return 0; 1160} 1161 1162static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt) 1163{ 1164 CRYPTO_w_unlock(mt->lockid); 1165} 1166 1167static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex * mt) 1168{ 1169 CRYPTO_destroy_dynlockid(mt->lockid); 1170} 1171 1172static int hwcrhk_get_pass(const char *prompt_info, 1173 int *len_io, char *buf, 1174 HWCryptoHook_PassphraseContext * ppctx, 1175 HWCryptoHook_CallerContext * cactx) 1176{ 1177 pem_password_cb *callback = NULL; 1178 void *callback_data = NULL; 1179 UI_METHOD *ui_method = NULL; 1180 /* 1181 * Despite what the documentation says prompt_info can be an empty 1182 * string. 1183 */ 1184 if (prompt_info && !*prompt_info) 1185 prompt_info = NULL; 1186 1187 if (cactx) { 1188 if (cactx->ui_method) 1189 ui_method = cactx->ui_method; 1190 if (cactx->password_callback) 1191 callback = cactx->password_callback; 1192 if (cactx->callback_data) 1193 callback_data = cactx->callback_data; 1194 } 1195 if (ppctx) { 1196 if (ppctx->ui_method) { 1197 ui_method = ppctx->ui_method; 1198 callback = NULL; 1199 } 1200 if (ppctx->callback_data) 1201 callback_data = ppctx->callback_data; 1202 } 1203 if (callback == NULL && ui_method == NULL) { 1204 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS, HWCRHK_R_NO_CALLBACK); 1205 return -1; 1206 } 1207 1208 if (ui_method) { 1209 UI *ui = UI_new_method(ui_method); 1210 if (ui) { 1211 int ok; 1212 char *prompt = UI_construct_prompt(ui, 1213 "pass phrase", prompt_info); 1214 1215 ok = UI_add_input_string(ui, prompt, 1216 UI_INPUT_FLAG_DEFAULT_PWD, 1217 buf, 0, (*len_io) - 1); 1218 UI_add_user_data(ui, callback_data); 1219 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); 1220 1221 if (ok >= 0) 1222 do { 1223 ok = UI_process(ui); 1224 } 1225 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); 1226 1227 if (ok >= 0) 1228 *len_io = strlen(buf); 1229 1230 UI_free(ui); 1231 OPENSSL_free(prompt); 1232 } 1233 } else { 1234 *len_io = callback(buf, *len_io, 0, callback_data); 1235 } 1236 if (!*len_io) 1237 return -1; 1238 return 0; 1239} 1240 1241static int hwcrhk_insert_card(const char *prompt_info, 1242 const char *wrong_info, 1243 HWCryptoHook_PassphraseContext * ppctx, 1244 HWCryptoHook_CallerContext * cactx) 1245{ 1246 int ok = -1; 1247 UI *ui; 1248 void *callback_data = NULL; 1249 UI_METHOD *ui_method = NULL; 1250 1251 if (cactx) { 1252 if (cactx->ui_method) 1253 ui_method = cactx->ui_method; 1254 if (cactx->callback_data) 1255 callback_data = cactx->callback_data; 1256 } 1257 if (ppctx) { 1258 if (ppctx->ui_method) 1259 ui_method = ppctx->ui_method; 1260 if (ppctx->callback_data) 1261 callback_data = ppctx->callback_data; 1262 } 1263 if (ui_method == NULL) { 1264 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD, HWCRHK_R_NO_CALLBACK); 1265 return -1; 1266 } 1267 1268 ui = UI_new_method(ui_method); 1269 1270 if (ui) { 1271 char answer; 1272 char buf[BUFSIZ]; 1273 /* 1274 * Despite what the documentation says wrong_info can be an empty 1275 * string. 1276 */ 1277 if (wrong_info && *wrong_info) 1278 BIO_snprintf(buf, sizeof(buf) - 1, 1279 "Current card: \"%s\"\n", wrong_info); 1280 else 1281 buf[0] = 0; 1282 ok = UI_dup_info_string(ui, buf); 1283 if (ok >= 0 && prompt_info) { 1284 BIO_snprintf(buf, sizeof(buf) - 1, 1285 "Insert card \"%s\"", prompt_info); 1286 ok = UI_dup_input_boolean(ui, buf, 1287 "\n then hit <enter> or C<enter> to cancel\n", 1288 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, 1289 &answer); 1290 } 1291 UI_add_user_data(ui, callback_data); 1292 1293 if (ok >= 0) 1294 ok = UI_process(ui); 1295 UI_free(ui); 1296 1297 if (ok == -2 || (ok >= 0 && answer == 'C')) 1298 ok = 1; 1299 else if (ok < 0) 1300 ok = -1; 1301 else 1302 ok = 0; 1303 } 1304 return ok; 1305} 1306 1307static void hwcrhk_log_message(void *logstr, const char *message) 1308{ 1309 BIO *lstream = NULL; 1310 1311 CRYPTO_w_lock(CRYPTO_LOCK_BIO); 1312 if (logstr) 1313 lstream = *(BIO **)logstr; 1314 if (lstream) { 1315 BIO_printf(lstream, "%s\n", message); 1316 } 1317 CRYPTO_w_unlock(CRYPTO_LOCK_BIO); 1318} 1319 1320/* 1321 * This stuff is needed if this ENGINE is being compiled into a 1322 * self-contained shared-library. 1323 */ 1324# ifndef OPENSSL_NO_DYNAMIC_ENGINE 1325static int bind_fn(ENGINE *e, const char *id) 1326{ 1327 if (id && (strcmp(id, engine_hwcrhk_id) != 0) && 1328 (strcmp(id, engine_hwcrhk_id_alt) != 0)) 1329 return 0; 1330 if (!bind_helper(e)) 1331 return 0; 1332 return 1; 1333} 1334 1335IMPLEMENT_DYNAMIC_CHECK_FN() 1336 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) 1337# endif /* OPENSSL_NO_DYNAMIC_ENGINE */ 1338# endif /* !OPENSSL_NO_HW_CHIL */ 1339#endif /* !OPENSSL_NO_HW */ 1340