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