1 /* crypto/engine/e_chil.c -*- mode: C; c-file-style: "eay" -*- */
2 /* Written by Richard Levitte (richard@levitte.org), Geoff Thorpe
3 * (geoff@geoffthorpe.net) and Dr Stephen N Henson (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>
64 #include <openssl/dso.h>
65 #include <openssl/engine.h>
66 #include <openssl/ui.h>
67 #include <openssl/rand.h>
68 #ifndef OPENSSL_NO_RSA
69 #include <openssl/rsa.h>
72 #include <openssl/dh.h>
74 #include <openssl/bn.h>
77 #ifndef OPENSSL_NO_HW_CHIL
79 /* Attribution notice: nCipher have said several times that it's OK for
80 * us to implement a general interface to their boxes, and recently declared
81 * their HWCryptoHook to be public, and therefore available for us to use.
84 * The hwcryptohook.h included here is from May 2000.
88 #include "hwcryptohook.h"
90 #include "vendor_defns/hwcryptohook.h"
93 #define HWCRHK_LIB_NAME "CHIL engine"
94 #include "e_chil_err.c"
96 static int hwcrhk_destroy(ENGINE
*e
);
97 static int hwcrhk_init(ENGINE
*e
);
98 static int hwcrhk_finish(ENGINE
*e
);
99 static int hwcrhk_ctrl(ENGINE
*e
, int cmd
, long i
, void *p
, void (*f
)(void));
101 /* Functions to handle mutexes */
102 static int hwcrhk_mutex_init(HWCryptoHook_Mutex
*, HWCryptoHook_CallerContext
*);
103 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex
*);
104 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex
*);
105 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex
*);
108 static int hwcrhk_mod_exp(BIGNUM
*r
, const BIGNUM
*a
, const BIGNUM
*p
,
109 const BIGNUM
*m
, BN_CTX
*ctx
);
111 #ifndef OPENSSL_NO_RSA
113 static int hwcrhk_rsa_mod_exp(BIGNUM
*r
, const BIGNUM
*I
, RSA
*rsa
, BN_CTX
*ctx
);
115 #ifndef OPENSSL_NO_RSA
116 /* This function is aliased to mod_exp (with the mont stuff dropped). */
117 static int hwcrhk_mod_exp_mont(BIGNUM
*r
, const BIGNUM
*a
, const BIGNUM
*p
,
118 const BIGNUM
*m
, BN_CTX
*ctx
, BN_MONT_CTX
*m_ctx
);
121 #ifndef OPENSSL_NO_DH
123 /* This function is alised to mod_exp (with the DH and mont dropped). */
124 static int hwcrhk_mod_exp_dh(const DH
*dh
, BIGNUM
*r
,
125 const BIGNUM
*a
, const BIGNUM
*p
,
126 const BIGNUM
*m
, BN_CTX
*ctx
, BN_MONT_CTX
*m_ctx
);
130 static int hwcrhk_rand_bytes(unsigned char *buf
, int num
);
131 static int hwcrhk_rand_status(void);
134 static EVP_PKEY
*hwcrhk_load_privkey(ENGINE
*eng
, const char *key_id
,
135 UI_METHOD
*ui_method
, void *callback_data
);
136 static EVP_PKEY
*hwcrhk_load_pubkey(ENGINE
*eng
, const char *key_id
,
137 UI_METHOD
*ui_method
, void *callback_data
);
138 #ifndef OPENSSL_NO_RSA
139 static void hwcrhk_ex_free(void *obj
, void *item
, CRYPTO_EX_DATA
*ad
,
140 int ind
,long argl
, void *argp
);
143 /* Interaction stuff */
144 static int hwcrhk_insert_card(const char *prompt_info
,
145 const char *wrong_info
,
146 HWCryptoHook_PassphraseContext
*ppctx
,
147 HWCryptoHook_CallerContext
*cactx
);
148 static int hwcrhk_get_pass(const char *prompt_info
,
149 int *len_io
, char *buf
,
150 HWCryptoHook_PassphraseContext
*ppctx
,
151 HWCryptoHook_CallerContext
*cactx
);
152 static void hwcrhk_log_message(void *logstr
, const char *message
);
154 /* The definitions for control commands specific to this engine */
155 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
156 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
157 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
158 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
159 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
160 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns
[] = {
163 "Specifies the path to the 'hwcrhk' shared library",
164 ENGINE_CMD_FLAG_STRING
},
165 {HWCRHK_CMD_FORK_CHECK
,
167 "Turns fork() checking on or off (boolean)",
168 ENGINE_CMD_FLAG_NUMERIC
},
169 {HWCRHK_CMD_THREAD_LOCKING
,
171 "Turns thread-safe locking on or off (boolean)",
172 ENGINE_CMD_FLAG_NUMERIC
},
173 {HWCRHK_CMD_SET_USER_INTERFACE
,
174 "SET_USER_INTERFACE",
175 "Set the global user interface (internal)",
176 ENGINE_CMD_FLAG_INTERNAL
},
177 {HWCRHK_CMD_SET_CALLBACK_DATA
,
179 "Set the global user interface extra data (internal)",
180 ENGINE_CMD_FLAG_INTERNAL
},
184 #ifndef OPENSSL_NO_RSA
185 /* Our internal RSA_METHOD that we provide pointers to */
186 static RSA_METHOD hwcrhk_rsa
=
205 #ifndef OPENSSL_NO_DH
206 /* Our internal DH_METHOD that we provide pointers to */
207 static DH_METHOD hwcrhk_dh
=
221 static RAND_METHOD hwcrhk_rand
=
223 /* "CHIL RAND method", */
232 /* Constants used when creating the ENGINE */
233 static const char *engine_hwcrhk_id
= "chil";
234 static const char *engine_hwcrhk_name
= "CHIL hardware engine support";
236 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
237 /* Compatibility hack, the dynamic library uses this form in the path */
238 static const char *engine_hwcrhk_id_alt
= "ncipher";
241 /* Internal stuff for HWCryptoHook */
243 /* Some structures needed for proper use of thread locks */
244 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
245 into HWCryptoHook_Mutex */
246 struct HWCryptoHook_MutexValue
251 /* hwcryptohook.h has some typedefs that turn
252 struct HWCryptoHook_PassphraseContextValue
253 into HWCryptoHook_PassphraseContext */
254 struct HWCryptoHook_PassphraseContextValue
256 UI_METHOD
*ui_method
;
260 /* hwcryptohook.h has some typedefs that turn
261 struct HWCryptoHook_CallerContextValue
262 into HWCryptoHook_CallerContext */
263 struct HWCryptoHook_CallerContextValue
265 pem_password_cb
*password_callback
; /* Deprecated! Only present for
266 backward compatibility! */
267 UI_METHOD
*ui_method
;
271 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
272 BIGNUM's, so lets define a couple of conversion macros */
273 #define BN2MPI(mp, bn) \
274 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
275 #define MPI2BN(bn, mp) \
276 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
278 static BIO
*logstream
= NULL
;
279 static int disable_mutex_callbacks
= 0;
281 /* One might wonder why these are needed, since one can pass down at least
282 a UI_METHOD and a pointer to callback data to the key-loading functions.
283 The thing is that the ModExp and RSAImmed functions can load keys as well,
284 if the data they get is in a special, nCipher-defined format (hint: if you
285 look at the private exponent of the RSA data as a string, you'll see this
286 string: "nCipher KM tool key id", followed by some bytes, followed a key
287 identity string, followed by more bytes. This happens when you use "embed"
288 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
289 any passphrase or caller context, and our functions can't really take any
290 callback data either. Still, the "insert_card" and "get_passphrase"
291 callbacks may be called down the line, and will need to know what user
292 interface callbacks to call, and having callback data from the application
293 may be a nice thing as well, so we need to keep track of that globally. */
294 static HWCryptoHook_CallerContext password_context
= { NULL
, NULL
, NULL
};
296 /* Stuff to pass to the HWCryptoHook library */
297 static HWCryptoHook_InitInfo hwcrhk_globals
= {
298 HWCryptoHook_InitFlags_SimpleForkCheck
, /* Flags */
299 &logstream
, /* logstream */
300 sizeof(BN_ULONG
), /* limbsize */
301 0, /* mslimb first: false for BNs */
302 -1, /* msbyte first: use native */
303 0, /* Max mutexes, 0 = no small limit */
304 0, /* Max simultaneous, 0 = default */
306 /* The next few are mutex stuff: we write wrapper functions
307 around the OS mutex functions. We initialise them to 0
308 here, and change that to actual function pointers in hwcrhk_init()
309 if dynamic locks are supported (that is, if the application
310 programmer has made sure of setting up callbacks bafore starting
311 this engine) *and* if disable_mutex_callbacks hasn't been set by
312 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
313 sizeof(HWCryptoHook_Mutex
),
319 /* The next few are condvar stuff: we write wrapper functions
320 round the OS functions. Currently not implemented and not
321 and absolute necessity even in threaded programs, therefore
322 0'ed. Will hopefully be implemented some day, since it
323 enhances the efficiency of HWCryptoHook. */
324 0, /* sizeof(HWCryptoHook_CondVar), */
325 0, /* hwcrhk_cv_init, */
326 0, /* hwcrhk_cv_wait, */
327 0, /* hwcrhk_cv_signal, */
328 0, /* hwcrhk_cv_broadcast, */
329 0, /* hwcrhk_cv_destroy, */
331 hwcrhk_get_pass
, /* pass phrase */
332 hwcrhk_insert_card
, /* insert a card */
333 hwcrhk_log_message
/* Log message */
337 /* Now, to our own code */
339 /* This internal function is used by ENGINE_chil() and possibly by the
340 * "dynamic" ENGINE support too */
341 static int bind_helper(ENGINE
*e
)
343 #ifndef OPENSSL_NO_RSA
344 const RSA_METHOD
*meth1
;
346 #ifndef OPENSSL_NO_DH
347 const DH_METHOD
*meth2
;
349 if(!ENGINE_set_id(e
, engine_hwcrhk_id
) ||
350 !ENGINE_set_name(e
, engine_hwcrhk_name
) ||
351 #ifndef OPENSSL_NO_RSA
352 !ENGINE_set_RSA(e
, &hwcrhk_rsa
) ||
354 #ifndef OPENSSL_NO_DH
355 !ENGINE_set_DH(e
, &hwcrhk_dh
) ||
357 !ENGINE_set_RAND(e
, &hwcrhk_rand
) ||
358 !ENGINE_set_destroy_function(e
, hwcrhk_destroy
) ||
359 !ENGINE_set_init_function(e
, hwcrhk_init
) ||
360 !ENGINE_set_finish_function(e
, hwcrhk_finish
) ||
361 !ENGINE_set_ctrl_function(e
, hwcrhk_ctrl
) ||
362 !ENGINE_set_load_privkey_function(e
, hwcrhk_load_privkey
) ||
363 !ENGINE_set_load_pubkey_function(e
, hwcrhk_load_pubkey
) ||
364 !ENGINE_set_cmd_defns(e
, hwcrhk_cmd_defns
))
367 #ifndef OPENSSL_NO_RSA
368 /* We know that the "PKCS1_SSLeay()" functions hook properly
369 * to the cswift-specific mod_exp and mod_exp_crt so we use
370 * those functions. NB: We don't use ENGINE_openssl() or
371 * anything "more generic" because something like the RSAref
372 * code may not hook properly, and if you own one of these
373 * cards then you have the right to do RSA operations on it
375 meth1
= RSA_PKCS1_SSLeay();
376 hwcrhk_rsa
.rsa_pub_enc
= meth1
->rsa_pub_enc
;
377 hwcrhk_rsa
.rsa_pub_dec
= meth1
->rsa_pub_dec
;
378 hwcrhk_rsa
.rsa_priv_enc
= meth1
->rsa_priv_enc
;
379 hwcrhk_rsa
.rsa_priv_dec
= meth1
->rsa_priv_dec
;
382 #ifndef OPENSSL_NO_DH
383 /* Much the same for Diffie-Hellman */
384 meth2
= DH_OpenSSL();
385 hwcrhk_dh
.generate_key
= meth2
->generate_key
;
386 hwcrhk_dh
.compute_key
= meth2
->compute_key
;
389 /* Ensure the hwcrhk error handling is set up */
390 ERR_load_HWCRHK_strings();
394 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
395 static ENGINE
*engine_chil(void)
397 ENGINE
*ret
= ENGINE_new();
400 if(!bind_helper(ret
))
408 void ENGINE_load_chil(void)
410 /* Copied from eng_[openssl|dyn].c */
411 ENGINE
*toadd
= engine_chil();
419 /* This is a process-global DSO handle used for loading and unloading
420 * the HWCryptoHook library. NB: This is only set (or unset) during an
421 * init() or finish() call (reference counts permitting) and they're
422 * operating with global locks, so this should be thread-safe
424 static DSO
*hwcrhk_dso
= NULL
;
425 static HWCryptoHook_ContextHandle hwcrhk_context
= 0;
426 #ifndef OPENSSL_NO_RSA
427 static int hndidx_rsa
= -1; /* Index for KM handle. Not really used yet. */
430 /* These are the function pointers that are (un)set when the library has
431 * successfully (un)loaded. */
432 static HWCryptoHook_Init_t
*p_hwcrhk_Init
= NULL
;
433 static HWCryptoHook_Finish_t
*p_hwcrhk_Finish
= NULL
;
434 static HWCryptoHook_ModExp_t
*p_hwcrhk_ModExp
= NULL
;
435 #ifndef OPENSSL_NO_RSA
436 static HWCryptoHook_RSA_t
*p_hwcrhk_RSA
= NULL
;
438 static HWCryptoHook_RandomBytes_t
*p_hwcrhk_RandomBytes
= NULL
;
439 #ifndef OPENSSL_NO_RSA
440 static HWCryptoHook_RSALoadKey_t
*p_hwcrhk_RSALoadKey
= NULL
;
441 static HWCryptoHook_RSAGetPublicKey_t
*p_hwcrhk_RSAGetPublicKey
= NULL
;
442 static HWCryptoHook_RSAUnloadKey_t
*p_hwcrhk_RSAUnloadKey
= NULL
;
444 static HWCryptoHook_ModExpCRT_t
*p_hwcrhk_ModExpCRT
= NULL
;
446 /* Used in the DSO operations. */
447 static const char *HWCRHK_LIBNAME
= NULL
;
448 static void free_HWCRHK_LIBNAME(void)
451 OPENSSL_free((void*)HWCRHK_LIBNAME
);
452 HWCRHK_LIBNAME
= NULL
;
454 static const char *get_HWCRHK_LIBNAME(void)
457 return HWCRHK_LIBNAME
;
460 static long set_HWCRHK_LIBNAME(const char *name
)
462 free_HWCRHK_LIBNAME();
463 return (((HWCRHK_LIBNAME
= BUF_strdup(name
)) != NULL
) ? 1 : 0);
465 static const char *n_hwcrhk_Init
= "HWCryptoHook_Init";
466 static const char *n_hwcrhk_Finish
= "HWCryptoHook_Finish";
467 static const char *n_hwcrhk_ModExp
= "HWCryptoHook_ModExp";
468 #ifndef OPENSSL_NO_RSA
469 static const char *n_hwcrhk_RSA
= "HWCryptoHook_RSA";
471 static const char *n_hwcrhk_RandomBytes
= "HWCryptoHook_RandomBytes";
472 #ifndef OPENSSL_NO_RSA
473 static const char *n_hwcrhk_RSALoadKey
= "HWCryptoHook_RSALoadKey";
474 static const char *n_hwcrhk_RSAGetPublicKey
= "HWCryptoHook_RSAGetPublicKey";
475 static const char *n_hwcrhk_RSAUnloadKey
= "HWCryptoHook_RSAUnloadKey";
477 static const char *n_hwcrhk_ModExpCRT
= "HWCryptoHook_ModExpCRT";
479 /* HWCryptoHook library functions and mechanics - these are used by the
480 * higher-level functions further down. NB: As and where there's no
481 * error checking, take a look lower down where these functions are
482 * called, the checking and error handling is probably down there. */
484 /* utility function to obtain a context */
485 static int get_context(HWCryptoHook_ContextHandle
*hac
,
486 HWCryptoHook_CallerContext
*cac
)
489 HWCryptoHook_ErrMsgBuf rmsg
;
492 rmsg
.size
= sizeof(tempbuf
);
494 *hac
= p_hwcrhk_Init(&hwcrhk_globals
, sizeof(hwcrhk_globals
), &rmsg
,
501 /* similarly to release one. */
502 static void release_context(HWCryptoHook_ContextHandle hac
)
504 p_hwcrhk_Finish(hac
);
507 /* Destructor (complements the "ENGINE_chil()" constructor) */
508 static int hwcrhk_destroy(ENGINE
*e
)
510 free_HWCRHK_LIBNAME();
511 ERR_unload_HWCRHK_strings();
515 /* (de)initialisation functions. */
516 static int hwcrhk_init(ENGINE
*e
)
518 HWCryptoHook_Init_t
*p1
;
519 HWCryptoHook_Finish_t
*p2
;
520 HWCryptoHook_ModExp_t
*p3
;
521 #ifndef OPENSSL_NO_RSA
522 HWCryptoHook_RSA_t
*p4
;
523 HWCryptoHook_RSALoadKey_t
*p5
;
524 HWCryptoHook_RSAGetPublicKey_t
*p6
;
525 HWCryptoHook_RSAUnloadKey_t
*p7
;
527 HWCryptoHook_RandomBytes_t
*p8
;
528 HWCryptoHook_ModExpCRT_t
*p9
;
530 if(hwcrhk_dso
!= NULL
)
532 HWCRHKerr(HWCRHK_F_HWCRHK_INIT
,HWCRHK_R_ALREADY_LOADED
);
535 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
536 hwcrhk_dso
= DSO_load(NULL
, get_HWCRHK_LIBNAME(), NULL
, 0);
537 if(hwcrhk_dso
== NULL
)
539 HWCRHKerr(HWCRHK_F_HWCRHK_INIT
,HWCRHK_R_DSO_FAILURE
);
542 if(!(p1
= (HWCryptoHook_Init_t
*)
543 DSO_bind_func(hwcrhk_dso
, n_hwcrhk_Init
)) ||
544 !(p2
= (HWCryptoHook_Finish_t
*)
545 DSO_bind_func(hwcrhk_dso
, n_hwcrhk_Finish
)) ||
546 !(p3
= (HWCryptoHook_ModExp_t
*)
547 DSO_bind_func(hwcrhk_dso
, n_hwcrhk_ModExp
)) ||
548 #ifndef OPENSSL_NO_RSA
549 !(p4
= (HWCryptoHook_RSA_t
*)
550 DSO_bind_func(hwcrhk_dso
, n_hwcrhk_RSA
)) ||
551 !(p5
= (HWCryptoHook_RSALoadKey_t
*)
552 DSO_bind_func(hwcrhk_dso
, n_hwcrhk_RSALoadKey
)) ||
553 !(p6
= (HWCryptoHook_RSAGetPublicKey_t
*)
554 DSO_bind_func(hwcrhk_dso
, n_hwcrhk_RSAGetPublicKey
)) ||
555 !(p7
= (HWCryptoHook_RSAUnloadKey_t
*)
556 DSO_bind_func(hwcrhk_dso
, n_hwcrhk_RSAUnloadKey
)) ||
558 !(p8
= (HWCryptoHook_RandomBytes_t
*)
559 DSO_bind_func(hwcrhk_dso
, n_hwcrhk_RandomBytes
)) ||
560 !(p9
= (HWCryptoHook_ModExpCRT_t
*)
561 DSO_bind_func(hwcrhk_dso
, n_hwcrhk_ModExpCRT
)))
563 HWCRHKerr(HWCRHK_F_HWCRHK_INIT
,HWCRHK_R_DSO_FAILURE
);
566 /* Copy the pointers */
568 p_hwcrhk_Finish
= p2
;
569 p_hwcrhk_ModExp
= p3
;
570 #ifndef OPENSSL_NO_RSA
572 p_hwcrhk_RSALoadKey
= p5
;
573 p_hwcrhk_RSAGetPublicKey
= p6
;
574 p_hwcrhk_RSAUnloadKey
= p7
;
576 p_hwcrhk_RandomBytes
= p8
;
577 p_hwcrhk_ModExpCRT
= p9
;
579 /* Check if the application decided to support dynamic locks,
580 and if it does, use them. */
581 if (disable_mutex_callbacks
== 0)
583 if (CRYPTO_get_dynlock_create_callback() != NULL
&&
584 CRYPTO_get_dynlock_lock_callback() != NULL
&&
585 CRYPTO_get_dynlock_destroy_callback() != NULL
)
587 hwcrhk_globals
.mutex_init
= hwcrhk_mutex_init
;
588 hwcrhk_globals
.mutex_acquire
= hwcrhk_mutex_lock
;
589 hwcrhk_globals
.mutex_release
= hwcrhk_mutex_unlock
;
590 hwcrhk_globals
.mutex_destroy
= hwcrhk_mutex_destroy
;
592 else if (CRYPTO_get_locking_callback() != NULL
)
594 HWCRHKerr(HWCRHK_F_HWCRHK_INIT
,HWCRHK_R_LOCKING_MISSING
);
595 ERR_add_error_data(1,"You HAVE to add dynamic locking callbacks via CRYPTO_set_dynlock_{create,lock,destroy}_callback()");
600 /* Try and get a context - if not, we may have a DSO but no
602 if(!get_context(&hwcrhk_context
, &password_context
))
604 HWCRHKerr(HWCRHK_F_HWCRHK_INIT
,HWCRHK_R_UNIT_FAILURE
);
607 /* Everything's fine. */
608 #ifndef OPENSSL_NO_RSA
609 if (hndidx_rsa
== -1)
610 hndidx_rsa
= RSA_get_ex_new_index(0,
611 "nFast HWCryptoHook RSA key handle",
612 NULL
, NULL
, hwcrhk_ex_free
);
617 DSO_free(hwcrhk_dso
);
619 p_hwcrhk_Init
= NULL
;
620 p_hwcrhk_Finish
= NULL
;
621 p_hwcrhk_ModExp
= NULL
;
622 #ifndef OPENSSL_NO_RSA
624 p_hwcrhk_RSALoadKey
= NULL
;
625 p_hwcrhk_RSAGetPublicKey
= NULL
;
626 p_hwcrhk_RSAUnloadKey
= NULL
;
628 p_hwcrhk_ModExpCRT
= NULL
;
629 p_hwcrhk_RandomBytes
= NULL
;
633 static int hwcrhk_finish(ENGINE
*e
)
636 free_HWCRHK_LIBNAME();
637 if(hwcrhk_dso
== NULL
)
639 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH
,HWCRHK_R_NOT_LOADED
);
643 release_context(hwcrhk_context
);
644 if(!DSO_free(hwcrhk_dso
))
646 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH
,HWCRHK_R_DSO_FAILURE
);
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_ctrl(ENGINE
*e
, int cmd
, long i
, void *p
, void (*f
)(void))
674 case HWCRHK_CMD_SO_PATH
:
677 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL
,HWCRHK_R_ALREADY_LOADED
);
682 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL
,ERR_R_PASSED_NULL_PARAMETER
);
685 return set_HWCRHK_LIBNAME((const char *)p
);
686 case ENGINE_CTRL_SET_LOGSTREAM
:
690 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE
);
696 if (CRYPTO_add(&bio
->references
,1,CRYPTO_LOCK_BIO
) > 1)
699 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL
,HWCRHK_R_BIO_WAS_FREED
);
701 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE
);
703 case ENGINE_CTRL_SET_PASSWORD_CALLBACK
:
704 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE
);
705 password_context
.password_callback
= (pem_password_cb
*)f
;
706 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE
);
708 case ENGINE_CTRL_SET_USER_INTERFACE
:
709 case HWCRHK_CMD_SET_USER_INTERFACE
:
710 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE
);
711 password_context
.ui_method
= (UI_METHOD
*)p
;
712 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE
);
714 case ENGINE_CTRL_SET_CALLBACK_DATA
:
715 case HWCRHK_CMD_SET_CALLBACK_DATA
:
716 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE
);
717 password_context
.callback_data
= p
;
718 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE
);
720 /* this enables or disables the "SimpleForkCheck" flag used in the
721 * initialisation structure. */
722 case ENGINE_CTRL_CHIL_SET_FORKCHECK
:
723 case HWCRHK_CMD_FORK_CHECK
:
724 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE
);
726 hwcrhk_globals
.flags
|=
727 HWCryptoHook_InitFlags_SimpleForkCheck
;
729 hwcrhk_globals
.flags
&=
730 ~HWCryptoHook_InitFlags_SimpleForkCheck
;
731 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE
);
733 /* This will prevent the initialisation function from "installing"
734 * the mutex-handling callbacks, even if they are available from
735 * within the library (or were provided to the library from the
736 * calling application). This is to remove any baggage for
737 * applications not using multithreading. */
738 case ENGINE_CTRL_CHIL_NO_LOCKING
:
739 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE
);
740 disable_mutex_callbacks
= 1;
741 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE
);
743 case HWCRHK_CMD_THREAD_LOCKING
:
744 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE
);
745 disable_mutex_callbacks
= ((i
== 0) ? 0 : 1);
746 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE
);
749 /* The command isn't understood by this engine */
751 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL
,
752 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED
);
760 static EVP_PKEY
*hwcrhk_load_privkey(ENGINE
*eng
, const char *key_id
,
761 UI_METHOD
*ui_method
, void *callback_data
)
763 #ifndef OPENSSL_NO_RSA
766 EVP_PKEY
*res
= NULL
;
767 #ifndef OPENSSL_NO_RSA
768 HWCryptoHook_MPI e
, n
;
769 HWCryptoHook_RSAKeyHandle
*hptr
;
771 #if !defined(OPENSSL_NO_RSA)
773 HWCryptoHook_ErrMsgBuf rmsg
;
774 HWCryptoHook_PassphraseContext ppctx
;
777 #if !defined(OPENSSL_NO_RSA)
779 rmsg
.size
= sizeof(tempbuf
);
784 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY
,
785 HWCRHK_R_NOT_INITIALISED
);
788 #ifndef OPENSSL_NO_RSA
789 hptr
= OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle
));
792 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY
,
793 ERR_R_MALLOC_FAILURE
);
796 ppctx
.ui_method
= ui_method
;
797 ppctx
.callback_data
= callback_data
;
798 if (p_hwcrhk_RSALoadKey(hwcrhk_context
, key_id
, hptr
,
801 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY
,
802 HWCRHK_R_CHIL_ERROR
);
803 ERR_add_error_data(1,rmsg
.buf
);
808 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY
,
813 #ifndef OPENSSL_NO_RSA
814 rtmp
= RSA_new_method(eng
);
815 RSA_set_ex_data(rtmp
, hndidx_rsa
, (char *)hptr
);
818 rtmp
->flags
|= RSA_FLAG_EXT_PKEY
;
821 if (p_hwcrhk_RSAGetPublicKey(*hptr
, &n
, &e
, &rmsg
)
822 != HWCRYPTOHOOK_ERROR_MPISIZE
)
824 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY
,HWCRHK_R_CHIL_ERROR
);
825 ERR_add_error_data(1,rmsg
.buf
);
829 bn_expand2(rtmp
->e
, e
.size
/sizeof(BN_ULONG
));
830 bn_expand2(rtmp
->n
, n
.size
/sizeof(BN_ULONG
));
834 if (p_hwcrhk_RSAGetPublicKey(*hptr
, &n
, &e
, &rmsg
))
836 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY
,
837 HWCRHK_R_CHIL_ERROR
);
838 ERR_add_error_data(1,rmsg
.buf
);
841 rtmp
->e
->top
= e
.size
/ sizeof(BN_ULONG
);
843 rtmp
->n
->top
= n
.size
/ sizeof(BN_ULONG
);
846 res
= EVP_PKEY_new();
847 EVP_PKEY_assign_RSA(res
, rtmp
);
851 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY
,
852 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED
);
858 #ifndef OPENSSL_NO_RSA
865 static EVP_PKEY
*hwcrhk_load_pubkey(ENGINE
*eng
, const char *key_id
,
866 UI_METHOD
*ui_method
, void *callback_data
)
868 EVP_PKEY
*res
= NULL
;
870 #ifndef OPENSSL_NO_RSA
871 res
= hwcrhk_load_privkey(eng
, key_id
,
872 ui_method
, callback_data
);
878 #ifndef OPENSSL_NO_RSA
883 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY
);
885 res
->pkey
.rsa
= RSA_new();
886 res
->pkey
.rsa
->n
= rsa
->n
;
887 res
->pkey
.rsa
->e
= rsa
->e
;
890 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY
);
896 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY
,
897 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED
);
908 /* A little mod_exp */
909 static int hwcrhk_mod_exp(BIGNUM
*r
, const BIGNUM
*a
, const BIGNUM
*p
,
910 const BIGNUM
*m
, BN_CTX
*ctx
)
913 HWCryptoHook_ErrMsgBuf rmsg
;
914 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
915 we use them directly, plus a little macro magic. We only
916 thing we need to make sure of is that enough space is allocated. */
917 HWCryptoHook_MPI m_a
, m_p
, m_n
, m_r
;
920 to_return
= 0; /* expect failure */
922 rmsg
.size
= sizeof(tempbuf
);
926 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP
,HWCRHK_R_NOT_INITIALISED
);
929 /* Prepare the params */
930 bn_expand2(r
, m
->top
); /* Check for error !! */
936 /* Perform the operation */
937 ret
= p_hwcrhk_ModExp(hwcrhk_context
, m_a
, m_p
, m_n
, &m_r
, &rmsg
);
939 /* Convert the response */
940 r
->top
= m_r
.size
/ sizeof(BN_ULONG
);
945 /* FIXME: When this error is returned, HWCryptoHook is
946 telling us that falling back to software computation
947 might be a good thing. */
948 if(ret
== HWCRYPTOHOOK_ERROR_FALLBACK
)
950 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP
,HWCRHK_R_REQUEST_FALLBACK
);
954 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP
,HWCRHK_R_REQUEST_FAILED
);
956 ERR_add_error_data(1,rmsg
.buf
);
965 #ifndef OPENSSL_NO_RSA
966 static int hwcrhk_rsa_mod_exp(BIGNUM
*r
, const BIGNUM
*I
, RSA
*rsa
, BN_CTX
*ctx
)
969 HWCryptoHook_ErrMsgBuf rmsg
;
970 HWCryptoHook_RSAKeyHandle
*hptr
;
971 int to_return
= 0, ret
;
974 rmsg
.size
= sizeof(tempbuf
);
978 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP
,HWCRHK_R_NOT_INITIALISED
);
982 /* This provides support for nForce keys. Since that's opaque data
983 all we do is provide a handle to the proper key and let HWCryptoHook
984 take care of the rest. */
985 if ((hptr
= (HWCryptoHook_RSAKeyHandle
*) RSA_get_ex_data(rsa
, hndidx_rsa
))
988 HWCryptoHook_MPI m_a
, m_r
;
992 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP
,
993 HWCRHK_R_MISSING_KEY_COMPONENTS
);
997 /* Prepare the params */
998 bn_expand2(r
, rsa
->n
->top
); /* Check for error !! */
1002 /* Perform the operation */
1003 ret
= p_hwcrhk_RSA(m_a
, *hptr
, &m_r
, &rmsg
);
1005 /* Convert the response */
1006 r
->top
= m_r
.size
/ sizeof(BN_ULONG
);
1011 /* FIXME: When this error is returned, HWCryptoHook is
1012 telling us that falling back to software computation
1013 might be a good thing. */
1014 if(ret
== HWCRYPTOHOOK_ERROR_FALLBACK
)
1016 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP
,
1017 HWCRHK_R_REQUEST_FALLBACK
);
1021 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP
,
1022 HWCRHK_R_REQUEST_FAILED
);
1024 ERR_add_error_data(1,rmsg
.buf
);
1030 HWCryptoHook_MPI m_a
, m_p
, m_q
, m_dmp1
, m_dmq1
, m_iqmp
, m_r
;
1032 if(!rsa
->p
|| !rsa
->q
|| !rsa
->dmp1
|| !rsa
->dmq1
|| !rsa
->iqmp
)
1034 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP
,
1035 HWCRHK_R_MISSING_KEY_COMPONENTS
);
1039 /* Prepare the params */
1040 bn_expand2(r
, rsa
->n
->top
); /* Check for error !! */
1042 BN2MPI(m_p
, rsa
->p
);
1043 BN2MPI(m_q
, rsa
->q
);
1044 BN2MPI(m_dmp1
, rsa
->dmp1
);
1045 BN2MPI(m_dmq1
, rsa
->dmq1
);
1046 BN2MPI(m_iqmp
, rsa
->iqmp
);
1049 /* Perform the operation */
1050 ret
= p_hwcrhk_ModExpCRT(hwcrhk_context
, m_a
, m_p
, m_q
,
1051 m_dmp1
, m_dmq1
, m_iqmp
, &m_r
, &rmsg
);
1053 /* Convert the response */
1054 r
->top
= m_r
.size
/ sizeof(BN_ULONG
);
1059 /* FIXME: When this error is returned, HWCryptoHook is
1060 telling us that falling back to software computation
1061 might be a good thing. */
1062 if(ret
== HWCRYPTOHOOK_ERROR_FALLBACK
)
1064 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP
,
1065 HWCRHK_R_REQUEST_FALLBACK
);
1069 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP
,
1070 HWCRHK_R_REQUEST_FAILED
);
1072 ERR_add_error_data(1,rmsg
.buf
);
1076 /* If we're here, we must be here with some semblance of success :-) */
1083 #ifndef OPENSSL_NO_RSA
1084 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1085 static int hwcrhk_mod_exp_mont(BIGNUM
*r
, const BIGNUM
*a
, const BIGNUM
*p
,
1086 const BIGNUM
*m
, BN_CTX
*ctx
, BN_MONT_CTX
*m_ctx
)
1088 return hwcrhk_mod_exp(r
, a
, p
, m
, ctx
);
1092 #ifndef OPENSSL_NO_DH
1093 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1094 static int hwcrhk_mod_exp_dh(const DH
*dh
, BIGNUM
*r
,
1095 const BIGNUM
*a
, const BIGNUM
*p
,
1096 const BIGNUM
*m
, BN_CTX
*ctx
, BN_MONT_CTX
*m_ctx
)
1098 return hwcrhk_mod_exp(r
, a
, p
, m
, ctx
);
1102 /* Random bytes are good */
1103 static int hwcrhk_rand_bytes(unsigned char *buf
, int num
)
1106 HWCryptoHook_ErrMsgBuf rmsg
;
1107 int to_return
= 0; /* assume failure */
1111 rmsg
.size
= sizeof(tempbuf
);
1115 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES
,HWCRHK_R_NOT_INITIALISED
);
1119 ret
= p_hwcrhk_RandomBytes(hwcrhk_context
, buf
, num
, &rmsg
);
1122 /* FIXME: When this error is returned, HWCryptoHook is
1123 telling us that falling back to software computation
1124 might be a good thing. */
1125 if(ret
== HWCRYPTOHOOK_ERROR_FALLBACK
)
1127 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES
,
1128 HWCRHK_R_REQUEST_FALLBACK
);
1132 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES
,
1133 HWCRHK_R_REQUEST_FAILED
);
1135 ERR_add_error_data(1,rmsg
.buf
);
1143 static int hwcrhk_rand_status(void)
1148 /* This cleans up an RSA KM key, called when ex_data is freed */
1149 #ifndef OPENSSL_NO_RSA
1150 static void hwcrhk_ex_free(void *obj
, void *item
, CRYPTO_EX_DATA
*ad
,
1151 int ind
,long argl
, void *argp
)
1154 HWCryptoHook_ErrMsgBuf rmsg
;
1155 #ifndef OPENSSL_NO_RSA
1156 HWCryptoHook_RSAKeyHandle
*hptr
;
1158 #if !defined(OPENSSL_NO_RSA)
1163 rmsg
.size
= sizeof(tempbuf
);
1165 #ifndef OPENSSL_NO_RSA
1166 hptr
= (HWCryptoHook_RSAKeyHandle
*) item
;
1169 ret
= p_hwcrhk_RSAUnloadKey(*hptr
, NULL
);
1176 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1177 * these just wrap the POSIX functions and add some logging.
1180 static int hwcrhk_mutex_init(HWCryptoHook_Mutex
* mt
,
1181 HWCryptoHook_CallerContext
*cactx
)
1183 mt
->lockid
= CRYPTO_get_new_dynlockid();
1184 if (mt
->lockid
== 0)
1185 return 1; /* failure */
1186 return 0; /* success */
1189 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex
*mt
)
1191 CRYPTO_w_lock(mt
->lockid
);
1195 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex
* mt
)
1197 CRYPTO_w_unlock(mt
->lockid
);
1200 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex
*mt
)
1202 CRYPTO_destroy_dynlockid(mt
->lockid
);
1205 static int hwcrhk_get_pass(const char *prompt_info
,
1206 int *len_io
, char *buf
,
1207 HWCryptoHook_PassphraseContext
*ppctx
,
1208 HWCryptoHook_CallerContext
*cactx
)
1210 pem_password_cb
*callback
= NULL
;
1211 void *callback_data
= NULL
;
1212 UI_METHOD
*ui_method
= NULL
;
1216 if (cactx
->ui_method
)
1217 ui_method
= cactx
->ui_method
;
1218 if (cactx
->password_callback
)
1219 callback
= cactx
->password_callback
;
1220 if (cactx
->callback_data
)
1221 callback_data
= cactx
->callback_data
;
1225 if (ppctx
->ui_method
)
1227 ui_method
= ppctx
->ui_method
;
1230 if (ppctx
->callback_data
)
1231 callback_data
= ppctx
->callback_data
;
1233 if (callback
== NULL
&& ui_method
== NULL
)
1235 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS
,HWCRHK_R_NO_CALLBACK
);
1241 UI
*ui
= UI_new_method(ui_method
);
1245 char *prompt
= UI_construct_prompt(ui
,
1246 "pass phrase", prompt_info
);
1248 ok
= UI_add_input_string(ui
,prompt
,
1249 UI_INPUT_FLAG_DEFAULT_PWD
,
1250 buf
,0,(*len_io
) - 1);
1251 UI_add_user_data(ui
, callback_data
);
1252 UI_ctrl(ui
, UI_CTRL_PRINT_ERRORS
, 1, 0, 0);
1259 while (ok
< 0 && UI_ctrl(ui
, UI_CTRL_IS_REDOABLE
, 0, 0, 0));
1262 *len_io
= strlen(buf
);
1265 OPENSSL_free(prompt
);
1270 *len_io
= callback(buf
, *len_io
, 0, callback_data
);
1277 static int hwcrhk_insert_card(const char *prompt_info
,
1278 const char *wrong_info
,
1279 HWCryptoHook_PassphraseContext
*ppctx
,
1280 HWCryptoHook_CallerContext
*cactx
)
1284 void *callback_data
= NULL
;
1285 UI_METHOD
*ui_method
= NULL
;
1289 if (cactx
->ui_method
)
1290 ui_method
= cactx
->ui_method
;
1291 if (cactx
->callback_data
)
1292 callback_data
= cactx
->callback_data
;
1296 if (ppctx
->ui_method
)
1297 ui_method
= ppctx
->ui_method
;
1298 if (ppctx
->callback_data
)
1299 callback_data
= ppctx
->callback_data
;
1301 if (ui_method
== NULL
)
1303 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD
,
1304 HWCRHK_R_NO_CALLBACK
);
1308 ui
= UI_new_method(ui_method
);
1316 BIO_snprintf(buf
, sizeof(buf
)-1,
1317 "Current card: \"%s\"\n", wrong_info
);
1318 ok
= UI_dup_info_string(ui
, buf
);
1319 if (ok
>= 0 && prompt_info
)
1321 BIO_snprintf(buf
, sizeof(buf
)-1,
1322 "Insert card \"%s\"", prompt_info
);
1323 ok
= UI_dup_input_boolean(ui
, buf
,
1324 "\n then hit <enter> or C<enter> to cancel\n",
1325 "\r\n", "Cc", UI_INPUT_FLAG_ECHO
, &answer
);
1327 UI_add_user_data(ui
, callback_data
);
1330 ok
= UI_process(ui
);
1333 if (ok
== -2 || (ok
>= 0 && answer
== 'C'))
1343 static void hwcrhk_log_message(void *logstr
, const char *message
)
1345 BIO
*lstream
= NULL
;
1347 CRYPTO_w_lock(CRYPTO_LOCK_BIO
);
1349 lstream
=*(BIO
**)logstr
;
1352 BIO_printf(lstream
, "%s\n", message
);
1354 CRYPTO_w_unlock(CRYPTO_LOCK_BIO
);
1357 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1358 * shared-library. */
1359 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1360 static int bind_fn(ENGINE
*e
, const char *id
)
1362 if(id
&& (strcmp(id
, engine_hwcrhk_id
) != 0) &&
1363 (strcmp(id
, engine_hwcrhk_id_alt
) != 0))
1369 IMPLEMENT_DYNAMIC_CHECK_FN()
1370 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn
)
1371 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1373 #endif /* !OPENSSL_NO_HW_CHIL */
1374 #endif /* !OPENSSL_NO_HW */