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_BN_mod_exp(e, hwcrhk_mod_exp) ||
421 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
422 !ENGINE_set_init_function(e, hwcrhk_init) ||
423 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
424 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
425 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
426 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
427 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
430 #ifndef OPENSSL_NO_RSA
431 /* We know that the "PKCS1_SSLeay()" functions hook properly
432 * to the cswift-specific mod_exp and mod_exp_crt so we use
433 * those functions. NB: We don't use ENGINE_openssl() or
434 * anything "more generic" because something like the RSAref
435 * code may not hook properly, and if you own one of these
436 * cards then you have the right to do RSA operations on it
438 meth1 = RSA_PKCS1_SSLeay();
439 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
440 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
441 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
442 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
445 #ifndef OPENSSL_NO_DH
446 /* Much the same for Diffie-Hellman */
447 meth2 = DH_OpenSSL();
448 hwcrhk_dh.generate_key = meth2->generate_key;
449 hwcrhk_dh.compute_key = meth2->compute_key;
452 /* Ensure the hwcrhk error handling is set up */
453 hwcrhk_load_error_strings();
457 /* As this is only ever called once, there's no need for locking
458 * (indeed - the lock will already be held by our caller!!!) */
459 ENGINE *ENGINE_ncipher(void)
461 ENGINE *ret = ENGINE_new();
464 if(!bind_helper(ret))
472 /* This is a process-global DSO handle used for loading and unloading
473 * the HWCryptoHook library. NB: This is only set (or unset) during an
474 * init() or finish() call (reference counts permitting) and they're
475 * operating with global locks, so this should be thread-safe
477 static DSO *hwcrhk_dso = NULL;
478 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
479 #ifndef OPENSSL_NO_RSA
480 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
483 /* These are the function pointers that are (un)set when the library has
484 * successfully (un)loaded. */
485 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
486 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
487 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
488 #ifndef OPENSSL_NO_RSA
489 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
491 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
492 #ifndef OPENSSL_NO_RSA
493 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
494 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
495 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
497 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
499 /* Used in the DSO operations. */
500 static const char def_HWCRHK_LIBNAME[] = "nfhwcrhk";
501 static const char *HWCRHK_LIBNAME = def_HWCRHK_LIBNAME;
502 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
503 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
504 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
505 #ifndef OPENSSL_NO_RSA
506 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
508 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
509 #ifndef OPENSSL_NO_RSA
510 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
511 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
512 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
514 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
516 /* HWCryptoHook library functions and mechanics - these are used by the
517 * higher-level functions further down. NB: As and where there's no
518 * error checking, take a look lower down where these functions are
519 * called, the checking and error handling is probably down there. */
521 /* utility function to obtain a context */
522 static int get_context(HWCryptoHook_ContextHandle *hac,
523 HWCryptoHook_CallerContext *cac)
526 HWCryptoHook_ErrMsgBuf rmsg;
531 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
538 /* similarly to release one. */
539 static void release_context(HWCryptoHook_ContextHandle hac)
541 p_hwcrhk_Finish(hac);
544 /* Destructor (complements the "ENGINE_ncipher()" constructor) */
545 static int hwcrhk_destroy(ENGINE *e)
547 hwcrhk_unload_error_strings();
551 /* (de)initialisation functions. */
552 static int hwcrhk_init(ENGINE *e)
554 HWCryptoHook_Init_t *p1;
555 HWCryptoHook_Finish_t *p2;
556 HWCryptoHook_ModExp_t *p3;
557 #ifndef OPENSSL_NO_RSA
558 HWCryptoHook_RSA_t *p4;
559 HWCryptoHook_RSALoadKey_t *p5;
560 HWCryptoHook_RSAGetPublicKey_t *p6;
561 HWCryptoHook_RSAUnloadKey_t *p7;
563 HWCryptoHook_RandomBytes_t *p8;
564 HWCryptoHook_ModExpCRT_t *p9;
566 if(hwcrhk_dso != NULL)
568 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
571 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
572 hwcrhk_dso = DSO_load(NULL, HWCRHK_LIBNAME, NULL, 0);
573 if(hwcrhk_dso == NULL)
575 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
578 if(!(p1 = (HWCryptoHook_Init_t *)
579 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
580 !(p2 = (HWCryptoHook_Finish_t *)
581 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
582 !(p3 = (HWCryptoHook_ModExp_t *)
583 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
584 #ifndef OPENSSL_NO_RSA
585 !(p4 = (HWCryptoHook_RSA_t *)
586 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
587 !(p5 = (HWCryptoHook_RSALoadKey_t *)
588 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
589 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
590 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
591 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
592 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
594 !(p8 = (HWCryptoHook_RandomBytes_t *)
595 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
596 !(p9 = (HWCryptoHook_ModExpCRT_t *)
597 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
599 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
602 /* Copy the pointers */
604 p_hwcrhk_Finish = p2;
605 p_hwcrhk_ModExp = p3;
606 #ifndef OPENSSL_NO_RSA
608 p_hwcrhk_RSALoadKey = p5;
609 p_hwcrhk_RSAGetPublicKey = p6;
610 p_hwcrhk_RSAUnloadKey = p7;
612 p_hwcrhk_RandomBytes = p8;
613 p_hwcrhk_ModExpCRT = p9;
615 /* Check if the application decided to support dynamic locks,
616 and if it does, use them. */
617 if (disable_mutex_callbacks == 0 &&
618 CRYPTO_get_dynlock_create_callback() != NULL &&
619 CRYPTO_get_dynlock_lock_callback() != NULL &&
620 CRYPTO_get_dynlock_destroy_callback() != NULL)
622 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
623 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
624 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
625 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
628 /* Try and get a context - if not, we may have a DSO but no
630 if(!get_context(&hwcrhk_context, &password_context))
632 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
635 /* Everything's fine. */
636 #ifndef OPENSSL_NO_RSA
637 if (hndidx_rsa == -1)
638 hndidx_rsa = RSA_get_ex_new_index(0,
639 "nFast HWCryptoHook RSA key handle",
640 NULL, NULL, hwcrhk_ex_free);
645 DSO_free(hwcrhk_dso);
647 p_hwcrhk_Init = NULL;
648 p_hwcrhk_Finish = NULL;
649 p_hwcrhk_ModExp = NULL;
650 #ifndef OPENSSL_NO_RSA
652 p_hwcrhk_RSALoadKey = NULL;
653 p_hwcrhk_RSAGetPublicKey = NULL;
654 p_hwcrhk_RSAUnloadKey = NULL;
656 p_hwcrhk_ModExpCRT = NULL;
657 p_hwcrhk_RandomBytes = NULL;
661 static int hwcrhk_finish(ENGINE *e)
664 if(hwcrhk_dso == NULL)
666 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
670 release_context(hwcrhk_context);
671 if(!DSO_free(hwcrhk_dso))
673 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
681 p_hwcrhk_Init = NULL;
682 p_hwcrhk_Finish = NULL;
683 p_hwcrhk_ModExp = NULL;
684 #ifndef OPENSSL_NO_RSA
686 p_hwcrhk_RSALoadKey = NULL;
687 p_hwcrhk_RSAGetPublicKey = NULL;
688 p_hwcrhk_RSAUnloadKey = NULL;
690 p_hwcrhk_ModExpCRT = NULL;
691 p_hwcrhk_RandomBytes = NULL;
695 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
701 case HWCRHK_CMD_SO_PATH:
704 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
709 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
712 HWCRHK_LIBNAME = (const char *)p;
714 case ENGINE_CTRL_SET_LOGSTREAM:
718 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
724 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
727 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
729 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
731 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
732 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
733 password_context.password_callback = (pem_password_cb *)f;
734 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
736 case ENGINE_CTRL_SET_USER_INTERFACE:
737 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
738 password_context.ui_method = (UI_METHOD *)p;
739 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
741 case ENGINE_CTRL_SET_CALLBACK_DATA:
742 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
743 password_context.callback_data = p;
744 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
746 /* this enables or disables the "SimpleForkCheck" flag used in the
747 * initialisation structure. */
748 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
749 case HWCRHK_CMD_FORK_CHECK:
750 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
752 hwcrhk_globals.flags |=
753 HWCryptoHook_InitFlags_SimpleForkCheck;
755 hwcrhk_globals.flags &=
756 ~HWCryptoHook_InitFlags_SimpleForkCheck;
757 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
759 /* This will prevent the initialisation function from "installing"
760 * the mutex-handling callbacks, even if they are available from
761 * within the library (or were provided to the library from the
762 * calling application). This is to remove any baggage for
763 * applications not using multithreading. */
764 case ENGINE_CTRL_CHIL_NO_LOCKING:
765 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
766 disable_mutex_callbacks = 1;
767 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
769 case HWCRHK_CMD_THREAD_LOCKING:
770 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
771 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
772 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
775 /* The command isn't understood by this engine */
777 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
778 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
786 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
787 UI_METHOD *ui_method, void *callback_data)
789 #ifndef OPENSSL_NO_RSA
792 EVP_PKEY *res = NULL;
793 #ifndef OPENSSL_NO_RSA
794 HWCryptoHook_MPI e, n;
795 HWCryptoHook_RSAKeyHandle *hptr;
797 #if !defined(OPENSSL_NO_RSA)
798 HWCryptoHook_ErrMsgBuf rmsg;
800 HWCryptoHook_PassphraseContext ppctx;
804 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
805 HWCRHK_R_NOT_INITIALISED);
808 #ifndef OPENSSL_NO_RSA
809 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
812 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
813 ERR_R_MALLOC_FAILURE);
816 ppctx.ui_method = ui_method;
817 ppctx.callback_data = callback_data;
818 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
821 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
822 HWCRHK_R_CHIL_ERROR);
823 ERR_add_error_data(1,rmsg.buf);
828 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
833 #ifndef OPENSSL_NO_RSA
834 rtmp = RSA_new_method(eng);
835 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
838 rtmp->flags |= RSA_FLAG_EXT_PKEY;
841 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
842 != HWCRYPTOHOOK_ERROR_MPISIZE)
844 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
845 ERR_add_error_data(1,rmsg.buf);
849 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
850 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
854 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
856 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
857 HWCRHK_R_CHIL_ERROR);
858 ERR_add_error_data(1,rmsg.buf);
861 rtmp->e->top = e.size / sizeof(BN_ULONG);
863 rtmp->n->top = n.size / sizeof(BN_ULONG);
866 res = EVP_PKEY_new();
867 EVP_PKEY_assign_RSA(res, rtmp);
871 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
872 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
878 #ifndef OPENSSL_NO_RSA
885 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
886 UI_METHOD *ui_method, void *callback_data)
888 EVP_PKEY *res = NULL;
890 #ifndef OPENSSL_NO_RSA
891 res = hwcrhk_load_privkey(eng, key_id,
892 ui_method, callback_data);
898 #ifndef OPENSSL_NO_RSA
903 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
905 res->pkey.rsa = RSA_new();
906 res->pkey.rsa->n = rsa->n;
907 res->pkey.rsa->e = rsa->e;
908 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
913 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
914 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
925 /* A little mod_exp */
926 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
927 const BIGNUM *m, BN_CTX *ctx)
930 HWCryptoHook_ErrMsgBuf rmsg;
931 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
932 we use them directly, plus a little macro magic. We only
933 thing we need to make sure of is that enough space is allocated. */
934 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
937 to_return = 0; /* expect failure */
943 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
946 /* Prepare the params */
947 bn_expand2(r, m->top); /* Check for error !! */
953 /* Perform the operation */
954 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
956 /* Convert the response */
957 r->top = m_r.size / sizeof(BN_ULONG);
962 /* FIXME: When this error is returned, HWCryptoHook is
963 telling us that falling back to software computation
964 might be a good thing. */
965 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
967 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
971 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
973 ERR_add_error_data(1,rmsg.buf);
982 #ifndef OPENSSL_NO_RSA
983 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
986 HWCryptoHook_ErrMsgBuf rmsg;
987 HWCryptoHook_RSAKeyHandle *hptr;
988 int to_return = 0, ret;
992 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
996 /* This provides support for nForce keys. Since that's opaque data
997 all we do is provide a handle to the proper key and let HWCryptoHook
998 take care of the rest. */
999 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
1002 HWCryptoHook_MPI m_a, m_r;
1006 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1007 HWCRHK_R_MISSING_KEY_COMPONENTS);
1014 /* Prepare the params */
1015 bn_expand2(r, rsa->n->top); /* Check for error !! */
1019 /* Perform the operation */
1020 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
1022 /* Convert the response */
1023 r->top = m_r.size / sizeof(BN_ULONG);
1028 /* FIXME: When this error is returned, HWCryptoHook is
1029 telling us that falling back to software computation
1030 might be a good thing. */
1031 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1033 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1034 HWCRHK_R_REQUEST_FALLBACK);
1038 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1039 HWCRHK_R_REQUEST_FAILED);
1041 ERR_add_error_data(1,rmsg.buf);
1047 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1049 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1051 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1052 HWCRHK_R_MISSING_KEY_COMPONENTS);
1059 /* Prepare the params */
1060 bn_expand2(r, rsa->n->top); /* Check for error !! */
1062 BN2MPI(m_p, rsa->p);
1063 BN2MPI(m_q, rsa->q);
1064 BN2MPI(m_dmp1, rsa->dmp1);
1065 BN2MPI(m_dmq1, rsa->dmq1);
1066 BN2MPI(m_iqmp, rsa->iqmp);
1069 /* Perform the operation */
1070 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1071 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
1073 /* Convert the response */
1074 r->top = m_r.size / sizeof(BN_ULONG);
1079 /* FIXME: When this error is returned, HWCryptoHook is
1080 telling us that falling back to software computation
1081 might be a good thing. */
1082 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1084 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1085 HWCRHK_R_REQUEST_FALLBACK);
1089 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1090 HWCRHK_R_REQUEST_FAILED);
1092 ERR_add_error_data(1,rmsg.buf);
1096 /* If we're here, we must be here with some semblance of success :-) */
1103 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1104 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1105 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1107 return hwcrhk_mod_exp(r, a, p, m, ctx);
1110 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1111 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1112 const BIGNUM *a, const BIGNUM *p,
1113 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1115 return hwcrhk_mod_exp(r, a, p, m, ctx);
1118 /* Random bytes are good */
1119 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1122 HWCryptoHook_ErrMsgBuf rmsg;
1123 int to_return = 0; /* assume failure */
1131 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1135 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1138 /* FIXME: When this error is returned, HWCryptoHook is
1139 telling us that falling back to software computation
1140 might be a good thing. */
1141 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1143 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1144 HWCRHK_R_REQUEST_FALLBACK);
1148 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1149 HWCRHK_R_REQUEST_FAILED);
1151 ERR_add_error_data(1,rmsg.buf);
1159 static int hwcrhk_rand_status(void)
1164 /* This cleans up an RSA KM key, called when ex_data is freed */
1166 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1167 int ind,long argl, void *argp)
1170 HWCryptoHook_ErrMsgBuf rmsg;
1171 #ifndef OPENSSL_NO_RSA
1172 HWCryptoHook_RSAKeyHandle *hptr;
1174 #if !defined(OPENSSL_NO_RSA)
1181 #ifndef OPENSSL_NO_RSA
1182 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1185 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1191 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1192 * these just wrap the POSIX functions and add some logging.
1195 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1196 HWCryptoHook_CallerContext *cactx)
1198 mt->lockid = CRYPTO_get_new_dynlockid();
1199 if (mt->lockid == 0)
1204 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1206 CRYPTO_w_lock(mt->lockid);
1210 void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1212 CRYPTO_w_unlock(mt->lockid);
1215 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1217 CRYPTO_destroy_dynlockid(mt->lockid);
1220 static int hwcrhk_get_pass(const char *prompt_info,
1221 int *len_io, char *buf,
1222 HWCryptoHook_PassphraseContext *ppctx,
1223 HWCryptoHook_CallerContext *cactx)
1225 pem_password_cb *callback = NULL;
1226 void *callback_data = NULL;
1227 UI_METHOD *ui_method = NULL;
1231 if (cactx->ui_method)
1232 ui_method = cactx->ui_method;
1233 if (cactx->password_callback)
1234 callback = cactx->password_callback;
1235 if (cactx->callback_data)
1236 callback_data = cactx->callback_data;
1240 if (ppctx->ui_method)
1242 ui_method = ppctx->ui_method;
1245 if (ppctx->callback_data)
1246 callback_data = ppctx->callback_data;
1248 if (callback == NULL && ui_method == NULL)
1250 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1256 UI *ui = UI_new_method(ui_method);
1260 char *prompt = UI_construct_prompt(ui,
1261 "pass phrase", prompt_info);
1263 ok = UI_add_input_string(ui,prompt,
1264 UI_INPUT_FLAG_DEFAULT_PWD,
1265 buf,0,(*len_io) - 1);
1266 UI_add_user_data(ui, callback_data);
1267 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1274 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1277 *len_io = strlen(buf);
1280 OPENSSL_free(prompt);
1285 *len_io = callback(buf, *len_io, 0, callback_data);
1292 static int hwcrhk_insert_card(const char *prompt_info,
1293 const char *wrong_info,
1294 HWCryptoHook_PassphraseContext *ppctx,
1295 HWCryptoHook_CallerContext *cactx)
1299 void *callback_data = NULL;
1300 UI_METHOD *ui_method = NULL;
1304 if (cactx->ui_method)
1305 ui_method = cactx->ui_method;
1306 if (cactx->callback_data)
1307 callback_data = cactx->callback_data;
1311 if (ppctx->ui_method)
1312 ui_method = ppctx->ui_method;
1313 if (ppctx->callback_data)
1314 callback_data = ppctx->callback_data;
1316 if (ui_method == NULL)
1318 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1319 HWCRHK_R_NO_CALLBACK);
1323 ui = UI_new_method(ui_method);
1331 BIO_snprintf(buf, sizeof(buf)-1,
1332 "Current card: \"%s\"\n", wrong_info);
1333 ok = UI_dup_info_string(ui, buf);
1334 if (ok >= 0 && prompt_info)
1336 BIO_snprintf(buf, sizeof(buf)-1,
1337 "Insert card \"%s\"", prompt_info);
1338 ok = UI_dup_input_boolean(ui, buf,
1339 "\n then hit <enter> or C<enter> to cancel\n",
1340 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1342 UI_add_user_data(ui, callback_data);
1345 ok = UI_process(ui);
1348 if (ok == -2 || (ok >= 0 && answer == 'C'))
1358 static void hwcrhk_log_message(void *logstr, const char *message)
1360 BIO *lstream = NULL;
1362 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1364 lstream=*(BIO **)logstr;
1367 BIO_write(lstream, message, strlen(message));
1369 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1372 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1373 * shared-library. */
1374 #ifdef ENGINE_DYNAMIC_SUPPORT
1375 static int bind_fn(ENGINE *e, const char *id)
1377 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1383 IMPLEMENT_DYNAMIC_CHECK_FN()
1384 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1385 #endif /* ENGINE_DYNAMIC_SUPPORT */
1387 #endif /* !OPENSSL_NO_HW_NCIPHER */
1388 #endif /* !OPENSSL_NO_HW */