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;
536 rmsg.size = sizeof(tempbuf);
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)
806 HWCryptoHook_ErrMsgBuf rmsg;
808 HWCryptoHook_PassphraseContext ppctx;
810 #if !defined(OPENSSL_NO_RSA)
812 rmsg.size = sizeof(tempbuf);
817 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
818 HWCRHK_R_NOT_INITIALISED);
821 #ifndef OPENSSL_NO_RSA
822 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
825 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
826 ERR_R_MALLOC_FAILURE);
829 ppctx.ui_method = ui_method;
830 ppctx.callback_data = callback_data;
831 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
834 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
835 HWCRHK_R_CHIL_ERROR);
836 ERR_add_error_data(1,rmsg.buf);
841 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
846 #ifndef OPENSSL_NO_RSA
847 rtmp = RSA_new_method(eng);
848 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
851 rtmp->flags |= RSA_FLAG_EXT_PKEY;
854 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
855 != HWCRYPTOHOOK_ERROR_MPISIZE)
857 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
858 ERR_add_error_data(1,rmsg.buf);
862 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
863 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
867 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
869 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
870 HWCRHK_R_CHIL_ERROR);
871 ERR_add_error_data(1,rmsg.buf);
874 rtmp->e->top = e.size / sizeof(BN_ULONG);
876 rtmp->n->top = n.size / sizeof(BN_ULONG);
879 res = EVP_PKEY_new();
880 EVP_PKEY_assign_RSA(res, rtmp);
884 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
885 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
891 #ifndef OPENSSL_NO_RSA
898 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
899 UI_METHOD *ui_method, void *callback_data)
901 EVP_PKEY *res = NULL;
903 #ifndef OPENSSL_NO_RSA
904 res = hwcrhk_load_privkey(eng, key_id,
905 ui_method, callback_data);
911 #ifndef OPENSSL_NO_RSA
916 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
918 res->pkey.rsa = RSA_new();
919 res->pkey.rsa->n = rsa->n;
920 res->pkey.rsa->e = rsa->e;
923 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
929 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
930 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
941 /* A little mod_exp */
942 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
943 const BIGNUM *m, BN_CTX *ctx)
946 HWCryptoHook_ErrMsgBuf rmsg;
947 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
948 we use them directly, plus a little macro magic. We only
949 thing we need to make sure of is that enough space is allocated. */
950 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
953 to_return = 0; /* expect failure */
955 rmsg.size = sizeof(tempbuf);
959 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
962 /* Prepare the params */
963 bn_expand2(r, m->top); /* Check for error !! */
969 /* Perform the operation */
970 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
972 /* Convert the response */
973 r->top = m_r.size / sizeof(BN_ULONG);
978 /* FIXME: When this error is returned, HWCryptoHook is
979 telling us that falling back to software computation
980 might be a good thing. */
981 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
983 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
987 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
989 ERR_add_error_data(1,rmsg.buf);
998 #ifndef OPENSSL_NO_RSA
999 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
1002 HWCryptoHook_ErrMsgBuf rmsg;
1003 HWCryptoHook_RSAKeyHandle *hptr;
1004 int to_return = 0, ret;
1007 rmsg.size = sizeof(tempbuf);
1011 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
1015 /* This provides support for nForce keys. Since that's opaque data
1016 all we do is provide a handle to the proper key and let HWCryptoHook
1017 take care of the rest. */
1018 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
1021 HWCryptoHook_MPI m_a, m_r;
1025 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1026 HWCRHK_R_MISSING_KEY_COMPONENTS);
1030 /* Prepare the params */
1031 bn_expand2(r, rsa->n->top); /* Check for error !! */
1035 /* Perform the operation */
1036 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
1038 /* Convert the response */
1039 r->top = m_r.size / sizeof(BN_ULONG);
1044 /* FIXME: When this error is returned, HWCryptoHook is
1045 telling us that falling back to software computation
1046 might be a good thing. */
1047 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1049 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1050 HWCRHK_R_REQUEST_FALLBACK);
1054 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1055 HWCRHK_R_REQUEST_FAILED);
1057 ERR_add_error_data(1,rmsg.buf);
1063 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1065 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1067 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1068 HWCRHK_R_MISSING_KEY_COMPONENTS);
1072 /* Prepare the params */
1073 bn_expand2(r, rsa->n->top); /* Check for error !! */
1075 BN2MPI(m_p, rsa->p);
1076 BN2MPI(m_q, rsa->q);
1077 BN2MPI(m_dmp1, rsa->dmp1);
1078 BN2MPI(m_dmq1, rsa->dmq1);
1079 BN2MPI(m_iqmp, rsa->iqmp);
1082 /* Perform the operation */
1083 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1084 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
1086 /* Convert the response */
1087 r->top = m_r.size / sizeof(BN_ULONG);
1092 /* FIXME: When this error is returned, HWCryptoHook is
1093 telling us that falling back to software computation
1094 might be a good thing. */
1095 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1097 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1098 HWCRHK_R_REQUEST_FALLBACK);
1102 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1103 HWCRHK_R_REQUEST_FAILED);
1105 ERR_add_error_data(1,rmsg.buf);
1109 /* If we're here, we must be here with some semblance of success :-) */
1116 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1117 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1118 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1120 return hwcrhk_mod_exp(r, a, p, m, ctx);
1123 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1124 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1125 const BIGNUM *a, const BIGNUM *p,
1126 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1128 return hwcrhk_mod_exp(r, a, p, m, ctx);
1131 /* Random bytes are good */
1132 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1135 HWCryptoHook_ErrMsgBuf rmsg;
1136 int to_return = 0; /* assume failure */
1140 rmsg.size = sizeof(tempbuf);
1144 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1148 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1151 /* FIXME: When this error is returned, HWCryptoHook is
1152 telling us that falling back to software computation
1153 might be a good thing. */
1154 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1156 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1157 HWCRHK_R_REQUEST_FALLBACK);
1161 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1162 HWCRHK_R_REQUEST_FAILED);
1164 ERR_add_error_data(1,rmsg.buf);
1172 static int hwcrhk_rand_status(void)
1177 /* This cleans up an RSA KM key, called when ex_data is freed */
1179 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1180 int ind,long argl, void *argp)
1183 HWCryptoHook_ErrMsgBuf rmsg;
1184 #ifndef OPENSSL_NO_RSA
1185 HWCryptoHook_RSAKeyHandle *hptr;
1187 #if !defined(OPENSSL_NO_RSA)
1192 rmsg.size = sizeof(tempbuf);
1194 #ifndef OPENSSL_NO_RSA
1195 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1198 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1204 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1205 * these just wrap the POSIX functions and add some logging.
1208 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1209 HWCryptoHook_CallerContext *cactx)
1211 mt->lockid = CRYPTO_get_new_dynlockid();
1212 if (mt->lockid == 0)
1213 return 1; /* failure */
1214 return 0; /* success */
1217 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1219 CRYPTO_w_lock(mt->lockid);
1223 void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1225 CRYPTO_w_unlock(mt->lockid);
1228 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1230 CRYPTO_destroy_dynlockid(mt->lockid);
1233 static int hwcrhk_get_pass(const char *prompt_info,
1234 int *len_io, char *buf,
1235 HWCryptoHook_PassphraseContext *ppctx,
1236 HWCryptoHook_CallerContext *cactx)
1238 pem_password_cb *callback = NULL;
1239 void *callback_data = NULL;
1240 UI_METHOD *ui_method = NULL;
1244 if (cactx->ui_method)
1245 ui_method = cactx->ui_method;
1246 if (cactx->password_callback)
1247 callback = cactx->password_callback;
1248 if (cactx->callback_data)
1249 callback_data = cactx->callback_data;
1253 if (ppctx->ui_method)
1255 ui_method = ppctx->ui_method;
1258 if (ppctx->callback_data)
1259 callback_data = ppctx->callback_data;
1261 if (callback == NULL && ui_method == NULL)
1263 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1269 UI *ui = UI_new_method(ui_method);
1273 char *prompt = UI_construct_prompt(ui,
1274 "pass phrase", prompt_info);
1276 ok = UI_add_input_string(ui,prompt,
1277 UI_INPUT_FLAG_DEFAULT_PWD,
1278 buf,0,(*len_io) - 1);
1279 UI_add_user_data(ui, callback_data);
1280 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1287 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1290 *len_io = strlen(buf);
1293 OPENSSL_free(prompt);
1298 *len_io = callback(buf, *len_io, 0, callback_data);
1305 static int hwcrhk_insert_card(const char *prompt_info,
1306 const char *wrong_info,
1307 HWCryptoHook_PassphraseContext *ppctx,
1308 HWCryptoHook_CallerContext *cactx)
1312 void *callback_data = NULL;
1313 UI_METHOD *ui_method = NULL;
1317 if (cactx->ui_method)
1318 ui_method = cactx->ui_method;
1319 if (cactx->callback_data)
1320 callback_data = cactx->callback_data;
1324 if (ppctx->ui_method)
1325 ui_method = ppctx->ui_method;
1326 if (ppctx->callback_data)
1327 callback_data = ppctx->callback_data;
1329 if (ui_method == NULL)
1331 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1332 HWCRHK_R_NO_CALLBACK);
1336 ui = UI_new_method(ui_method);
1344 BIO_snprintf(buf, sizeof(buf)-1,
1345 "Current card: \"%s\"\n", wrong_info);
1346 ok = UI_dup_info_string(ui, buf);
1347 if (ok >= 0 && prompt_info)
1349 BIO_snprintf(buf, sizeof(buf)-1,
1350 "Insert card \"%s\"", prompt_info);
1351 ok = UI_dup_input_boolean(ui, buf,
1352 "\n then hit <enter> or C<enter> to cancel\n",
1353 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1355 UI_add_user_data(ui, callback_data);
1358 ok = UI_process(ui);
1361 if (ok == -2 || (ok >= 0 && answer == 'C'))
1371 static void hwcrhk_log_message(void *logstr, const char *message)
1373 BIO *lstream = NULL;
1375 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1377 lstream=*(BIO **)logstr;
1380 BIO_write(lstream, message, strlen(message));
1382 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1385 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1386 * shared-library. */
1387 #ifdef ENGINE_DYNAMIC_SUPPORT
1388 static int bind_fn(ENGINE *e, const char *id)
1390 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1396 IMPLEMENT_DYNAMIC_CHECK_FN()
1397 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1398 #endif /* ENGINE_DYNAMIC_SUPPORT */
1400 #endif /* !OPENSSL_NO_HW_NCIPHER */
1401 #endif /* !OPENSSL_NO_HW */