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