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