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