Configure et al: split up the lflags configuration item into two
[openssl.git] / engines / e_chil.c
1 /*
2  * Written by Richard Levitte (richard@levitte.org), Geoff Thorpe
3  * (geoff@geoffthorpe.net) and Dr Stephen N Henson (steve@openssl.org) for
4  * the OpenSSL project 2000.
5  */
6 /* ====================================================================
7  * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. All advertising materials mentioning features or use of this
22  *    software must display the following acknowledgment:
23  *    "This product includes software developed by the OpenSSL Project
24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25  *
26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27  *    endorse or promote products derived from this software without
28  *    prior written permission. For written permission, please contact
29  *    licensing@OpenSSL.org.
30  *
31  * 5. Products derived from this software may not be called "OpenSSL"
32  *    nor may "OpenSSL" appear in their names without prior written
33  *    permission of the OpenSSL Project.
34  *
35  * 6. Redistributions of any form whatsoever must retain the following
36  *    acknowledgment:
37  *    "This product includes software developed by the OpenSSL Project
38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This product includes cryptographic software written by Eric Young
55  * (eay@cryptsoft.com).  This product includes software written by Tim
56  * Hudson (tjh@cryptsoft.com).
57  *
58  */
59
60 #include <stdio.h>
61 #include <string.h>
62 #include <openssl/crypto.h>
63 #include <openssl/pem.h>
64 #include <openssl/dso.h>
65 #include <openssl/engine.h>
66 #include <openssl/ui.h>
67 #include <openssl/rand.h>
68 #ifndef OPENSSL_NO_RSA
69 # include <openssl/rsa.h>
70 #endif
71 #ifndef OPENSSL_NO_DH
72 # include <openssl/dh.h>
73 #endif
74 #include <openssl/bn.h>
75
76 #ifndef OPENSSL_NO_HW
77 # ifndef OPENSSL_NO_HW_CHIL
78
79 /*-
80  * Attribution notice: nCipher have said several times that it's OK for
81  * us to implement a general interface to their boxes, and recently declared
82  * their HWCryptoHook to be public, and therefore available for us to use.
83  * Thanks, nCipher.
84  *
85  * The hwcryptohook.h included here is from May 2000.
86  * [Richard Levitte]
87  */
88 #  ifdef FLAT_INC
89 #   include "hwcryptohook.h"
90 #  else
91 #   include "vendor_defns/hwcryptohook.h"
92 #  endif
93
94 #  define HWCRHK_LIB_NAME "CHIL engine"
95 #  include "e_chil_err.c"
96
97 static int hwcrhk_destroy(ENGINE *e);
98 static int hwcrhk_init(ENGINE *e);
99 static int hwcrhk_finish(ENGINE *e);
100 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void));
101
102 /* Functions to handle mutexes */
103 static int hwcrhk_mutex_init(HWCryptoHook_Mutex *,
104                              HWCryptoHook_CallerContext *);
105 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *);
106 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex *);
107 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *);
108
109 /* BIGNUM stuff */
110 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
111                           const BIGNUM *m, BN_CTX *ctx);
112
113 #  ifndef OPENSSL_NO_RSA
114 /* RSA stuff */
115 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa,
116                               BN_CTX *ctx);
117 /* This function is aliased to mod_exp (with the mont stuff dropped). */
118 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
119                                const BIGNUM *m, BN_CTX *ctx,
120                                BN_MONT_CTX *m_ctx);
121 static int hwcrhk_rsa_finish(RSA *rsa);
122 #  endif
123
124 #  ifndef OPENSSL_NO_DH
125 /* DH stuff */
126 /* This function is alised to mod_exp (with the DH and mont dropped). */
127 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
128                              const BIGNUM *a, const BIGNUM *p,
129                              const BIGNUM *m, BN_CTX *ctx,
130                              BN_MONT_CTX *m_ctx);
131 #  endif
132
133 /* RAND stuff */
134 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
135 static int hwcrhk_rand_status(void);
136
137 /* KM stuff */
138 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
139                                      UI_METHOD *ui_method,
140                                      void *callback_data);
141 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
142                                     UI_METHOD *ui_method,
143                                     void *callback_data);
144
145 /* Interaction stuff */
146 static int hwcrhk_insert_card(const char *prompt_info,
147                               const char *wrong_info,
148                               HWCryptoHook_PassphraseContext * ppctx,
149                               HWCryptoHook_CallerContext * cactx);
150 static int hwcrhk_get_pass(const char *prompt_info,
151                            int *len_io, char *buf,
152                            HWCryptoHook_PassphraseContext * ppctx,
153                            HWCryptoHook_CallerContext * cactx);
154 static void hwcrhk_log_message(void *logstr, const char *message);
155
156 /* The definitions for control commands specific to this engine */
157 #  define HWCRHK_CMD_SO_PATH              ENGINE_CMD_BASE
158 #  define HWCRHK_CMD_FORK_CHECK           (ENGINE_CMD_BASE + 1)
159 #  define HWCRHK_CMD_THREAD_LOCKING       (ENGINE_CMD_BASE + 2)
160 #  define HWCRHK_CMD_SET_USER_INTERFACE   (ENGINE_CMD_BASE + 3)
161 #  define HWCRHK_CMD_SET_CALLBACK_DATA    (ENGINE_CMD_BASE + 4)
162 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
163     {HWCRHK_CMD_SO_PATH,
164      "SO_PATH",
165      "Specifies the path to the 'hwcrhk' shared library",
166      ENGINE_CMD_FLAG_STRING},
167     {HWCRHK_CMD_FORK_CHECK,
168      "FORK_CHECK",
169      "Turns fork() checking on (non-zero) or off (zero)",
170      ENGINE_CMD_FLAG_NUMERIC},
171     {HWCRHK_CMD_THREAD_LOCKING,
172      "THREAD_LOCKING",
173      "Turns thread-safe locking on (zero) or off (non-zero)",
174      ENGINE_CMD_FLAG_NUMERIC},
175     {HWCRHK_CMD_SET_USER_INTERFACE,
176      "SET_USER_INTERFACE",
177      "Set the global user interface (internal)",
178      ENGINE_CMD_FLAG_INTERNAL},
179     {HWCRHK_CMD_SET_CALLBACK_DATA,
180      "SET_CALLBACK_DATA",
181      "Set the global user interface extra data (internal)",
182      ENGINE_CMD_FLAG_INTERNAL},
183     {0, NULL, NULL, 0}
184 };
185
186 #  ifndef OPENSSL_NO_RSA
187 /* Our internal RSA_METHOD that we provide pointers to */
188 static RSA_METHOD hwcrhk_rsa = {
189     "CHIL RSA method",
190     NULL,
191     NULL,
192     NULL,
193     NULL,
194     hwcrhk_rsa_mod_exp,
195     hwcrhk_mod_exp_mont,
196     NULL,
197     hwcrhk_rsa_finish,
198     0,
199     NULL,
200     NULL,
201     NULL,
202     NULL
203 };
204 #  endif
205
206 #  ifndef OPENSSL_NO_DH
207 /* Our internal DH_METHOD that we provide pointers to */
208 static DH_METHOD hwcrhk_dh = {
209     "CHIL DH method",
210     NULL,
211     NULL,
212     hwcrhk_mod_exp_dh,
213     NULL,
214     NULL,
215     0,
216     NULL,
217     NULL
218 };
219 #  endif
220
221 static RAND_METHOD hwcrhk_rand = {
222     /* "CHIL RAND method", */
223     NULL,
224     hwcrhk_rand_bytes,
225     NULL,
226     NULL,
227     hwcrhk_rand_bytes,
228     hwcrhk_rand_status,
229 };
230
231 /* Constants used when creating the ENGINE */
232 static const char *engine_hwcrhk_id = "chil";
233 static const char *engine_hwcrhk_name = "CHIL hardware engine support";
234 #  ifndef OPENSSL_NO_DYNAMIC_ENGINE
235 /* Compatibility hack, the dynamic library uses this form in the path */
236 static const char *engine_hwcrhk_id_alt = "ncipher";
237 #  endif
238
239 /* Internal stuff for HWCryptoHook */
240
241 /* Some structures needed for proper use of thread locks */
242 /*
243  * hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
244  * into HWCryptoHook_Mutex
245  */
246 struct HWCryptoHook_MutexValue {
247     int lockid;
248 };
249
250 /*
251  * hwcryptohook.h has some typedefs that turn struct
252  * HWCryptoHook_PassphraseContextValue into HWCryptoHook_PassphraseContext
253  */
254 struct HWCryptoHook_PassphraseContextValue {
255     UI_METHOD *ui_method;
256     void *callback_data;
257 };
258
259 /*
260  * hwcryptohook.h has some typedefs that turn struct
261  * HWCryptoHook_CallerContextValue into HWCryptoHook_CallerContext
262  */
263 struct HWCryptoHook_CallerContextValue {
264     pem_password_cb *password_callback; /* Deprecated! Only present for
265                                          * backward compatibility! */
266     UI_METHOD *ui_method;
267     void *callback_data;
268 };
269
270 /*
271  * The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
272  * BIGNUM's, so lets define a couple of conversion macros
273  */
274 #  define BN2MPI(mp, bn) \
275     {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
276 #  define MPI2BN(bn, mp) \
277     {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
278
279 static BIO *logstream = NULL;
280 static int disable_mutex_callbacks = 0;
281
282 /*
283  * One might wonder why these are needed, since one can pass down at least a
284  * UI_METHOD and a pointer to callback data to the key-loading functions. The
285  * thing is that the ModExp and RSAImmed functions can load keys as well, if
286  * the data they get is in a special, nCipher-defined format (hint: if you
287  * look at the private exponent of the RSA data as a string, you'll see this
288  * string: "nCipher KM tool key id", followed by some bytes, followed a key
289  * identity string, followed by more bytes.  This happens when you use
290  * "embed" keys instead of "hwcrhk" keys).  Unfortunately, those functions do
291  * not take any passphrase or caller context, and our functions can't really
292  * take any callback data either.  Still, the "insert_card" and
293  * "get_passphrase" callbacks may be called down the line, and will need to
294  * know what user interface callbacks to call, and having callback data from
295  * the application may be a nice thing as well, so we need to keep track of
296  * that globally.
297  */
298 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
299
300 /* Stuff to pass to the HWCryptoHook library */
301 static HWCryptoHook_InitInfo hwcrhk_globals = {
302     HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
303     &logstream,                 /* logstream */
304     sizeof(BN_ULONG),           /* limbsize */
305     0,                          /* mslimb first: false for BNs */
306     -1,                         /* msbyte first: use native */
307     0,                          /* Max mutexes, 0 = no small limit */
308     0,                          /* Max simultaneous, 0 = default */
309
310     /*
311      * The next few are mutex stuff: we write wrapper functions around the OS
312      * mutex functions.  We initialise them to 0 here, and change that to
313      * actual function pointers in hwcrhk_init() if dynamic locks are
314      * supported (that is, if the application programmer has made sure of
315      * setting up callbacks bafore starting this engine) *and* if
316      * disable_mutex_callbacks hasn't been set by a call to
317      * ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING).
318      */
319     sizeof(HWCryptoHook_Mutex),
320     0,
321     0,
322     0,
323     0,
324
325     /*
326      * The next few are condvar stuff: we write wrapper functions round the
327      * OS functions.  Currently not implemented and not and absolute
328      * necessity even in threaded programs, therefore 0'ed.  Will hopefully
329      * be implemented some day, since it enhances the efficiency of
330      * HWCryptoHook.
331      */
332     0,                          /* sizeof(HWCryptoHook_CondVar), */
333     0,                          /* hwcrhk_cv_init, */
334     0,                          /* hwcrhk_cv_wait, */
335     0,                          /* hwcrhk_cv_signal, */
336     0,                          /* hwcrhk_cv_broadcast, */
337     0,                          /* hwcrhk_cv_destroy, */
338
339     hwcrhk_get_pass,            /* pass phrase */
340     hwcrhk_insert_card,         /* insert a card */
341     hwcrhk_log_message          /* Log message */
342 };
343
344 /* Now, to our own code */
345
346 /*
347  * This internal function is used by ENGINE_chil() and possibly by the
348  * "dynamic" ENGINE support too
349  */
350 static int bind_helper(ENGINE *e)
351 {
352 #  ifndef OPENSSL_NO_RSA
353     const RSA_METHOD *meth1;
354 #  endif
355 #  ifndef OPENSSL_NO_DH
356     const DH_METHOD *meth2;
357 #  endif
358     if (!ENGINE_set_id(e, engine_hwcrhk_id) ||
359         !ENGINE_set_name(e, engine_hwcrhk_name) ||
360 #  ifndef OPENSSL_NO_RSA
361         !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
362 #  endif
363 #  ifndef OPENSSL_NO_DH
364         !ENGINE_set_DH(e, &hwcrhk_dh) ||
365 #  endif
366         !ENGINE_set_RAND(e, &hwcrhk_rand) ||
367         !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
368         !ENGINE_set_init_function(e, hwcrhk_init) ||
369         !ENGINE_set_finish_function(e, hwcrhk_finish) ||
370         !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
371         !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
372         !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
373         !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
374         return 0;
375
376 #  ifndef OPENSSL_NO_RSA
377     /*
378      * We know that the "PKCS1_OpenSSL()" functions hook properly to the
379      * cswift-specific mod_exp and mod_exp_crt so we use those functions. NB:
380      * We don't use ENGINE_openssl() or anything "more generic" because
381      * something like the RSAref code may not hook properly, and if you own
382      * one of these cards then you have the right to do RSA operations on it
383      * anyway!
384      */
385     meth1 = RSA_PKCS1_OpenSSL();
386     hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
387     hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
388     hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
389     hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
390 #  endif
391
392 #  ifndef OPENSSL_NO_DH
393     /* Much the same for Diffie-Hellman */
394     meth2 = DH_OpenSSL();
395     hwcrhk_dh.generate_key = meth2->generate_key;
396     hwcrhk_dh.compute_key = meth2->compute_key;
397 #  endif
398
399     /* Ensure the hwcrhk error handling is set up */
400     ERR_load_HWCRHK_strings();
401     return 1;
402 }
403
404 #  ifdef OPENSSL_NO_DYNAMIC_ENGINE
405 static ENGINE *engine_chil(void)
406 {
407     ENGINE *ret = ENGINE_new();
408     if (ret == NULL)
409         return NULL;
410     if (!bind_helper(ret)) {
411         ENGINE_free(ret);
412         return NULL;
413     }
414     return ret;
415 }
416
417 void ENGINE_load_chil(void)
418 {
419     /* Copied from eng_[openssl|dyn].c */
420     ENGINE *toadd = engine_chil();
421     if (!toadd)
422         return;
423     ENGINE_add(toadd);
424     ENGINE_free(toadd);
425     ERR_clear_error();
426 }
427 #  endif
428
429 /*
430  * This is a process-global DSO handle used for loading and unloading the
431  * HWCryptoHook library. NB: This is only set (or unset) during an init() or
432  * finish() call (reference counts permitting) and they're operating with
433  * global locks, so this should be thread-safe implicitly.
434  */
435 static DSO *hwcrhk_dso = NULL;
436 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
437 #  ifndef OPENSSL_NO_RSA
438 /* Index for KM handle.  Not really used yet. */
439 static int hndidx_rsa = -1;
440 #  endif
441
442 /*
443  * These are the function pointers that are (un)set when the library has
444  * successfully (un)loaded.
445  */
446 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
447 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
448 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
449 #  ifndef OPENSSL_NO_RSA
450 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
451 #  endif
452 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
453 #  ifndef OPENSSL_NO_RSA
454 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
455 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
456 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
457 #  endif
458 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
459
460 /* Used in the DSO operations. */
461 static const char *HWCRHK_LIBNAME = NULL;
462 static void free_HWCRHK_LIBNAME(void)
463 {
464     OPENSSL_free(HWCRHK_LIBNAME);
465     HWCRHK_LIBNAME = NULL;
466 }
467
468 static const char *get_HWCRHK_LIBNAME(void)
469 {
470     if (HWCRHK_LIBNAME)
471         return HWCRHK_LIBNAME;
472     return "nfhwcrhk";
473 }
474
475 static long set_HWCRHK_LIBNAME(const char *name)
476 {
477     free_HWCRHK_LIBNAME();
478     return (((HWCRHK_LIBNAME = OPENSSL_strdup(name)) != NULL) ? 1 : 0);
479 }
480
481 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
482 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
483 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
484 #  ifndef OPENSSL_NO_RSA
485 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
486 #  endif
487 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
488 #  ifndef OPENSSL_NO_RSA
489 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
490 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
491 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
492 #  endif
493 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
494
495 /*
496  * HWCryptoHook library functions and mechanics - these are used by the
497  * higher-level functions further down. NB: As and where there's no error
498  * checking, take a look lower down where these functions are called, the
499  * checking and error handling is probably down there.
500  */
501
502 /* utility function to obtain a context */
503 static int get_context(HWCryptoHook_ContextHandle * hac,
504                        HWCryptoHook_CallerContext * cac)
505 {
506     char tempbuf[1024];
507     HWCryptoHook_ErrMsgBuf rmsg;
508
509     rmsg.buf = tempbuf;
510     rmsg.size = sizeof(tempbuf);
511
512     *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg, cac);
513     if (!*hac)
514         return 0;
515     return 1;
516 }
517
518 /* similarly to release one. */
519 static void release_context(HWCryptoHook_ContextHandle hac)
520 {
521     p_hwcrhk_Finish(hac);
522 }
523
524 /* Destructor (complements the "ENGINE_chil()" constructor) */
525 static int hwcrhk_destroy(ENGINE *e)
526 {
527     free_HWCRHK_LIBNAME();
528     ERR_unload_HWCRHK_strings();
529     return 1;
530 }
531
532 /* (de)initialisation functions. */
533 static int hwcrhk_init(ENGINE *e)
534 {
535     HWCryptoHook_Init_t *p1;
536     HWCryptoHook_Finish_t *p2;
537     HWCryptoHook_ModExp_t *p3;
538 #  ifndef OPENSSL_NO_RSA
539     HWCryptoHook_RSA_t *p4;
540     HWCryptoHook_RSALoadKey_t *p5;
541     HWCryptoHook_RSAGetPublicKey_t *p6;
542     HWCryptoHook_RSAUnloadKey_t *p7;
543 #  endif
544     HWCryptoHook_RandomBytes_t *p8;
545     HWCryptoHook_ModExpCRT_t *p9;
546
547     if (hwcrhk_dso != NULL) {
548         HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_ALREADY_LOADED);
549         goto err;
550     }
551     /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
552     hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
553     if (hwcrhk_dso == NULL) {
554         HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE);
555         goto err;
556     }
557
558 #define BINDIT(t, name) (t *)DSO_bind_func(hwcrhk_dso, name)
559     if ((p1 = BINDIT(HWCryptoHook_Init_t, n_hwcrhk_Init)) == NULL
560         || (p2 = BINDIT(HWCryptoHook_Finish_t, n_hwcrhk_Finish)) == NULL
561         || (p3 = BINDIT(HWCryptoHook_ModExp_t, n_hwcrhk_ModExp)) == NULL
562 #  ifndef OPENSSL_NO_RSA
563         || (p4 = BINDIT(HWCryptoHook_RSA_t, n_hwcrhk_RSA)) == NULL
564         || (p5 = BINDIT(HWCryptoHook_RSALoadKey_t, n_hwcrhk_RSALoadKey)) == NULL
565         || (p6 = BINDIT(HWCryptoHook_RSAGetPublicKey_t, n_hwcrhk_RSAGetPublicKey)) == NULL
566         || (p7 = BINDIT(HWCryptoHook_RSAUnloadKey_t, n_hwcrhk_RSAUnloadKey)) == NULL
567 #  endif
568         || (p8 = BINDIT(HWCryptoHook_RandomBytes_t, n_hwcrhk_RandomBytes)) == NULL
569         || (p9 = BINDIT(HWCryptoHook_ModExpCRT_t, n_hwcrhk_ModExpCRT)) == NULL) {
570         HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE);
571         goto err;
572     }
573     /* Copy the pointers */
574     p_hwcrhk_Init = p1;
575     p_hwcrhk_Finish = p2;
576     p_hwcrhk_ModExp = p3;
577 #  ifndef OPENSSL_NO_RSA
578     p_hwcrhk_RSA = p4;
579     p_hwcrhk_RSALoadKey = p5;
580     p_hwcrhk_RSAGetPublicKey = p6;
581     p_hwcrhk_RSAUnloadKey = p7;
582 #  endif
583     p_hwcrhk_RandomBytes = p8;
584     p_hwcrhk_ModExpCRT = p9;
585
586     /*
587      * Check if the application decided to support dynamic locks, and if it
588      * does, use them.
589      */
590     if (disable_mutex_callbacks == 0) {
591         if (CRYPTO_get_dynlock_create_callback() != NULL &&
592             CRYPTO_get_dynlock_lock_callback() != NULL &&
593             CRYPTO_get_dynlock_destroy_callback() != NULL) {
594             hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
595             hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
596             hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
597             hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
598         }
599     }
600
601     /*
602      * Try and get a context - if not, we may have a DSO but no accelerator!
603      */
604     if (!get_context(&hwcrhk_context, &password_context)) {
605         HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_UNIT_FAILURE);
606         goto err;
607     }
608     /* Everything's fine. */
609 #  ifndef OPENSSL_NO_RSA
610     if (hndidx_rsa == -1)
611         hndidx_rsa = RSA_get_ex_new_index(0,
612                                           "nFast HWCryptoHook RSA key handle",
613                                           NULL, NULL, NULL);
614 #  endif
615     return 1;
616  err:
617     DSO_free(hwcrhk_dso);
618     hwcrhk_dso = NULL;
619     p_hwcrhk_Init = NULL;
620     p_hwcrhk_Finish = NULL;
621     p_hwcrhk_ModExp = NULL;
622 #  ifndef OPENSSL_NO_RSA
623     p_hwcrhk_RSA = NULL;
624     p_hwcrhk_RSALoadKey = NULL;
625     p_hwcrhk_RSAGetPublicKey = NULL;
626     p_hwcrhk_RSAUnloadKey = NULL;
627 #  endif
628     p_hwcrhk_ModExpCRT = NULL;
629     p_hwcrhk_RandomBytes = NULL;
630     return 0;
631 }
632
633 static int hwcrhk_finish(ENGINE *e)
634 {
635     int to_return = 1;
636     free_HWCRHK_LIBNAME();
637     if (hwcrhk_dso == NULL) {
638         HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_NOT_LOADED);
639         to_return = 0;
640         goto err;
641     }
642     release_context(hwcrhk_context);
643     if (!DSO_free(hwcrhk_dso)) {
644         HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_DSO_FAILURE);
645         to_return = 0;
646         goto err;
647     }
648  err:
649     BIO_free(logstream);
650     hwcrhk_dso = NULL;
651     p_hwcrhk_Init = NULL;
652     p_hwcrhk_Finish = NULL;
653     p_hwcrhk_ModExp = NULL;
654 #  ifndef OPENSSL_NO_RSA
655     p_hwcrhk_RSA = NULL;
656     p_hwcrhk_RSALoadKey = NULL;
657     p_hwcrhk_RSAGetPublicKey = NULL;
658     p_hwcrhk_RSAUnloadKey = NULL;
659 #  endif
660     p_hwcrhk_ModExpCRT = NULL;
661     p_hwcrhk_RandomBytes = NULL;
662     return to_return;
663 }
664
665 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
666 {
667     int to_return = 1;
668
669     switch (cmd) {
670     case HWCRHK_CMD_SO_PATH:
671         if (hwcrhk_dso) {
672             HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_ALREADY_LOADED);
673             return 0;
674         }
675         if (p == NULL) {
676             HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, ERR_R_PASSED_NULL_PARAMETER);
677             return 0;
678         }
679         return set_HWCRHK_LIBNAME((const char *)p);
680     case ENGINE_CTRL_SET_LOGSTREAM:
681         {
682             BIO *bio = (BIO *)p;
683
684             CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
685             BIO_free(logstream);
686             logstream = NULL;
687             if (CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO) > 1)
688                 logstream = bio;
689             else
690                 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_BIO_WAS_FREED);
691         }
692         CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
693         break;
694     case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
695         CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
696         password_context.password_callback = (pem_password_cb *)f;
697         CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
698         break;
699     case ENGINE_CTRL_SET_USER_INTERFACE:
700     case HWCRHK_CMD_SET_USER_INTERFACE:
701         CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
702         password_context.ui_method = (UI_METHOD *)p;
703         CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
704         break;
705     case ENGINE_CTRL_SET_CALLBACK_DATA:
706     case HWCRHK_CMD_SET_CALLBACK_DATA:
707         CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
708         password_context.callback_data = p;
709         CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
710         break;
711         /*
712          * this enables or disables the "SimpleForkCheck" flag used in the
713          * initialisation structure.
714          */
715     case ENGINE_CTRL_CHIL_SET_FORKCHECK:
716     case HWCRHK_CMD_FORK_CHECK:
717         CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
718         if (i)
719             hwcrhk_globals.flags |= HWCryptoHook_InitFlags_SimpleForkCheck;
720         else
721             hwcrhk_globals.flags &= ~HWCryptoHook_InitFlags_SimpleForkCheck;
722         CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
723         break;
724         /*
725          * This will prevent the initialisation function from "installing"
726          * the mutex-handling callbacks, even if they are available from
727          * within the library (or were provided to the library from the
728          * calling application). This is to remove any baggage for
729          * applications not using multithreading.
730          */
731     case ENGINE_CTRL_CHIL_NO_LOCKING:
732         CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
733         disable_mutex_callbacks = 1;
734         CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
735         break;
736     case HWCRHK_CMD_THREAD_LOCKING:
737         CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
738         disable_mutex_callbacks = ((i == 0) ? 0 : 1);
739         CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
740         break;
741
742         /* The command isn't understood by this engine */
743     default:
744         HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
745                   HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
746         to_return = 0;
747         break;
748     }
749
750     return to_return;
751 }
752
753 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
754                                      UI_METHOD *ui_method,
755                                      void *callback_data)
756 {
757 #  ifndef OPENSSL_NO_RSA
758     RSA *rtmp = NULL;
759 #  endif
760     EVP_PKEY *res = NULL;
761 #  ifndef OPENSSL_NO_RSA
762     HWCryptoHook_MPI e, n;
763     HWCryptoHook_RSAKeyHandle *hptr;
764 #  endif
765 #  if !defined(OPENSSL_NO_RSA)
766     char tempbuf[1024];
767     HWCryptoHook_ErrMsgBuf rmsg;
768     HWCryptoHook_PassphraseContext ppctx;
769 #  endif
770
771 #  if !defined(OPENSSL_NO_RSA)
772     rmsg.buf = tempbuf;
773     rmsg.size = sizeof(tempbuf);
774 #  endif
775
776     if (!hwcrhk_context) {
777         HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NOT_INITIALISED);
778         goto err;
779     }
780 #  ifndef OPENSSL_NO_RSA
781     hptr = OPENSSL_malloc(sizeof(*hptr));
782     if (hptr == NULL) {
783         HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
784         goto err;
785     }
786     ppctx.ui_method = ui_method;
787     ppctx.callback_data = callback_data;
788     if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr, &rmsg, &ppctx)) {
789         HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
790         ERR_add_error_data(1, rmsg.buf);
791         goto err;
792     }
793     if (!*hptr) {
794         HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NO_KEY);
795         goto err;
796     }
797 #  endif
798 #  ifndef OPENSSL_NO_RSA
799     rtmp = RSA_new_method(eng);
800     RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
801     rtmp->e = BN_new();
802     rtmp->n = BN_new();
803     rtmp->flags |= RSA_FLAG_EXT_PKEY;
804     MPI2BN(rtmp->e, e);
805     MPI2BN(rtmp->n, n);
806     if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
807         != HWCRYPTOHOOK_ERROR_MPISIZE) {
808         HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
809         ERR_add_error_data(1, rmsg.buf);
810         goto err;
811     }
812
813     bn_expand2(rtmp->e, e.size / sizeof(BN_ULONG));
814     bn_expand2(rtmp->n, n.size / sizeof(BN_ULONG));
815     MPI2BN(rtmp->e, e);
816     MPI2BN(rtmp->n, n);
817
818     if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)) {
819         HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
820         ERR_add_error_data(1, rmsg.buf);
821         goto err;
822     }
823     rtmp->e->top = e.size / sizeof(BN_ULONG);
824     bn_fix_top(rtmp->e);
825     rtmp->n->top = n.size / sizeof(BN_ULONG);
826     bn_fix_top(rtmp->n);
827
828     res = EVP_PKEY_new();
829     if (res == NULL) {
830         HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
831         goto err;
832     }
833     EVP_PKEY_assign_RSA(res, rtmp);
834 #  endif
835
836     if (res == NULL)
837         HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
838                   HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
839
840     return res;
841  err:
842 #  ifndef OPENSSL_NO_RSA
843     RSA_free(rtmp);
844 #  endif
845     return NULL;
846 }
847
848 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
849                                     UI_METHOD *ui_method, void *callback_data)
850 {
851     EVP_PKEY *res = NULL;
852
853 #  ifndef OPENSSL_NO_RSA
854     res = hwcrhk_load_privkey(eng, key_id, ui_method, callback_data);
855 #  endif
856
857     if (res)
858         switch (res->type) {
859 #  ifndef OPENSSL_NO_RSA
860         case EVP_PKEY_RSA:
861             {
862                 RSA *rsa = NULL;
863
864                 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
865                 rsa = res->pkey.rsa;
866                 res->pkey.rsa = RSA_new();
867                 res->pkey.rsa->n = rsa->n;
868                 res->pkey.rsa->e = rsa->e;
869                 rsa->n = NULL;
870                 rsa->e = NULL;
871                 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
872                 RSA_free(rsa);
873             }
874             break;
875 #  endif
876         default:
877             HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
878                       HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
879             goto err;
880         }
881
882     return res;
883  err:
884     EVP_PKEY_free(res);
885     return NULL;
886 }
887
888 /* A little mod_exp */
889 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
890                           const BIGNUM *m, BN_CTX *ctx)
891 {
892     char tempbuf[1024];
893     HWCryptoHook_ErrMsgBuf rmsg;
894     /*
895      * Since HWCryptoHook_MPI is pretty compatible with BIGNUM's, we use them
896      * directly, plus a little macro magic.  We only thing we need to make
897      * sure of is that enough space is allocated.
898      */
899     HWCryptoHook_MPI m_a, m_p, m_n, m_r;
900     int to_return, ret;
901
902     to_return = 0;              /* expect failure */
903     rmsg.buf = tempbuf;
904     rmsg.size = sizeof(tempbuf);
905
906     if (!hwcrhk_context) {
907         HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_NOT_INITIALISED);
908         goto err;
909     }
910     /* Prepare the params */
911     bn_expand2(r, m->top);      /* Check for error !! */
912     BN2MPI(m_a, a);
913     BN2MPI(m_p, p);
914     BN2MPI(m_n, m);
915     MPI2BN(r, m_r);
916
917     /* Perform the operation */
918     ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
919
920     /* Convert the response */
921     r->top = m_r.size / sizeof(BN_ULONG);
922     bn_fix_top(r);
923
924     if (ret < 0) {
925         /*
926          * FIXME: When this error is returned, HWCryptoHook is telling us
927          * that falling back to software computation might be a good thing.
928          */
929         if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
930             HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FALLBACK);
931         } else {
932             HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FAILED);
933         }
934         ERR_add_error_data(1, rmsg.buf);
935         goto err;
936     }
937
938     to_return = 1;
939  err:
940     return to_return;
941 }
942
943 #  ifndef OPENSSL_NO_RSA
944 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa,
945                               BN_CTX *ctx)
946 {
947     char tempbuf[1024];
948     HWCryptoHook_ErrMsgBuf rmsg;
949     HWCryptoHook_RSAKeyHandle *hptr;
950     int to_return = 0, ret;
951
952     rmsg.buf = tempbuf;
953     rmsg.size = sizeof(tempbuf);
954
955     if (!hwcrhk_context) {
956         HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, HWCRHK_R_NOT_INITIALISED);
957         goto err;
958     }
959
960     /*
961      * This provides support for nForce keys.  Since that's opaque data all
962      * we do is provide a handle to the proper key and let HWCryptoHook take
963      * care of the rest.
964      */
965     if ((hptr =
966          (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
967         != NULL) {
968         HWCryptoHook_MPI m_a, m_r;
969
970         if (!rsa->n) {
971             HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
972                       HWCRHK_R_MISSING_KEY_COMPONENTS);
973             goto err;
974         }
975
976         /* Prepare the params */
977         bn_expand2(r, rsa->n->top); /* Check for error !! */
978         BN2MPI(m_a, I);
979         MPI2BN(r, m_r);
980
981         /* Perform the operation */
982         ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
983
984         /* Convert the response */
985         r->top = m_r.size / sizeof(BN_ULONG);
986         bn_fix_top(r);
987
988         if (ret < 0) {
989             /*
990              * FIXME: When this error is returned, HWCryptoHook is telling us
991              * that falling back to software computation might be a good
992              * thing.
993              */
994             if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
995                 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
996                           HWCRHK_R_REQUEST_FALLBACK);
997             } else {
998                 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
999                           HWCRHK_R_REQUEST_FAILED);
1000             }
1001             ERR_add_error_data(1, rmsg.buf);
1002             goto err;
1003         }
1004     } else {
1005         HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1006
1007         if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) {
1008             HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1009                       HWCRHK_R_MISSING_KEY_COMPONENTS);
1010             goto err;
1011         }
1012
1013         /* Prepare the params */
1014         bn_expand2(r, rsa->n->top); /* Check for error !! */
1015         BN2MPI(m_a, I);
1016         BN2MPI(m_p, rsa->p);
1017         BN2MPI(m_q, rsa->q);
1018         BN2MPI(m_dmp1, rsa->dmp1);
1019         BN2MPI(m_dmq1, rsa->dmq1);
1020         BN2MPI(m_iqmp, rsa->iqmp);
1021         MPI2BN(r, m_r);
1022
1023         /* Perform the operation */
1024         ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1025                                  m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1026
1027         /* Convert the response */
1028         r->top = m_r.size / sizeof(BN_ULONG);
1029         bn_fix_top(r);
1030
1031         if (ret < 0) {
1032             /*
1033              * FIXME: When this error is returned, HWCryptoHook is telling us
1034              * that falling back to software computation might be a good
1035              * thing.
1036              */
1037             if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
1038                 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1039                           HWCRHK_R_REQUEST_FALLBACK);
1040             } else {
1041                 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1042                           HWCRHK_R_REQUEST_FAILED);
1043             }
1044             ERR_add_error_data(1, rmsg.buf);
1045             goto err;
1046         }
1047     }
1048     /*
1049      * If we're here, we must be here with some semblance of success :-)
1050      */
1051     to_return = 1;
1052  err:
1053     return to_return;
1054 }
1055 #  endif
1056
1057 #  ifndef OPENSSL_NO_RSA
1058 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1059 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1060                                const BIGNUM *m, BN_CTX *ctx,
1061                                BN_MONT_CTX *m_ctx)
1062 {
1063     return hwcrhk_mod_exp(r, a, p, m, ctx);
1064 }
1065
1066 static int hwcrhk_rsa_finish(RSA *rsa)
1067 {
1068     HWCryptoHook_RSAKeyHandle *hptr;
1069
1070     hptr = RSA_get_ex_data(rsa, hndidx_rsa);
1071     if (hptr) {
1072         p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1073         OPENSSL_free(hptr);
1074         RSA_set_ex_data(rsa, hndidx_rsa, NULL);
1075     }
1076     return 1;
1077 }
1078
1079 #  endif
1080
1081 #  ifndef OPENSSL_NO_DH
1082 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1083 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1084                              const BIGNUM *a, const BIGNUM *p,
1085                              const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1086 {
1087     return hwcrhk_mod_exp(r, a, p, m, ctx);
1088 }
1089 #  endif
1090
1091 /* Random bytes are good */
1092 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1093 {
1094     char tempbuf[1024];
1095     HWCryptoHook_ErrMsgBuf rmsg;
1096     int to_return = 0;          /* assume failure */
1097     int ret;
1098
1099     rmsg.buf = tempbuf;
1100     rmsg.size = sizeof(tempbuf);
1101
1102     if (!hwcrhk_context) {
1103         HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_NOT_INITIALISED);
1104         goto err;
1105     }
1106
1107     ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1108     if (ret < 0) {
1109         /*
1110          * FIXME: When this error is returned, HWCryptoHook is telling us
1111          * that falling back to software computation might be a good thing.
1112          */
1113         if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
1114             HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FALLBACK);
1115         } else {
1116             HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FAILED);
1117         }
1118         ERR_add_error_data(1, rmsg.buf);
1119         goto err;
1120     }
1121     to_return = 1;
1122  err:
1123     return to_return;
1124 }
1125
1126 static int hwcrhk_rand_status(void)
1127 {
1128     return 1;
1129 }
1130
1131 /*
1132  * Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1133  * these just wrap the POSIX functions and add some logging.
1134  */
1135
1136 static int hwcrhk_mutex_init(HWCryptoHook_Mutex * mt,
1137                              HWCryptoHook_CallerContext * cactx)
1138 {
1139     mt->lockid = CRYPTO_get_new_dynlockid();
1140     if (mt->lockid == 0)
1141         return 1;               /* failure */
1142     return 0;                   /* success */
1143 }
1144
1145 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex * mt)
1146 {
1147     CRYPTO_w_lock(mt->lockid);
1148     return 0;
1149 }
1150
1151 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1152 {
1153     CRYPTO_w_unlock(mt->lockid);
1154 }
1155
1156 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex * mt)
1157 {
1158     CRYPTO_destroy_dynlockid(mt->lockid);
1159 }
1160
1161 static int hwcrhk_get_pass(const char *prompt_info,
1162                            int *len_io, char *buf,
1163                            HWCryptoHook_PassphraseContext * ppctx,
1164                            HWCryptoHook_CallerContext * cactx)
1165 {
1166     pem_password_cb *callback = NULL;
1167     void *callback_data = NULL;
1168     UI_METHOD *ui_method = NULL;
1169     /*
1170      * Despite what the documentation says prompt_info can be an empty
1171      * string.
1172      */
1173     if (prompt_info && !*prompt_info)
1174         prompt_info = NULL;
1175
1176     if (cactx) {
1177         if (cactx->ui_method)
1178             ui_method = cactx->ui_method;
1179         if (cactx->password_callback)
1180             callback = cactx->password_callback;
1181         if (cactx->callback_data)
1182             callback_data = cactx->callback_data;
1183     }
1184     if (ppctx) {
1185         if (ppctx->ui_method) {
1186             ui_method = ppctx->ui_method;
1187             callback = NULL;
1188         }
1189         if (ppctx->callback_data)
1190             callback_data = ppctx->callback_data;
1191     }
1192     if (callback == NULL && ui_method == NULL) {
1193         HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS, HWCRHK_R_NO_CALLBACK);
1194         return -1;
1195     }
1196
1197     if (ui_method) {
1198         UI *ui = UI_new_method(ui_method);
1199         if (ui) {
1200             int ok;
1201             char *prompt = UI_construct_prompt(ui,
1202                                                "pass phrase", prompt_info);
1203
1204             ok = UI_add_input_string(ui, prompt,
1205                                      UI_INPUT_FLAG_DEFAULT_PWD,
1206                                      buf, 0, (*len_io) - 1);
1207             UI_add_user_data(ui, callback_data);
1208             UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1209
1210             if (ok >= 0)
1211                 do {
1212                     ok = UI_process(ui);
1213                 }
1214                 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1215
1216             if (ok >= 0)
1217                 *len_io = strlen(buf);
1218
1219             UI_free(ui);
1220             OPENSSL_free(prompt);
1221         }
1222     } else {
1223         *len_io = callback(buf, *len_io, 0, callback_data);
1224     }
1225     if (!*len_io)
1226         return -1;
1227     return 0;
1228 }
1229
1230 static int hwcrhk_insert_card(const char *prompt_info,
1231                               const char *wrong_info,
1232                               HWCryptoHook_PassphraseContext * ppctx,
1233                               HWCryptoHook_CallerContext * cactx)
1234 {
1235     int ok = -1;
1236     UI *ui;
1237     void *callback_data = NULL;
1238     UI_METHOD *ui_method = NULL;
1239
1240     if (cactx) {
1241         if (cactx->ui_method)
1242             ui_method = cactx->ui_method;
1243         if (cactx->callback_data)
1244             callback_data = cactx->callback_data;
1245     }
1246     if (ppctx) {
1247         if (ppctx->ui_method)
1248             ui_method = ppctx->ui_method;
1249         if (ppctx->callback_data)
1250             callback_data = ppctx->callback_data;
1251     }
1252     if (ui_method == NULL) {
1253         HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD, HWCRHK_R_NO_CALLBACK);
1254         return -1;
1255     }
1256
1257     ui = UI_new_method(ui_method);
1258
1259     if (ui) {
1260         char answer;
1261         char buf[BUFSIZ];
1262         /*
1263          * Despite what the documentation says wrong_info can be an empty
1264          * string.
1265          */
1266         if (wrong_info && *wrong_info)
1267             BIO_snprintf(buf, sizeof(buf) - 1,
1268                          "Current card: \"%s\"\n", wrong_info);
1269         else
1270             buf[0] = 0;
1271         ok = UI_dup_info_string(ui, buf);
1272         if (ok >= 0 && prompt_info) {
1273             BIO_snprintf(buf, sizeof(buf) - 1,
1274                          "Insert card \"%s\"", prompt_info);
1275             ok = UI_dup_input_boolean(ui, buf,
1276                                       "\n then hit <enter> or C<enter> to cancel\n",
1277                                       "\r\n", "Cc", UI_INPUT_FLAG_ECHO,
1278                                       &answer);
1279         }
1280         UI_add_user_data(ui, callback_data);
1281
1282         if (ok >= 0)
1283             ok = UI_process(ui);
1284         UI_free(ui);
1285
1286         if (ok == -2 || (ok >= 0 && answer == 'C'))
1287             ok = 1;
1288         else if (ok < 0)
1289             ok = -1;
1290         else
1291             ok = 0;
1292     }
1293     return ok;
1294 }
1295
1296 static void hwcrhk_log_message(void *logstr, const char *message)
1297 {
1298     BIO *lstream = NULL;
1299
1300     CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1301     if (logstr)
1302         lstream = *(BIO **)logstr;
1303     if (lstream) {
1304         BIO_printf(lstream, "%s\n", message);
1305     }
1306     CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1307 }
1308
1309 /*
1310  * This stuff is needed if this ENGINE is being compiled into a
1311  * self-contained shared-library.
1312  */
1313 #  ifndef OPENSSL_NO_DYNAMIC_ENGINE
1314 static int bind_fn(ENGINE *e, const char *id)
1315 {
1316     if (id && (strcmp(id, engine_hwcrhk_id) != 0) &&
1317         (strcmp(id, engine_hwcrhk_id_alt) != 0))
1318         return 0;
1319     if (!bind_helper(e))
1320         return 0;
1321     return 1;
1322 }
1323
1324 IMPLEMENT_DYNAMIC_CHECK_FN()
1325     IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1326 #  endif                        /* OPENSSL_NO_DYNAMIC_ENGINE */
1327 # endif                         /* !OPENSSL_NO_HW_CHIL */
1328 #endif                          /* !OPENSSL_NO_HW */