1 /* crypto/engine/hw_ncipher.c -*- mode: C; c-file-style: "eay" -*- */
2 /* Written by Richard Levitte (richard@levitte.org), Geoff Thorpe
3 * (geoff@geoffthorpe.net) and Dr Stephen N Henson (shenson@bigfoot.com)
4 * for the OpenSSL project 2000.
6 /* ====================================================================
7 * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
35 * 6. Redistributions of any form whatsoever must retain the following
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
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 * ====================================================================
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).
62 #include <openssl/crypto.h>
63 #include <openssl/pem.h>
65 #include <openssl/dso.h>
66 #include <openssl/engine.h>
67 #include <openssl/ui.h>
70 #ifndef OPENSSL_NO_HW_NCIPHER
72 /* Attribution notice: nCipher have said several times that it's OK for
73 * us to implement a general interface to their boxes, and recently declared
74 * their HWCryptoHook to be public, and therefore available for us to use.
77 * The hwcryptohook.h included here is from May 2000.
81 #include "hwcryptohook.h"
83 #include "vendor_defns/hwcryptohook.h"
86 static int hwcrhk_destroy(ENGINE *e);
87 static int hwcrhk_init(ENGINE *e);
88 static int hwcrhk_finish(ENGINE *e);
89 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
91 /* Functions to handle mutexes */
92 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
93 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
94 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
95 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
98 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
99 const BIGNUM *m, BN_CTX *ctx);
101 #ifndef OPENSSL_NO_RSA
103 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa);
105 /* This function is aliased to mod_exp (with the mont stuff dropped). */
106 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
107 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
110 /* This function is alised to mod_exp (with the DH and mont dropped). */
111 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
112 const BIGNUM *a, const BIGNUM *p,
113 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
116 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
117 static int hwcrhk_rand_status(void);
120 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
121 UI_METHOD *ui_method, void *callback_data);
122 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
123 UI_METHOD *ui_method, void *callback_data);
124 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
125 int ind,long argl, void *argp);
127 /* Interaction stuff */
128 static int hwcrhk_insert_card(const char *prompt_info,
129 const char *wrong_info,
130 HWCryptoHook_PassphraseContext *ppctx,
131 HWCryptoHook_CallerContext *cactx);
132 static int hwcrhk_get_pass(const char *prompt_info,
133 int *len_io, char *buf,
134 HWCryptoHook_PassphraseContext *ppctx,
135 HWCryptoHook_CallerContext *cactx);
136 static void hwcrhk_log_message(void *logstr, const char *message);
138 /* The definitions for control commands specific to this engine */
139 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
140 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
141 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
142 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
143 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
144 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
147 "Specifies the path to the 'hwcrhk' shared library",
148 ENGINE_CMD_FLAG_STRING},
149 {HWCRHK_CMD_FORK_CHECK,
151 "Turns fork() checking on or off (boolean)",
152 ENGINE_CMD_FLAG_NUMERIC},
153 {HWCRHK_CMD_THREAD_LOCKING,
155 "Turns thread-safe locking on or off (boolean)",
156 ENGINE_CMD_FLAG_NUMERIC},
157 {HWCRHK_CMD_SET_USER_INTERFACE,
158 "SET_USER_INTERFACE",
159 "Set the global user interface (internal)",
160 ENGINE_CMD_FLAG_INTERNAL},
161 {HWCRHK_CMD_SET_CALLBACK_DATA,
163 "Set the global user interface extra data (internal)",
164 ENGINE_CMD_FLAG_INTERNAL},
168 #ifndef OPENSSL_NO_RSA
169 /* Our internal RSA_METHOD that we provide pointers to */
170 static RSA_METHOD hwcrhk_rsa =
172 "nCipher RSA method",
188 #ifndef OPENSSL_NO_DH
189 /* Our internal DH_METHOD that we provide pointers to */
190 static DH_METHOD hwcrhk_dh =
203 static RAND_METHOD hwcrhk_rand =
205 /* "nCipher RAND method", */
214 #ifndef OPENSSL_NO_ERR
215 /* Error function codes for use in hwcrhk operation */
216 #define HWCRHK_F_HWCRHK_INIT 100
217 #define HWCRHK_F_HWCRHK_FINISH 101
218 #define HWCRHK_F_HWCRHK_CTRL 102
219 #define HWCRHK_F_HWCRHK_LOAD_PRIVKEY 103
220 #define HWCRHK_F_HWCRHK_LOAD_PUBKEY 104
221 #define HWCRHK_F_HWCRHK_MOD_EXP 105
222 #define HWCRHK_F_HWCRHK_RSA_MOD_EXP 106
223 #define HWCRHK_F_HWCRHK_RAND_BYTES 107
224 #define HWCRHK_F_HWCRHK_GET_PASS 108
225 #define HWCRHK_F_HWCRHK_INSERT_CARD 109
226 /* Error reason codes */
227 #define HWCRHK_R_ALREADY_LOADED 110
228 #define HWCRHK_R_DSO_FAILURE 111
229 #define HWCRHK_R_UNIT_FAILURE 112
230 #define HWCRHK_R_NOT_LOADED 113
231 #define HWCRHK_R_BIO_WAS_FREED 114
232 #define HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED 115
233 #define HWCRHK_R_NOT_INITIALISED 116
234 #define HWCRHK_R_CHIL_ERROR 117
235 #define HWCRHK_R_NO_KEY 118
236 #define HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED 119
237 #define HWCRHK_R_REQUEST_FALLBACK 120
238 #define HWCRHK_R_REQUEST_FAILED 121
239 #define HWCRHK_R_MISSING_KEY_COMPONENTS 122
240 #define HWCRHK_R_NO_CALLBACK 123
241 static ERR_STRING_DATA hwcrhk_str_functs[] =
243 /* This first element is changed to match the dynamic 'lib' number */
244 {ERR_PACK(0,0,0), "hwcrhk engine code"},
245 {ERR_PACK(0,HWCRHK_F_HWCRHK_INIT,0), "hwcrhk_init"},
246 {ERR_PACK(0,HWCRHK_F_HWCRHK_FINISH,0), ""},
247 {ERR_PACK(0,HWCRHK_F_HWCRHK_CTRL,0), ""},
248 {ERR_PACK(0,HWCRHK_F_HWCRHK_LOAD_PRIVKEY,0), ""},
249 {ERR_PACK(0,HWCRHK_F_HWCRHK_LOAD_PUBKEY,0), ""},
250 {ERR_PACK(0,HWCRHK_F_HWCRHK_MOD_EXP,0), ""},
251 {ERR_PACK(0,HWCRHK_F_HWCRHK_RSA_MOD_EXP,0), ""},
252 {ERR_PACK(0,HWCRHK_F_HWCRHK_RAND_BYTES,0), ""},
253 {ERR_PACK(0,HWCRHK_F_HWCRHK_GET_PASS,0), ""},
254 {ERR_PACK(0,HWCRHK_F_HWCRHK_INSERT_CARD,0), ""},
255 /* Error reason codes */
256 {HWCRHK_R_ALREADY_LOADED ,"already loaded"},
257 {HWCRHK_R_DSO_FAILURE ,"DSO failure"},
258 {HWCRHK_R_UNIT_FAILURE ,"unit failure"},
259 {HWCRHK_R_NOT_LOADED ,"not loaded"},
260 {HWCRHK_R_BIO_WAS_FREED ,"BIO was freed"},
261 {HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED ,"ctrl command not implemented"},
262 {HWCRHK_R_NOT_INITIALISED ,"not initialised"},
263 {HWCRHK_R_CHIL_ERROR ,"'chil' error"},
264 {HWCRHK_R_NO_KEY ,"no key"},
265 {HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED,"private key algorithms disabled"},
266 {HWCRHK_R_REQUEST_FALLBACK ,"request fallback"},
267 {HWCRHK_R_REQUEST_FAILED ,"request failed"},
268 {HWCRHK_R_MISSING_KEY_COMPONENTS ,"missing key components"},
269 {HWCRHK_R_NO_CALLBACK ,"no callback"},
272 /* The library number we obtain dynamically from the ERR code */
273 static int hwcrhk_err_lib = -1;
274 #define HWCRHKerr(f,r) ERR_PUT_error(hwcrhk_err_lib,(f),(r),__FILE__,__LINE__)
275 static void hwcrhk_load_error_strings(void)
277 if(hwcrhk_err_lib < 0)
279 if((hwcrhk_err_lib = ERR_get_next_error_library()) <= 0)
281 hwcrhk_str_functs[0].error = ERR_PACK(hwcrhk_err_lib,0,0);
282 ERR_load_strings(hwcrhk_err_lib, hwcrhk_str_functs);
285 static void hwcrhk_unload_error_strings(void)
287 if(hwcrhk_err_lib >= 0)
289 ERR_unload_strings(hwcrhk_err_lib, hwcrhk_str_functs);
294 #define HWCRHKerr(f,r) /* NOP */
295 static void hwcrhk_load_error_strings(void) { } /* NOP */
296 static void hwcrhk_unload_error_strings(void) { } /* NOP */
299 /* Constants used when creating the ENGINE */
300 static const char *engine_hwcrhk_id = "chil";
301 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
303 /* Internal stuff for HWCryptoHook */
305 /* Some structures needed for proper use of thread locks */
306 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
307 into HWCryptoHook_Mutex */
308 struct HWCryptoHook_MutexValue
313 /* hwcryptohook.h has some typedefs that turn
314 struct HWCryptoHook_PassphraseContextValue
315 into HWCryptoHook_PassphraseContext */
316 struct HWCryptoHook_PassphraseContextValue
318 UI_METHOD *ui_method;
322 /* hwcryptohook.h has some typedefs that turn
323 struct HWCryptoHook_CallerContextValue
324 into HWCryptoHook_CallerContext */
325 struct HWCryptoHook_CallerContextValue
327 pem_password_cb *password_callback; /* Deprecated! Only present for
328 backward compatibility! */
329 UI_METHOD *ui_method;
333 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
334 BIGNUM's, so lets define a couple of conversion macros */
335 #define BN2MPI(mp, bn) \
336 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
337 #define MPI2BN(bn, mp) \
338 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
340 static BIO *logstream = NULL;
341 static int disable_mutex_callbacks = 0;
343 /* One might wonder why these are needed, since one can pass down at least
344 a UI_METHOD and a pointer to callback data to the key-loading functions.
345 The thing is that the ModExp and RSAImmed functions can load keys as well,
346 if the data they get is in a special, nCipher-defined format (hint: if you
347 look at the private exponent of the RSA data as a string, you'll see this
348 string: "nCipher KM tool key id", followed by some bytes, followed a key
349 identity string, followed by more bytes. This happens when you use "embed"
350 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
351 any passphrase or caller context, and our functions can't really take any
352 callback data either. Still, the "insert_card" and "get_passphrase"
353 callbacks may be called down the line, and will need to know what user
354 interface callbacks to call, and having callback data from the application
355 may be a nice thing as well, so we need to keep track of that globally. */
356 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
358 /* Stuff to pass to the HWCryptoHook library */
359 static HWCryptoHook_InitInfo hwcrhk_globals = {
361 &logstream, /* logstream */
362 sizeof(BN_ULONG), /* limbsize */
363 0, /* mslimb first: false for BNs */
364 -1, /* msbyte first: use native */
365 0, /* Max mutexes, 0 = no small limit */
366 0, /* Max simultaneous, 0 = default */
368 /* The next few are mutex stuff: we write wrapper functions
369 around the OS mutex functions. We initialise them to 0
370 here, and change that to actual function pointers in hwcrhk_init()
371 if dynamic locks are supported (that is, if the application
372 programmer has made sure of setting up callbacks bafore starting
373 this engine) *and* if disable_mutex_callbacks hasn't been set by
374 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
375 sizeof(HWCryptoHook_Mutex),
381 /* The next few are condvar stuff: we write wrapper functions
382 round the OS functions. Currently not implemented and not
383 and absolute necessity even in threaded programs, therefore
384 0'ed. Will hopefully be implemented some day, since it
385 enhances the efficiency of HWCryptoHook. */
386 0, /* sizeof(HWCryptoHook_CondVar), */
387 0, /* hwcrhk_cv_init, */
388 0, /* hwcrhk_cv_wait, */
389 0, /* hwcrhk_cv_signal, */
390 0, /* hwcrhk_cv_broadcast, */
391 0, /* hwcrhk_cv_destroy, */
393 hwcrhk_get_pass, /* pass phrase */
394 hwcrhk_insert_card, /* insert a card */
395 hwcrhk_log_message /* Log message */
399 /* Now, to our own code */
401 /* This internal function is used by ENGINE_ncipher() and possibly by the
402 * "dynamic" ENGINE support too */
403 static int bind_helper(ENGINE *e)
405 #ifndef OPENSSL_NO_RSA
406 const RSA_METHOD *meth1;
408 #ifndef OPENSSL_NO_DH
409 const DH_METHOD *meth2;
411 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
412 !ENGINE_set_name(e, engine_hwcrhk_name) ||
413 #ifndef OPENSSL_NO_RSA
414 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
416 #ifndef OPENSSL_NO_DH
417 !ENGINE_set_DH(e, &hwcrhk_dh) ||
419 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
420 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
421 !ENGINE_set_init_function(e, hwcrhk_init) ||
422 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
423 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
424 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
425 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
426 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
429 #ifndef OPENSSL_NO_RSA
430 /* We know that the "PKCS1_SSLeay()" functions hook properly
431 * to the cswift-specific mod_exp and mod_exp_crt so we use
432 * those functions. NB: We don't use ENGINE_openssl() or
433 * anything "more generic" because something like the RSAref
434 * code may not hook properly, and if you own one of these
435 * cards then you have the right to do RSA operations on it
437 meth1 = RSA_PKCS1_SSLeay();
438 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
439 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
440 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
441 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
444 #ifndef OPENSSL_NO_DH
445 /* Much the same for Diffie-Hellman */
446 meth2 = DH_OpenSSL();
447 hwcrhk_dh.generate_key = meth2->generate_key;
448 hwcrhk_dh.compute_key = meth2->compute_key;
451 /* Ensure the hwcrhk error handling is set up */
452 hwcrhk_load_error_strings();
456 static ENGINE *engine_ncipher(void)
458 ENGINE *ret = ENGINE_new();
461 if(!bind_helper(ret))
469 void ENGINE_load_chil(void)
471 /* Copied from eng_[openssl|dyn].c */
472 ENGINE *toadd = engine_ncipher();
479 /* This is a process-global DSO handle used for loading and unloading
480 * the HWCryptoHook library. NB: This is only set (or unset) during an
481 * init() or finish() call (reference counts permitting) and they're
482 * operating with global locks, so this should be thread-safe
484 static DSO *hwcrhk_dso = NULL;
485 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
486 #ifndef OPENSSL_NO_RSA
487 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
490 /* These are the function pointers that are (un)set when the library has
491 * successfully (un)loaded. */
492 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
493 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
494 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
495 #ifndef OPENSSL_NO_RSA
496 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
498 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
499 #ifndef OPENSSL_NO_RSA
500 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
501 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
502 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
504 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
506 /* Used in the DSO operations. */
507 static const char def_HWCRHK_LIBNAME[] = "nfhwcrhk";
508 static const char *HWCRHK_LIBNAME = def_HWCRHK_LIBNAME;
509 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
510 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
511 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
512 #ifndef OPENSSL_NO_RSA
513 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
515 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
516 #ifndef OPENSSL_NO_RSA
517 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
518 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
519 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
521 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
523 /* HWCryptoHook library functions and mechanics - these are used by the
524 * higher-level functions further down. NB: As and where there's no
525 * error checking, take a look lower down where these functions are
526 * called, the checking and error handling is probably down there. */
528 /* utility function to obtain a context */
529 static int get_context(HWCryptoHook_ContextHandle *hac,
530 HWCryptoHook_CallerContext *cac)
533 HWCryptoHook_ErrMsgBuf rmsg;
538 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
545 /* similarly to release one. */
546 static void release_context(HWCryptoHook_ContextHandle hac)
548 p_hwcrhk_Finish(hac);
551 /* Destructor (complements the "ENGINE_ncipher()" constructor) */
552 static int hwcrhk_destroy(ENGINE *e)
554 hwcrhk_unload_error_strings();
558 /* (de)initialisation functions. */
559 static int hwcrhk_init(ENGINE *e)
561 HWCryptoHook_Init_t *p1;
562 HWCryptoHook_Finish_t *p2;
563 HWCryptoHook_ModExp_t *p3;
564 #ifndef OPENSSL_NO_RSA
565 HWCryptoHook_RSA_t *p4;
566 HWCryptoHook_RSALoadKey_t *p5;
567 HWCryptoHook_RSAGetPublicKey_t *p6;
568 HWCryptoHook_RSAUnloadKey_t *p7;
570 HWCryptoHook_RandomBytes_t *p8;
571 HWCryptoHook_ModExpCRT_t *p9;
573 if(hwcrhk_dso != NULL)
575 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
578 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
579 hwcrhk_dso = DSO_load(NULL, HWCRHK_LIBNAME, NULL, 0);
580 if(hwcrhk_dso == NULL)
582 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
585 if(!(p1 = (HWCryptoHook_Init_t *)
586 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
587 !(p2 = (HWCryptoHook_Finish_t *)
588 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
589 !(p3 = (HWCryptoHook_ModExp_t *)
590 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
591 #ifndef OPENSSL_NO_RSA
592 !(p4 = (HWCryptoHook_RSA_t *)
593 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
594 !(p5 = (HWCryptoHook_RSALoadKey_t *)
595 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
596 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
597 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
598 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
599 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
601 !(p8 = (HWCryptoHook_RandomBytes_t *)
602 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
603 !(p9 = (HWCryptoHook_ModExpCRT_t *)
604 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
606 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
609 /* Copy the pointers */
611 p_hwcrhk_Finish = p2;
612 p_hwcrhk_ModExp = p3;
613 #ifndef OPENSSL_NO_RSA
615 p_hwcrhk_RSALoadKey = p5;
616 p_hwcrhk_RSAGetPublicKey = p6;
617 p_hwcrhk_RSAUnloadKey = p7;
619 p_hwcrhk_RandomBytes = p8;
620 p_hwcrhk_ModExpCRT = p9;
622 /* Check if the application decided to support dynamic locks,
623 and if it does, use them. */
624 if (disable_mutex_callbacks == 0 &&
625 CRYPTO_get_dynlock_create_callback() != NULL &&
626 CRYPTO_get_dynlock_lock_callback() != NULL &&
627 CRYPTO_get_dynlock_destroy_callback() != NULL)
629 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
630 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
631 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
632 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
635 /* Try and get a context - if not, we may have a DSO but no
637 if(!get_context(&hwcrhk_context, &password_context))
639 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
642 /* Everything's fine. */
643 #ifndef OPENSSL_NO_RSA
644 if (hndidx_rsa == -1)
645 hndidx_rsa = RSA_get_ex_new_index(0,
646 "nFast HWCryptoHook RSA key handle",
647 NULL, NULL, hwcrhk_ex_free);
652 DSO_free(hwcrhk_dso);
654 p_hwcrhk_Init = NULL;
655 p_hwcrhk_Finish = NULL;
656 p_hwcrhk_ModExp = NULL;
657 #ifndef OPENSSL_NO_RSA
659 p_hwcrhk_RSALoadKey = NULL;
660 p_hwcrhk_RSAGetPublicKey = NULL;
661 p_hwcrhk_RSAUnloadKey = NULL;
663 p_hwcrhk_ModExpCRT = NULL;
664 p_hwcrhk_RandomBytes = NULL;
668 static int hwcrhk_finish(ENGINE *e)
671 if(hwcrhk_dso == NULL)
673 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
677 release_context(hwcrhk_context);
678 if(!DSO_free(hwcrhk_dso))
680 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
688 p_hwcrhk_Init = NULL;
689 p_hwcrhk_Finish = NULL;
690 p_hwcrhk_ModExp = NULL;
691 #ifndef OPENSSL_NO_RSA
693 p_hwcrhk_RSALoadKey = NULL;
694 p_hwcrhk_RSAGetPublicKey = NULL;
695 p_hwcrhk_RSAUnloadKey = NULL;
697 p_hwcrhk_ModExpCRT = NULL;
698 p_hwcrhk_RandomBytes = NULL;
702 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
708 case HWCRHK_CMD_SO_PATH:
711 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
716 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
719 HWCRHK_LIBNAME = (const char *)p;
721 case ENGINE_CTRL_SET_LOGSTREAM:
725 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
731 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
734 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
736 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
738 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
739 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
740 password_context.password_callback = (pem_password_cb *)f;
741 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
743 case ENGINE_CTRL_SET_USER_INTERFACE:
744 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
745 password_context.ui_method = (UI_METHOD *)p;
746 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
748 case ENGINE_CTRL_SET_CALLBACK_DATA:
749 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
750 password_context.callback_data = p;
751 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
753 /* this enables or disables the "SimpleForkCheck" flag used in the
754 * initialisation structure. */
755 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
756 case HWCRHK_CMD_FORK_CHECK:
757 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
759 hwcrhk_globals.flags |=
760 HWCryptoHook_InitFlags_SimpleForkCheck;
762 hwcrhk_globals.flags &=
763 ~HWCryptoHook_InitFlags_SimpleForkCheck;
764 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
766 /* This will prevent the initialisation function from "installing"
767 * the mutex-handling callbacks, even if they are available from
768 * within the library (or were provided to the library from the
769 * calling application). This is to remove any baggage for
770 * applications not using multithreading. */
771 case ENGINE_CTRL_CHIL_NO_LOCKING:
772 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
773 disable_mutex_callbacks = 1;
774 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
776 case HWCRHK_CMD_THREAD_LOCKING:
777 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
778 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
779 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
782 /* The command isn't understood by this engine */
784 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
785 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
793 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
794 UI_METHOD *ui_method, void *callback_data)
796 #ifndef OPENSSL_NO_RSA
799 EVP_PKEY *res = NULL;
800 #ifndef OPENSSL_NO_RSA
801 HWCryptoHook_MPI e, n;
802 HWCryptoHook_RSAKeyHandle *hptr;
804 #if !defined(OPENSSL_NO_RSA)
805 HWCryptoHook_ErrMsgBuf rmsg;
807 HWCryptoHook_PassphraseContext ppctx;
811 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
812 HWCRHK_R_NOT_INITIALISED);
815 #ifndef OPENSSL_NO_RSA
816 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
819 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
820 ERR_R_MALLOC_FAILURE);
823 ppctx.ui_method = ui_method;
824 ppctx.callback_data = callback_data;
825 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
828 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
829 HWCRHK_R_CHIL_ERROR);
830 ERR_add_error_data(1,rmsg.buf);
835 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
840 #ifndef OPENSSL_NO_RSA
841 rtmp = RSA_new_method(eng);
842 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
845 rtmp->flags |= RSA_FLAG_EXT_PKEY;
848 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
849 != HWCRYPTOHOOK_ERROR_MPISIZE)
851 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
852 ERR_add_error_data(1,rmsg.buf);
856 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
857 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
861 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
863 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
864 HWCRHK_R_CHIL_ERROR);
865 ERR_add_error_data(1,rmsg.buf);
868 rtmp->e->top = e.size / sizeof(BN_ULONG);
870 rtmp->n->top = n.size / sizeof(BN_ULONG);
873 res = EVP_PKEY_new();
874 EVP_PKEY_assign_RSA(res, rtmp);
878 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
879 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
885 #ifndef OPENSSL_NO_RSA
892 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
893 UI_METHOD *ui_method, void *callback_data)
895 EVP_PKEY *res = NULL;
897 #ifndef OPENSSL_NO_RSA
898 res = hwcrhk_load_privkey(eng, key_id,
899 ui_method, callback_data);
905 #ifndef OPENSSL_NO_RSA
910 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
912 res->pkey.rsa = RSA_new();
913 res->pkey.rsa->n = rsa->n;
914 res->pkey.rsa->e = rsa->e;
915 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
920 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
921 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
932 /* A little mod_exp */
933 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
934 const BIGNUM *m, BN_CTX *ctx)
937 HWCryptoHook_ErrMsgBuf rmsg;
938 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
939 we use them directly, plus a little macro magic. We only
940 thing we need to make sure of is that enough space is allocated. */
941 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
944 to_return = 0; /* expect failure */
950 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
953 /* Prepare the params */
954 bn_expand2(r, m->top); /* Check for error !! */
960 /* Perform the operation */
961 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
963 /* Convert the response */
964 r->top = m_r.size / sizeof(BN_ULONG);
969 /* FIXME: When this error is returned, HWCryptoHook is
970 telling us that falling back to software computation
971 might be a good thing. */
972 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
974 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
978 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
980 ERR_add_error_data(1,rmsg.buf);
989 #ifndef OPENSSL_NO_RSA
990 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
993 HWCryptoHook_ErrMsgBuf rmsg;
994 HWCryptoHook_RSAKeyHandle *hptr;
995 int to_return = 0, ret;
999 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
1003 /* This provides support for nForce keys. Since that's opaque data
1004 all we do is provide a handle to the proper key and let HWCryptoHook
1005 take care of the rest. */
1006 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
1009 HWCryptoHook_MPI m_a, m_r;
1013 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1014 HWCRHK_R_MISSING_KEY_COMPONENTS);
1021 /* Prepare the params */
1022 bn_expand2(r, rsa->n->top); /* Check for error !! */
1026 /* Perform the operation */
1027 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
1029 /* Convert the response */
1030 r->top = m_r.size / sizeof(BN_ULONG);
1035 /* FIXME: When this error is returned, HWCryptoHook is
1036 telling us that falling back to software computation
1037 might be a good thing. */
1038 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1040 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1041 HWCRHK_R_REQUEST_FALLBACK);
1045 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1046 HWCRHK_R_REQUEST_FAILED);
1048 ERR_add_error_data(1,rmsg.buf);
1054 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1056 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1058 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1059 HWCRHK_R_MISSING_KEY_COMPONENTS);
1066 /* Prepare the params */
1067 bn_expand2(r, rsa->n->top); /* Check for error !! */
1069 BN2MPI(m_p, rsa->p);
1070 BN2MPI(m_q, rsa->q);
1071 BN2MPI(m_dmp1, rsa->dmp1);
1072 BN2MPI(m_dmq1, rsa->dmq1);
1073 BN2MPI(m_iqmp, rsa->iqmp);
1076 /* Perform the operation */
1077 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1078 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
1080 /* Convert the response */
1081 r->top = m_r.size / sizeof(BN_ULONG);
1086 /* FIXME: When this error is returned, HWCryptoHook is
1087 telling us that falling back to software computation
1088 might be a good thing. */
1089 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1091 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1092 HWCRHK_R_REQUEST_FALLBACK);
1096 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1097 HWCRHK_R_REQUEST_FAILED);
1099 ERR_add_error_data(1,rmsg.buf);
1103 /* If we're here, we must be here with some semblance of success :-) */
1110 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1111 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1112 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1114 return hwcrhk_mod_exp(r, a, p, m, ctx);
1117 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1118 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1119 const BIGNUM *a, const BIGNUM *p,
1120 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1122 return hwcrhk_mod_exp(r, a, p, m, ctx);
1125 /* Random bytes are good */
1126 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1129 HWCryptoHook_ErrMsgBuf rmsg;
1130 int to_return = 0; /* assume failure */
1138 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1142 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1145 /* FIXME: When this error is returned, HWCryptoHook is
1146 telling us that falling back to software computation
1147 might be a good thing. */
1148 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1150 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1151 HWCRHK_R_REQUEST_FALLBACK);
1155 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1156 HWCRHK_R_REQUEST_FAILED);
1158 ERR_add_error_data(1,rmsg.buf);
1166 static int hwcrhk_rand_status(void)
1171 /* This cleans up an RSA KM key, called when ex_data is freed */
1173 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1174 int ind,long argl, void *argp)
1177 HWCryptoHook_ErrMsgBuf rmsg;
1178 #ifndef OPENSSL_NO_RSA
1179 HWCryptoHook_RSAKeyHandle *hptr;
1181 #if !defined(OPENSSL_NO_RSA)
1188 #ifndef OPENSSL_NO_RSA
1189 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1192 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1198 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1199 * these just wrap the POSIX functions and add some logging.
1202 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1203 HWCryptoHook_CallerContext *cactx)
1205 mt->lockid = CRYPTO_get_new_dynlockid();
1206 if (mt->lockid == 0)
1211 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1213 CRYPTO_w_lock(mt->lockid);
1217 void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1219 CRYPTO_w_unlock(mt->lockid);
1222 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1224 CRYPTO_destroy_dynlockid(mt->lockid);
1227 static int hwcrhk_get_pass(const char *prompt_info,
1228 int *len_io, char *buf,
1229 HWCryptoHook_PassphraseContext *ppctx,
1230 HWCryptoHook_CallerContext *cactx)
1232 pem_password_cb *callback = NULL;
1233 void *callback_data = NULL;
1234 UI_METHOD *ui_method = NULL;
1238 if (cactx->ui_method)
1239 ui_method = cactx->ui_method;
1240 if (cactx->password_callback)
1241 callback = cactx->password_callback;
1242 if (cactx->callback_data)
1243 callback_data = cactx->callback_data;
1247 if (ppctx->ui_method)
1249 ui_method = ppctx->ui_method;
1252 if (ppctx->callback_data)
1253 callback_data = ppctx->callback_data;
1255 if (callback == NULL && ui_method == NULL)
1257 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1263 UI *ui = UI_new_method(ui_method);
1267 char *prompt = UI_construct_prompt(ui,
1268 "pass phrase", prompt_info);
1270 ok = UI_add_input_string(ui,prompt,
1271 UI_INPUT_FLAG_DEFAULT_PWD,
1272 buf,0,(*len_io) - 1);
1273 UI_add_user_data(ui, callback_data);
1274 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1281 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1284 *len_io = strlen(buf);
1287 OPENSSL_free(prompt);
1292 *len_io = callback(buf, *len_io, 0, callback_data);
1299 static int hwcrhk_insert_card(const char *prompt_info,
1300 const char *wrong_info,
1301 HWCryptoHook_PassphraseContext *ppctx,
1302 HWCryptoHook_CallerContext *cactx)
1306 void *callback_data = NULL;
1307 UI_METHOD *ui_method = NULL;
1311 if (cactx->ui_method)
1312 ui_method = cactx->ui_method;
1313 if (cactx->callback_data)
1314 callback_data = cactx->callback_data;
1318 if (ppctx->ui_method)
1319 ui_method = ppctx->ui_method;
1320 if (ppctx->callback_data)
1321 callback_data = ppctx->callback_data;
1323 if (ui_method == NULL)
1325 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1326 HWCRHK_R_NO_CALLBACK);
1330 ui = UI_new_method(ui_method);
1338 BIO_snprintf(buf, sizeof(buf)-1,
1339 "Current card: \"%s\"\n", wrong_info);
1340 ok = UI_dup_info_string(ui, buf);
1341 if (ok >= 0 && prompt_info)
1343 BIO_snprintf(buf, sizeof(buf)-1,
1344 "Insert card \"%s\"", prompt_info);
1345 ok = UI_dup_input_boolean(ui, buf,
1346 "\n then hit <enter> or C<enter> to cancel\n",
1347 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1349 UI_add_user_data(ui, callback_data);
1352 ok = UI_process(ui);
1355 if (ok == -2 || (ok >= 0 && answer == 'C'))
1365 static void hwcrhk_log_message(void *logstr, const char *message)
1367 BIO *lstream = NULL;
1369 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1371 lstream=*(BIO **)logstr;
1374 BIO_write(lstream, message, strlen(message));
1376 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1379 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1380 * shared-library. */
1381 #ifdef ENGINE_DYNAMIC_SUPPORT
1382 static int bind_fn(ENGINE *e, const char *id)
1384 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1390 IMPLEMENT_DYNAMIC_CHECK_FN()
1391 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1392 #endif /* ENGINE_DYNAMIC_SUPPORT */
1394 #endif /* !OPENSSL_NO_HW_NCIPHER */
1395 #endif /* !OPENSSL_NO_HW */