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