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