e_chil.c revision 296465
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 236# ifndef OPENSSL_NO_DYNAMIC_ENGINE 237/* Compatibility hack, the dynamic library uses this form in the path */ 238static const char *engine_hwcrhk_id_alt = "ncipher"; 239# endif 240 241/* Internal stuff for HWCryptoHook */ 242 243/* Some structures needed for proper use of thread locks */ 244/* 245 * hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue 246 * into HWCryptoHook_Mutex 247 */ 248struct HWCryptoHook_MutexValue { 249 int lockid; 250}; 251 252/* 253 * hwcryptohook.h has some typedefs that turn struct 254 * HWCryptoHook_PassphraseContextValue into HWCryptoHook_PassphraseContext 255 */ 256struct HWCryptoHook_PassphraseContextValue { 257 UI_METHOD *ui_method; 258 void *callback_data; 259}; 260 261/* 262 * hwcryptohook.h has some typedefs that turn struct 263 * HWCryptoHook_CallerContextValue into HWCryptoHook_CallerContext 264 */ 265struct HWCryptoHook_CallerContextValue { 266 pem_password_cb *password_callback; /* Deprecated! Only present for 267 * backward compatibility! */ 268 UI_METHOD *ui_method; 269 void *callback_data; 270}; 271 272/* 273 * The MPI structure in HWCryptoHook is pretty compatible with OpenSSL 274 * BIGNUM's, so lets define a couple of conversion macros 275 */ 276# define BN2MPI(mp, bn) \ 277 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;} 278# define MPI2BN(bn, mp) \ 279 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;} 280 281static BIO *logstream = NULL; 282static int disable_mutex_callbacks = 0; 283 284/* 285 * One might wonder why these are needed, since one can pass down at least a 286 * UI_METHOD and a pointer to callback data to the key-loading functions. The 287 * thing is that the ModExp and RSAImmed functions can load keys as well, if 288 * the data they get is in a special, nCipher-defined format (hint: if you 289 * look at the private exponent of the RSA data as a string, you'll see this 290 * string: "nCipher KM tool key id", followed by some bytes, followed a key 291 * identity string, followed by more bytes. This happens when you use 292 * "embed" keys instead of "hwcrhk" keys). Unfortunately, those functions do 293 * not take any passphrase or caller context, and our functions can't really 294 * take any callback data either. Still, the "insert_card" and 295 * "get_passphrase" callbacks may be called down the line, and will need to 296 * know what user interface callbacks to call, and having callback data from 297 * the application may be a nice thing as well, so we need to keep track of 298 * that globally. 299 */ 300static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL }; 301 302/* Stuff to pass to the HWCryptoHook library */ 303static HWCryptoHook_InitInfo hwcrhk_globals = { 304 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */ 305 &logstream, /* logstream */ 306 sizeof(BN_ULONG), /* limbsize */ 307 0, /* mslimb first: false for BNs */ 308 -1, /* msbyte first: use native */ 309 0, /* Max mutexes, 0 = no small limit */ 310 0, /* Max simultaneous, 0 = default */ 311 312 /* 313 * The next few are mutex stuff: we write wrapper functions around the OS 314 * mutex functions. We initialise them to 0 here, and change that to 315 * actual function pointers in hwcrhk_init() if dynamic locks are 316 * supported (that is, if the application programmer has made sure of 317 * setting up callbacks bafore starting this engine) *and* if 318 * disable_mutex_callbacks hasn't been set by a call to 319 * ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). 320 */ 321 sizeof(HWCryptoHook_Mutex), 322 0, 323 0, 324 0, 325 0, 326 327 /* 328 * The next few are condvar stuff: we write wrapper functions round the 329 * OS functions. Currently not implemented and not and absolute 330 * necessity even in threaded programs, therefore 0'ed. Will hopefully 331 * be implemented some day, since it enhances the efficiency of 332 * HWCryptoHook. 333 */ 334 0, /* sizeof(HWCryptoHook_CondVar), */ 335 0, /* hwcrhk_cv_init, */ 336 0, /* hwcrhk_cv_wait, */ 337 0, /* hwcrhk_cv_signal, */ 338 0, /* hwcrhk_cv_broadcast, */ 339 0, /* hwcrhk_cv_destroy, */ 340 341 hwcrhk_get_pass, /* pass phrase */ 342 hwcrhk_insert_card, /* insert a card */ 343 hwcrhk_log_message /* Log message */ 344}; 345 346/* Now, to our own code */ 347 348/* 349 * This internal function is used by ENGINE_chil() and possibly by the 350 * "dynamic" ENGINE support too 351 */ 352static int bind_helper(ENGINE *e) 353{ 354# ifndef OPENSSL_NO_RSA 355 const RSA_METHOD *meth1; 356# endif 357# ifndef OPENSSL_NO_DH 358 const DH_METHOD *meth2; 359# endif 360 if (!ENGINE_set_id(e, engine_hwcrhk_id) || 361 !ENGINE_set_name(e, engine_hwcrhk_name) || 362# ifndef OPENSSL_NO_RSA 363 !ENGINE_set_RSA(e, &hwcrhk_rsa) || 364# endif 365# ifndef OPENSSL_NO_DH 366 !ENGINE_set_DH(e, &hwcrhk_dh) || 367# endif 368 !ENGINE_set_RAND(e, &hwcrhk_rand) || 369 !ENGINE_set_destroy_function(e, hwcrhk_destroy) || 370 !ENGINE_set_init_function(e, hwcrhk_init) || 371 !ENGINE_set_finish_function(e, hwcrhk_finish) || 372 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) || 373 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) || 374 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) || 375 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns)) 376 return 0; 377 378# ifndef OPENSSL_NO_RSA 379 /* 380 * We know that the "PKCS1_SSLeay()" functions hook properly to the 381 * cswift-specific mod_exp and mod_exp_crt so we use those functions. NB: 382 * We don't use ENGINE_openssl() or anything "more generic" because 383 * something like the RSAref code may not hook properly, and if you own 384 * one of these cards then you have the right to do RSA operations on it 385 * anyway! 386 */ 387 meth1 = RSA_PKCS1_SSLeay(); 388 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc; 389 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec; 390 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc; 391 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec; 392# endif 393 394# ifndef OPENSSL_NO_DH 395 /* Much the same for Diffie-Hellman */ 396 meth2 = DH_OpenSSL(); 397 hwcrhk_dh.generate_key = meth2->generate_key; 398 hwcrhk_dh.compute_key = meth2->compute_key; 399# endif 400 401 /* Ensure the hwcrhk error handling is set up */ 402 ERR_load_HWCRHK_strings(); 403 return 1; 404} 405 406# ifdef OPENSSL_NO_DYNAMIC_ENGINE 407static ENGINE *engine_chil(void) 408{ 409 ENGINE *ret = ENGINE_new(); 410 if (!ret) 411 return NULL; 412 if (!bind_helper(ret)) { 413 ENGINE_free(ret); 414 return NULL; 415 } 416 return ret; 417} 418 419void ENGINE_load_chil(void) 420{ 421 /* Copied from eng_[openssl|dyn].c */ 422 ENGINE *toadd = engine_chil(); 423 if (!toadd) 424 return; 425 ENGINE_add(toadd); 426 ENGINE_free(toadd); 427 ERR_clear_error(); 428} 429# endif 430 431/* 432 * This is a process-global DSO handle used for loading and unloading the 433 * HWCryptoHook library. NB: This is only set (or unset) during an init() or 434 * finish() call (reference counts permitting) and they're operating with 435 * global locks, so this should be thread-safe implicitly. 436 */ 437static DSO *hwcrhk_dso = NULL; 438static HWCryptoHook_ContextHandle hwcrhk_context = 0; 439# ifndef OPENSSL_NO_RSA 440/* Index for KM handle. Not really used yet. */ 441static int hndidx_rsa = -1; 442# endif 443 444/* 445 * These are the function pointers that are (un)set when the library has 446 * successfully (un)loaded. 447 */ 448static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL; 449static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL; 450static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL; 451# ifndef OPENSSL_NO_RSA 452static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL; 453# endif 454static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL; 455# ifndef OPENSSL_NO_RSA 456static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL; 457static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL; 458static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL; 459# endif 460static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL; 461 462/* Used in the DSO operations. */ 463static const char *HWCRHK_LIBNAME = NULL; 464static void free_HWCRHK_LIBNAME(void) 465{ 466 if (HWCRHK_LIBNAME) 467 OPENSSL_free((void *)HWCRHK_LIBNAME); 468 HWCRHK_LIBNAME = NULL; 469} 470 471static const char *get_HWCRHK_LIBNAME(void) 472{ 473 if (HWCRHK_LIBNAME) 474 return HWCRHK_LIBNAME; 475 return "nfhwcrhk"; 476} 477 478static long set_HWCRHK_LIBNAME(const char *name) 479{ 480 free_HWCRHK_LIBNAME(); 481 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0); 482} 483 484static const char *n_hwcrhk_Init = "HWCryptoHook_Init"; 485static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish"; 486static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp"; 487# ifndef OPENSSL_NO_RSA 488static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA"; 489# endif 490static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes"; 491# ifndef OPENSSL_NO_RSA 492static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey"; 493static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey"; 494static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey"; 495# endif 496static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT"; 497 498/* 499 * HWCryptoHook library functions and mechanics - these are used by the 500 * higher-level functions further down. NB: As and where there's no error 501 * checking, take a look lower down where these functions are called, the 502 * checking and error handling is probably down there. 503 */ 504 505/* utility function to obtain a context */ 506static int get_context(HWCryptoHook_ContextHandle * hac, 507 HWCryptoHook_CallerContext * cac) 508{ 509 char tempbuf[1024]; 510 HWCryptoHook_ErrMsgBuf rmsg; 511 512 rmsg.buf = tempbuf; 513 rmsg.size = sizeof(tempbuf); 514 515 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg, cac); 516 if (!*hac) 517 return 0; 518 return 1; 519} 520 521/* similarly to release one. */ 522static void release_context(HWCryptoHook_ContextHandle hac) 523{ 524 p_hwcrhk_Finish(hac); 525} 526 527/* Destructor (complements the "ENGINE_chil()" constructor) */ 528static int hwcrhk_destroy(ENGINE *e) 529{ 530 free_HWCRHK_LIBNAME(); 531 ERR_unload_HWCRHK_strings(); 532 return 1; 533} 534 535/* (de)initialisation functions. */ 536static int hwcrhk_init(ENGINE *e) 537{ 538 HWCryptoHook_Init_t *p1; 539 HWCryptoHook_Finish_t *p2; 540 HWCryptoHook_ModExp_t *p3; 541# ifndef OPENSSL_NO_RSA 542 HWCryptoHook_RSA_t *p4; 543 HWCryptoHook_RSALoadKey_t *p5; 544 HWCryptoHook_RSAGetPublicKey_t *p6; 545 HWCryptoHook_RSAUnloadKey_t *p7; 546# endif 547 HWCryptoHook_RandomBytes_t *p8; 548 HWCryptoHook_ModExpCRT_t *p9; 549 550 if (hwcrhk_dso != NULL) { 551 HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_ALREADY_LOADED); 552 goto err; 553 } 554 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */ 555 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0); 556 if (hwcrhk_dso == NULL) { 557 HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE); 558 goto err; 559 } 560 if (!(p1 = (HWCryptoHook_Init_t *) 561 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) || 562 !(p2 = (HWCryptoHook_Finish_t *) 563 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) || 564 !(p3 = (HWCryptoHook_ModExp_t *) 565 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) || 566# ifndef OPENSSL_NO_RSA 567 !(p4 = (HWCryptoHook_RSA_t *) 568 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) || 569 !(p5 = (HWCryptoHook_RSALoadKey_t *) 570 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) || 571 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *) 572 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) || 573 !(p7 = (HWCryptoHook_RSAUnloadKey_t *) 574 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) || 575# endif 576 !(p8 = (HWCryptoHook_RandomBytes_t *) 577 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) || 578 !(p9 = (HWCryptoHook_ModExpCRT_t *) 579 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT))) { 580 HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE); 581 goto err; 582 } 583 /* Copy the pointers */ 584 p_hwcrhk_Init = p1; 585 p_hwcrhk_Finish = p2; 586 p_hwcrhk_ModExp = p3; 587# ifndef OPENSSL_NO_RSA 588 p_hwcrhk_RSA = p4; 589 p_hwcrhk_RSALoadKey = p5; 590 p_hwcrhk_RSAGetPublicKey = p6; 591 p_hwcrhk_RSAUnloadKey = p7; 592# endif 593 p_hwcrhk_RandomBytes = p8; 594 p_hwcrhk_ModExpCRT = p9; 595 596 /* 597 * Check if the application decided to support dynamic locks, and if it 598 * does, use them. 599 */ 600 if (disable_mutex_callbacks == 0) { 601 if (CRYPTO_get_dynlock_create_callback() != NULL && 602 CRYPTO_get_dynlock_lock_callback() != NULL && 603 CRYPTO_get_dynlock_destroy_callback() != NULL) { 604 hwcrhk_globals.mutex_init = hwcrhk_mutex_init; 605 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock; 606 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock; 607 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy; 608 } 609 } 610 611 /* 612 * Try and get a context - if not, we may have a DSO but no accelerator! 613 */ 614 if (!get_context(&hwcrhk_context, &password_context)) { 615 HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_UNIT_FAILURE); 616 goto err; 617 } 618 /* Everything's fine. */ 619# ifndef OPENSSL_NO_RSA 620 if (hndidx_rsa == -1) 621 hndidx_rsa = RSA_get_ex_new_index(0, 622 "nFast HWCryptoHook RSA key handle", 623 NULL, NULL, NULL); 624# endif 625 return 1; 626 err: 627 if (hwcrhk_dso) 628 DSO_free(hwcrhk_dso); 629 hwcrhk_dso = NULL; 630 p_hwcrhk_Init = NULL; 631 p_hwcrhk_Finish = NULL; 632 p_hwcrhk_ModExp = NULL; 633# ifndef OPENSSL_NO_RSA 634 p_hwcrhk_RSA = NULL; 635 p_hwcrhk_RSALoadKey = NULL; 636 p_hwcrhk_RSAGetPublicKey = NULL; 637 p_hwcrhk_RSAUnloadKey = NULL; 638# endif 639 p_hwcrhk_ModExpCRT = NULL; 640 p_hwcrhk_RandomBytes = NULL; 641 return 0; 642} 643 644static int hwcrhk_finish(ENGINE *e) 645{ 646 int to_return = 1; 647 free_HWCRHK_LIBNAME(); 648 if (hwcrhk_dso == NULL) { 649 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_NOT_LOADED); 650 to_return = 0; 651 goto err; 652 } 653 release_context(hwcrhk_context); 654 if (!DSO_free(hwcrhk_dso)) { 655 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_DSO_FAILURE); 656 to_return = 0; 657 goto err; 658 } 659 err: 660 if (logstream) 661 BIO_free(logstream); 662 hwcrhk_dso = NULL; 663 p_hwcrhk_Init = NULL; 664 p_hwcrhk_Finish = NULL; 665 p_hwcrhk_ModExp = NULL; 666# ifndef OPENSSL_NO_RSA 667 p_hwcrhk_RSA = NULL; 668 p_hwcrhk_RSALoadKey = NULL; 669 p_hwcrhk_RSAGetPublicKey = NULL; 670 p_hwcrhk_RSAUnloadKey = NULL; 671# endif 672 p_hwcrhk_ModExpCRT = NULL; 673 p_hwcrhk_RandomBytes = NULL; 674 return to_return; 675} 676 677static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) 678{ 679 int to_return = 1; 680 681 switch (cmd) { 682 case HWCRHK_CMD_SO_PATH: 683 if (hwcrhk_dso) { 684 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_ALREADY_LOADED); 685 return 0; 686 } 687 if (p == NULL) { 688 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, ERR_R_PASSED_NULL_PARAMETER); 689 return 0; 690 } 691 return set_HWCRHK_LIBNAME((const char *)p); 692 case ENGINE_CTRL_SET_LOGSTREAM: 693 { 694 BIO *bio = (BIO *)p; 695 696 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 697 if (logstream) { 698 BIO_free(logstream); 699 logstream = NULL; 700 } 701 if (CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO) > 1) 702 logstream = bio; 703 else 704 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_BIO_WAS_FREED); 705 } 706 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 707 break; 708 case ENGINE_CTRL_SET_PASSWORD_CALLBACK: 709 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 710 password_context.password_callback = (pem_password_cb *)f; 711 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 712 break; 713 case ENGINE_CTRL_SET_USER_INTERFACE: 714 case HWCRHK_CMD_SET_USER_INTERFACE: 715 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 716 password_context.ui_method = (UI_METHOD *)p; 717 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 718 break; 719 case ENGINE_CTRL_SET_CALLBACK_DATA: 720 case HWCRHK_CMD_SET_CALLBACK_DATA: 721 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 722 password_context.callback_data = p; 723 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 724 break; 725 /* 726 * this enables or disables the "SimpleForkCheck" flag used in the 727 * initialisation structure. 728 */ 729 case ENGINE_CTRL_CHIL_SET_FORKCHECK: 730 case HWCRHK_CMD_FORK_CHECK: 731 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 732 if (i) 733 hwcrhk_globals.flags |= HWCryptoHook_InitFlags_SimpleForkCheck; 734 else 735 hwcrhk_globals.flags &= ~HWCryptoHook_InitFlags_SimpleForkCheck; 736 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 737 break; 738 /* 739 * This will prevent the initialisation function from "installing" 740 * the mutex-handling callbacks, even if they are available from 741 * within the library (or were provided to the library from the 742 * calling application). This is to remove any baggage for 743 * applications not using multithreading. 744 */ 745 case ENGINE_CTRL_CHIL_NO_LOCKING: 746 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 747 disable_mutex_callbacks = 1; 748 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 749 break; 750 case HWCRHK_CMD_THREAD_LOCKING: 751 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 752 disable_mutex_callbacks = ((i == 0) ? 0 : 1); 753 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 754 break; 755 756 /* The command isn't understood by this engine */ 757 default: 758 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, 759 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED); 760 to_return = 0; 761 break; 762 } 763 764 return to_return; 765} 766 767static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id, 768 UI_METHOD *ui_method, 769 void *callback_data) 770{ 771# ifndef OPENSSL_NO_RSA 772 RSA *rtmp = NULL; 773# endif 774 EVP_PKEY *res = NULL; 775# ifndef OPENSSL_NO_RSA 776 HWCryptoHook_MPI e, n; 777 HWCryptoHook_RSAKeyHandle *hptr; 778# endif 779# if !defined(OPENSSL_NO_RSA) 780 char tempbuf[1024]; 781 HWCryptoHook_ErrMsgBuf rmsg; 782 HWCryptoHook_PassphraseContext ppctx; 783# endif 784 785# if !defined(OPENSSL_NO_RSA) 786 rmsg.buf = tempbuf; 787 rmsg.size = sizeof(tempbuf); 788# endif 789 790 if (!hwcrhk_context) { 791 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NOT_INITIALISED); 792 goto err; 793 } 794# ifndef OPENSSL_NO_RSA 795 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle)); 796 if (!hptr) { 797 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE); 798 goto err; 799 } 800 ppctx.ui_method = ui_method; 801 ppctx.callback_data = callback_data; 802 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr, &rmsg, &ppctx)) { 803 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR); 804 ERR_add_error_data(1, rmsg.buf); 805 goto err; 806 } 807 if (!*hptr) { 808 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NO_KEY); 809 goto err; 810 } 811# endif 812# ifndef OPENSSL_NO_RSA 813 rtmp = RSA_new_method(eng); 814 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr); 815 rtmp->e = BN_new(); 816 rtmp->n = BN_new(); 817 rtmp->flags |= RSA_FLAG_EXT_PKEY; 818 MPI2BN(rtmp->e, e); 819 MPI2BN(rtmp->n, n); 820 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg) 821 != HWCRYPTOHOOK_ERROR_MPISIZE) { 822 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR); 823 ERR_add_error_data(1, rmsg.buf); 824 goto err; 825 } 826 827 bn_expand2(rtmp->e, e.size / sizeof(BN_ULONG)); 828 bn_expand2(rtmp->n, n.size / sizeof(BN_ULONG)); 829 MPI2BN(rtmp->e, e); 830 MPI2BN(rtmp->n, n); 831 832 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)) { 833 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR); 834 ERR_add_error_data(1, rmsg.buf); 835 goto err; 836 } 837 rtmp->e->top = e.size / sizeof(BN_ULONG); 838 bn_fix_top(rtmp->e); 839 rtmp->n->top = n.size / sizeof(BN_ULONG); 840 bn_fix_top(rtmp->n); 841 842 res = EVP_PKEY_new(); 843 EVP_PKEY_assign_RSA(res, rtmp); 844# endif 845 846 if (!res) 847 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, 848 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED); 849 850 return res; 851 err: 852 if (res) 853 EVP_PKEY_free(res); 854# ifndef OPENSSL_NO_RSA 855 if (rtmp) 856 RSA_free(rtmp); 857# endif 858 return NULL; 859} 860 861static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id, 862 UI_METHOD *ui_method, void *callback_data) 863{ 864 EVP_PKEY *res = NULL; 865 866# ifndef OPENSSL_NO_RSA 867 res = hwcrhk_load_privkey(eng, key_id, ui_method, callback_data); 868# endif 869 870 if (res) 871 switch (res->type) { 872# ifndef OPENSSL_NO_RSA 873 case EVP_PKEY_RSA: 874 { 875 RSA *rsa = NULL; 876 877 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); 878 rsa = res->pkey.rsa; 879 res->pkey.rsa = RSA_new(); 880 res->pkey.rsa->n = rsa->n; 881 res->pkey.rsa->e = rsa->e; 882 rsa->n = NULL; 883 rsa->e = NULL; 884 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); 885 RSA_free(rsa); 886 } 887 break; 888# endif 889 default: 890 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY, 891 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED); 892 goto err; 893 } 894 895 return res; 896 err: 897 if (res) 898 EVP_PKEY_free(res); 899 return NULL; 900} 901 902/* A little mod_exp */ 903static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 904 const BIGNUM *m, BN_CTX *ctx) 905{ 906 char tempbuf[1024]; 907 HWCryptoHook_ErrMsgBuf rmsg; 908 /* 909 * Since HWCryptoHook_MPI is pretty compatible with BIGNUM's, we use them 910 * directly, plus a little macro magic. We only thing we need to make 911 * sure of is that enough space is allocated. 912 */ 913 HWCryptoHook_MPI m_a, m_p, m_n, m_r; 914 int to_return, ret; 915 916 to_return = 0; /* expect failure */ 917 rmsg.buf = tempbuf; 918 rmsg.size = sizeof(tempbuf); 919 920 if (!hwcrhk_context) { 921 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_NOT_INITIALISED); 922 goto err; 923 } 924 /* Prepare the params */ 925 bn_expand2(r, m->top); /* Check for error !! */ 926 BN2MPI(m_a, a); 927 BN2MPI(m_p, p); 928 BN2MPI(m_n, m); 929 MPI2BN(r, m_r); 930 931 /* Perform the operation */ 932 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg); 933 934 /* Convert the response */ 935 r->top = m_r.size / sizeof(BN_ULONG); 936 bn_fix_top(r); 937 938 if (ret < 0) { 939 /* 940 * FIXME: When this error is returned, HWCryptoHook is telling us 941 * that falling back to software computation might be a good thing. 942 */ 943 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 944 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FALLBACK); 945 } else { 946 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FAILED); 947 } 948 ERR_add_error_data(1, rmsg.buf); 949 goto err; 950 } 951 952 to_return = 1; 953 err: 954 return to_return; 955} 956 957# ifndef OPENSSL_NO_RSA 958static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, 959 BN_CTX *ctx) 960{ 961 char tempbuf[1024]; 962 HWCryptoHook_ErrMsgBuf rmsg; 963 HWCryptoHook_RSAKeyHandle *hptr; 964 int to_return = 0, ret; 965 966 rmsg.buf = tempbuf; 967 rmsg.size = sizeof(tempbuf); 968 969 if (!hwcrhk_context) { 970 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, HWCRHK_R_NOT_INITIALISED); 971 goto err; 972 } 973 974 /* 975 * This provides support for nForce keys. Since that's opaque data all 976 * we do is provide a handle to the proper key and let HWCryptoHook take 977 * care of the rest. 978 */ 979 if ((hptr = 980 (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa)) 981 != NULL) { 982 HWCryptoHook_MPI m_a, m_r; 983 984 if (!rsa->n) { 985 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 986 HWCRHK_R_MISSING_KEY_COMPONENTS); 987 goto err; 988 } 989 990 /* Prepare the params */ 991 bn_expand2(r, rsa->n->top); /* Check for error !! */ 992 BN2MPI(m_a, I); 993 MPI2BN(r, m_r); 994 995 /* Perform the operation */ 996 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg); 997 998 /* Convert the response */ 999 r->top = m_r.size / sizeof(BN_ULONG); 1000 bn_fix_top(r); 1001 1002 if (ret < 0) { 1003 /* 1004 * FIXME: When this error is returned, HWCryptoHook is telling us 1005 * that falling back to software computation might be a good 1006 * thing. 1007 */ 1008 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 1009 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1010 HWCRHK_R_REQUEST_FALLBACK); 1011 } else { 1012 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1013 HWCRHK_R_REQUEST_FAILED); 1014 } 1015 ERR_add_error_data(1, rmsg.buf); 1016 goto err; 1017 } 1018 } else { 1019 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r; 1020 1021 if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) { 1022 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1023 HWCRHK_R_MISSING_KEY_COMPONENTS); 1024 goto err; 1025 } 1026 1027 /* Prepare the params */ 1028 bn_expand2(r, rsa->n->top); /* Check for error !! */ 1029 BN2MPI(m_a, I); 1030 BN2MPI(m_p, rsa->p); 1031 BN2MPI(m_q, rsa->q); 1032 BN2MPI(m_dmp1, rsa->dmp1); 1033 BN2MPI(m_dmq1, rsa->dmq1); 1034 BN2MPI(m_iqmp, rsa->iqmp); 1035 MPI2BN(r, m_r); 1036 1037 /* Perform the operation */ 1038 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q, 1039 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg); 1040 1041 /* Convert the response */ 1042 r->top = m_r.size / sizeof(BN_ULONG); 1043 bn_fix_top(r); 1044 1045 if (ret < 0) { 1046 /* 1047 * FIXME: When this error is returned, HWCryptoHook is telling us 1048 * that falling back to software computation might be a good 1049 * thing. 1050 */ 1051 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 1052 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1053 HWCRHK_R_REQUEST_FALLBACK); 1054 } else { 1055 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1056 HWCRHK_R_REQUEST_FAILED); 1057 } 1058 ERR_add_error_data(1, rmsg.buf); 1059 goto err; 1060 } 1061 } 1062 /* 1063 * If we're here, we must be here with some semblance of success :-) 1064 */ 1065 to_return = 1; 1066 err: 1067 return to_return; 1068} 1069# endif 1070 1071# ifndef OPENSSL_NO_RSA 1072/* This function is aliased to mod_exp (with the mont stuff dropped). */ 1073static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 1074 const BIGNUM *m, BN_CTX *ctx, 1075 BN_MONT_CTX *m_ctx) 1076{ 1077 return hwcrhk_mod_exp(r, a, p, m, ctx); 1078} 1079 1080static int hwcrhk_rsa_finish(RSA *rsa) 1081{ 1082 HWCryptoHook_RSAKeyHandle *hptr; 1083 1084 hptr = RSA_get_ex_data(rsa, hndidx_rsa); 1085 if (hptr) { 1086 p_hwcrhk_RSAUnloadKey(*hptr, NULL); 1087 OPENSSL_free(hptr); 1088 RSA_set_ex_data(rsa, hndidx_rsa, NULL); 1089 } 1090 return 1; 1091} 1092 1093# endif 1094 1095# ifndef OPENSSL_NO_DH 1096/* This function is aliased to mod_exp (with the dh and mont dropped). */ 1097static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r, 1098 const BIGNUM *a, const BIGNUM *p, 1099 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) 1100{ 1101 return hwcrhk_mod_exp(r, a, p, m, ctx); 1102} 1103# endif 1104 1105/* Random bytes are good */ 1106static int hwcrhk_rand_bytes(unsigned char *buf, int num) 1107{ 1108 char tempbuf[1024]; 1109 HWCryptoHook_ErrMsgBuf rmsg; 1110 int to_return = 0; /* assume failure */ 1111 int ret; 1112 1113 rmsg.buf = tempbuf; 1114 rmsg.size = sizeof(tempbuf); 1115 1116 if (!hwcrhk_context) { 1117 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_NOT_INITIALISED); 1118 goto err; 1119 } 1120 1121 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg); 1122 if (ret < 0) { 1123 /* 1124 * FIXME: When this error is returned, HWCryptoHook is telling us 1125 * that falling back to software computation might be a good thing. 1126 */ 1127 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 1128 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FALLBACK); 1129 } else { 1130 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FAILED); 1131 } 1132 ERR_add_error_data(1, rmsg.buf); 1133 goto err; 1134 } 1135 to_return = 1; 1136 err: 1137 return to_return; 1138} 1139 1140static int hwcrhk_rand_status(void) 1141{ 1142 return 1; 1143} 1144 1145/* 1146 * Mutex calls: since the HWCryptoHook model closely follows the POSIX model 1147 * these just wrap the POSIX functions and add some logging. 1148 */ 1149 1150static int hwcrhk_mutex_init(HWCryptoHook_Mutex * mt, 1151 HWCryptoHook_CallerContext * cactx) 1152{ 1153 mt->lockid = CRYPTO_get_new_dynlockid(); 1154 if (mt->lockid == 0) 1155 return 1; /* failure */ 1156 return 0; /* success */ 1157} 1158 1159static int hwcrhk_mutex_lock(HWCryptoHook_Mutex * mt) 1160{ 1161 CRYPTO_w_lock(mt->lockid); 1162 return 0; 1163} 1164 1165static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt) 1166{ 1167 CRYPTO_w_unlock(mt->lockid); 1168} 1169 1170static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex * mt) 1171{ 1172 CRYPTO_destroy_dynlockid(mt->lockid); 1173} 1174 1175static int hwcrhk_get_pass(const char *prompt_info, 1176 int *len_io, char *buf, 1177 HWCryptoHook_PassphraseContext * ppctx, 1178 HWCryptoHook_CallerContext * cactx) 1179{ 1180 pem_password_cb *callback = NULL; 1181 void *callback_data = NULL; 1182 UI_METHOD *ui_method = NULL; 1183 /* 1184 * Despite what the documentation says prompt_info can be an empty 1185 * string. 1186 */ 1187 if (prompt_info && !*prompt_info) 1188 prompt_info = NULL; 1189 1190 if (cactx) { 1191 if (cactx->ui_method) 1192 ui_method = cactx->ui_method; 1193 if (cactx->password_callback) 1194 callback = cactx->password_callback; 1195 if (cactx->callback_data) 1196 callback_data = cactx->callback_data; 1197 } 1198 if (ppctx) { 1199 if (ppctx->ui_method) { 1200 ui_method = ppctx->ui_method; 1201 callback = NULL; 1202 } 1203 if (ppctx->callback_data) 1204 callback_data = ppctx->callback_data; 1205 } 1206 if (callback == NULL && ui_method == NULL) { 1207 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS, HWCRHK_R_NO_CALLBACK); 1208 return -1; 1209 } 1210 1211 if (ui_method) { 1212 UI *ui = UI_new_method(ui_method); 1213 if (ui) { 1214 int ok; 1215 char *prompt = UI_construct_prompt(ui, 1216 "pass phrase", prompt_info); 1217 1218 ok = UI_add_input_string(ui, prompt, 1219 UI_INPUT_FLAG_DEFAULT_PWD, 1220 buf, 0, (*len_io) - 1); 1221 UI_add_user_data(ui, callback_data); 1222 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); 1223 1224 if (ok >= 0) 1225 do { 1226 ok = UI_process(ui); 1227 } 1228 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); 1229 1230 if (ok >= 0) 1231 *len_io = strlen(buf); 1232 1233 UI_free(ui); 1234 OPENSSL_free(prompt); 1235 } 1236 } else { 1237 *len_io = callback(buf, *len_io, 0, callback_data); 1238 } 1239 if (!*len_io) 1240 return -1; 1241 return 0; 1242} 1243 1244static int hwcrhk_insert_card(const char *prompt_info, 1245 const char *wrong_info, 1246 HWCryptoHook_PassphraseContext * ppctx, 1247 HWCryptoHook_CallerContext * cactx) 1248{ 1249 int ok = -1; 1250 UI *ui; 1251 void *callback_data = NULL; 1252 UI_METHOD *ui_method = NULL; 1253 1254 if (cactx) { 1255 if (cactx->ui_method) 1256 ui_method = cactx->ui_method; 1257 if (cactx->callback_data) 1258 callback_data = cactx->callback_data; 1259 } 1260 if (ppctx) { 1261 if (ppctx->ui_method) 1262 ui_method = ppctx->ui_method; 1263 if (ppctx->callback_data) 1264 callback_data = ppctx->callback_data; 1265 } 1266 if (ui_method == NULL) { 1267 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD, HWCRHK_R_NO_CALLBACK); 1268 return -1; 1269 } 1270 1271 ui = UI_new_method(ui_method); 1272 1273 if (ui) { 1274 char answer; 1275 char buf[BUFSIZ]; 1276 /* 1277 * Despite what the documentation says wrong_info can be an empty 1278 * string. 1279 */ 1280 if (wrong_info && *wrong_info) 1281 BIO_snprintf(buf, sizeof(buf) - 1, 1282 "Current card: \"%s\"\n", wrong_info); 1283 else 1284 buf[0] = 0; 1285 ok = UI_dup_info_string(ui, buf); 1286 if (ok >= 0 && prompt_info) { 1287 BIO_snprintf(buf, sizeof(buf) - 1, 1288 "Insert card \"%s\"", prompt_info); 1289 ok = UI_dup_input_boolean(ui, buf, 1290 "\n then hit <enter> or C<enter> to cancel\n", 1291 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, 1292 &answer); 1293 } 1294 UI_add_user_data(ui, callback_data); 1295 1296 if (ok >= 0) 1297 ok = UI_process(ui); 1298 UI_free(ui); 1299 1300 if (ok == -2 || (ok >= 0 && answer == 'C')) 1301 ok = 1; 1302 else if (ok < 0) 1303 ok = -1; 1304 else 1305 ok = 0; 1306 } 1307 return ok; 1308} 1309 1310static void hwcrhk_log_message(void *logstr, const char *message) 1311{ 1312 BIO *lstream = NULL; 1313 1314 CRYPTO_w_lock(CRYPTO_LOCK_BIO); 1315 if (logstr) 1316 lstream = *(BIO **)logstr; 1317 if (lstream) { 1318 BIO_printf(lstream, "%s\n", message); 1319 } 1320 CRYPTO_w_unlock(CRYPTO_LOCK_BIO); 1321} 1322 1323/* 1324 * This stuff is needed if this ENGINE is being compiled into a 1325 * self-contained shared-library. 1326 */ 1327# ifndef OPENSSL_NO_DYNAMIC_ENGINE 1328static int bind_fn(ENGINE *e, const char *id) 1329{ 1330 if (id && (strcmp(id, engine_hwcrhk_id) != 0) && 1331 (strcmp(id, engine_hwcrhk_id_alt) != 0)) 1332 return 0; 1333 if (!bind_helper(e)) 1334 return 0; 1335 return 1; 1336} 1337 1338IMPLEMENT_DYNAMIC_CHECK_FN() 1339 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) 1340# endif /* OPENSSL_NO_DYNAMIC_ENGINE */ 1341# endif /* !OPENSSL_NO_HW_CHIL */ 1342#endif /* !OPENSSL_NO_HW */ 1343