Move more comments that confuse indent
[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 /* Index for KM handle.  Not really used yet. */
423 static int hndidx_rsa = -1;
424 #endif
425
426 /* These are the function pointers that are (un)set when the library has
427  * successfully (un)loaded. */
428 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
429 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
430 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
431 #ifndef OPENSSL_NO_RSA
432 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
433 #endif
434 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
435 #ifndef OPENSSL_NO_RSA
436 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
437 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
438 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
439 #endif
440 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
441
442 /* Used in the DSO operations. */
443 static const char *HWCRHK_LIBNAME = NULL;
444 static void free_HWCRHK_LIBNAME(void)
445         {
446         if(HWCRHK_LIBNAME)
447                 OPENSSL_free((void*)HWCRHK_LIBNAME);
448         HWCRHK_LIBNAME = NULL;
449         }
450 static const char *get_HWCRHK_LIBNAME(void)
451         {
452         if(HWCRHK_LIBNAME)
453                 return HWCRHK_LIBNAME;
454         return "nfhwcrhk";
455         }
456 static long set_HWCRHK_LIBNAME(const char *name)
457         {
458         free_HWCRHK_LIBNAME();
459         return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
460         }
461 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
462 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
463 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
464 #ifndef OPENSSL_NO_RSA
465 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
466 #endif
467 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
468 #ifndef OPENSSL_NO_RSA
469 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
470 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
471 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
472 #endif
473 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
474
475 /* HWCryptoHook library functions and mechanics - these are used by the
476  * higher-level functions further down. NB: As and where there's no
477  * error checking, take a look lower down where these functions are
478  * called, the checking and error handling is probably down there. */
479
480 /* utility function to obtain a context */
481 static int get_context(HWCryptoHook_ContextHandle *hac,
482         HWCryptoHook_CallerContext *cac)
483         {
484         char tempbuf[1024];
485         HWCryptoHook_ErrMsgBuf rmsg;
486
487         rmsg.buf = tempbuf;
488         rmsg.size = sizeof(tempbuf);
489
490         *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
491                 cac);
492         if (!*hac)
493                 return 0;
494         return 1;
495         }
496  
497 /* similarly to release one. */
498 static void release_context(HWCryptoHook_ContextHandle hac)
499         {
500         p_hwcrhk_Finish(hac);
501         }
502
503 /* Destructor (complements the "ENGINE_chil()" constructor) */
504 static int hwcrhk_destroy(ENGINE *e)
505         {
506         free_HWCRHK_LIBNAME();
507         ERR_unload_HWCRHK_strings();
508         return 1;
509         }
510
511 /* (de)initialisation functions. */
512 static int hwcrhk_init(ENGINE *e)
513         {
514         HWCryptoHook_Init_t *p1;
515         HWCryptoHook_Finish_t *p2;
516         HWCryptoHook_ModExp_t *p3;
517 #ifndef OPENSSL_NO_RSA
518         HWCryptoHook_RSA_t *p4;
519         HWCryptoHook_RSALoadKey_t *p5;
520         HWCryptoHook_RSAGetPublicKey_t *p6;
521         HWCryptoHook_RSAUnloadKey_t *p7;
522 #endif
523         HWCryptoHook_RandomBytes_t *p8;
524         HWCryptoHook_ModExpCRT_t *p9;
525
526         if(hwcrhk_dso != NULL)
527                 {
528                 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
529                 goto err;
530                 }
531         /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
532         hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
533         if(hwcrhk_dso == NULL)
534                 {
535                 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
536                 goto err;
537                 }
538         if(!(p1 = (HWCryptoHook_Init_t *)
539                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
540                 !(p2 = (HWCryptoHook_Finish_t *)
541                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
542                 !(p3 = (HWCryptoHook_ModExp_t *)
543                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
544 #ifndef OPENSSL_NO_RSA
545                 !(p4 = (HWCryptoHook_RSA_t *)
546                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
547                 !(p5 = (HWCryptoHook_RSALoadKey_t *)
548                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
549                 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
550                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
551                 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
552                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
553 #endif
554                 !(p8 = (HWCryptoHook_RandomBytes_t *)
555                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
556                 !(p9 = (HWCryptoHook_ModExpCRT_t *)
557                         DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
558                 {
559                 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
560                 goto err;
561                 }
562         /* Copy the pointers */
563         p_hwcrhk_Init = p1;
564         p_hwcrhk_Finish = p2;
565         p_hwcrhk_ModExp = p3;
566 #ifndef OPENSSL_NO_RSA
567         p_hwcrhk_RSA = p4;
568         p_hwcrhk_RSALoadKey = p5;
569         p_hwcrhk_RSAGetPublicKey = p6;
570         p_hwcrhk_RSAUnloadKey = p7;
571 #endif
572         p_hwcrhk_RandomBytes = p8;
573         p_hwcrhk_ModExpCRT = p9;
574
575         /* Check if the application decided to support dynamic locks,
576            and if it does, use them. */
577         if (disable_mutex_callbacks == 0)
578                 {
579                 if (CRYPTO_get_dynlock_create_callback() != NULL &&
580                         CRYPTO_get_dynlock_lock_callback() != NULL &&
581                         CRYPTO_get_dynlock_destroy_callback() != NULL)
582                         {
583                         hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
584                         hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
585                         hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
586                         hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
587                         }
588                 }
589
590         /* Try and get a context - if not, we may have a DSO but no
591          * accelerator! */
592         if(!get_context(&hwcrhk_context, &password_context))
593                 {
594                 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
595                 goto err;
596                 }
597         /* Everything's fine. */
598 #ifndef OPENSSL_NO_RSA
599         if (hndidx_rsa == -1)
600                 hndidx_rsa = RSA_get_ex_new_index(0,
601                         "nFast HWCryptoHook RSA key handle",
602                         NULL, NULL, NULL);
603 #endif
604         return 1;
605 err:
606         if(hwcrhk_dso)
607                 DSO_free(hwcrhk_dso);
608         hwcrhk_dso = NULL;
609         p_hwcrhk_Init = NULL;
610         p_hwcrhk_Finish = NULL;
611         p_hwcrhk_ModExp = NULL;
612 #ifndef OPENSSL_NO_RSA
613         p_hwcrhk_RSA = NULL;
614         p_hwcrhk_RSALoadKey = NULL;
615         p_hwcrhk_RSAGetPublicKey = NULL;
616         p_hwcrhk_RSAUnloadKey = NULL;
617 #endif
618         p_hwcrhk_ModExpCRT = NULL;
619         p_hwcrhk_RandomBytes = NULL;
620         return 0;
621         }
622
623 static int hwcrhk_finish(ENGINE *e)
624         {
625         int to_return = 1;
626         free_HWCRHK_LIBNAME();
627         if(hwcrhk_dso == NULL)
628                 {
629                 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
630                 to_return = 0;
631                 goto err;
632                 }
633         release_context(hwcrhk_context);
634         if(!DSO_free(hwcrhk_dso))
635                 {
636                 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
637                 to_return = 0;
638                 goto err;
639                 }
640  err:
641         if (logstream)
642                 BIO_free(logstream);
643         hwcrhk_dso = NULL;
644         p_hwcrhk_Init = NULL;
645         p_hwcrhk_Finish = NULL;
646         p_hwcrhk_ModExp = NULL;
647 #ifndef OPENSSL_NO_RSA
648         p_hwcrhk_RSA = NULL;
649         p_hwcrhk_RSALoadKey = NULL;
650         p_hwcrhk_RSAGetPublicKey = NULL;
651         p_hwcrhk_RSAUnloadKey = NULL;
652 #endif
653         p_hwcrhk_ModExpCRT = NULL;
654         p_hwcrhk_RandomBytes = NULL;
655         return to_return;
656         }
657
658 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
659         {
660         int to_return = 1;
661
662         switch(cmd)
663                 {
664         case HWCRHK_CMD_SO_PATH:
665                 if(hwcrhk_dso)
666                         {
667                         HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
668                         return 0;
669                         }
670                 if(p == NULL)
671                         {
672                         HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
673                         return 0;
674                         }
675                 return set_HWCRHK_LIBNAME((const char *)p);
676         case ENGINE_CTRL_SET_LOGSTREAM:
677                 {
678                 BIO *bio = (BIO *)p;
679
680                 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
681                 if (logstream)
682                         {
683                         BIO_free(logstream);
684                         logstream = NULL;
685                         }
686                 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
687                         logstream = bio;
688                 else
689                         HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
690                 }
691                 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
692                 break;
693         case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
694                 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
695                 password_context.password_callback = (pem_password_cb *)f;
696                 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
697                 break;
698         case ENGINE_CTRL_SET_USER_INTERFACE:
699         case HWCRHK_CMD_SET_USER_INTERFACE:
700                 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
701                 password_context.ui_method = (UI_METHOD *)p;
702                 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
703                 break;
704         case ENGINE_CTRL_SET_CALLBACK_DATA:
705         case HWCRHK_CMD_SET_CALLBACK_DATA:
706                 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
707                 password_context.callback_data = p;
708                 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
709                 break;
710         /* this enables or disables the "SimpleForkCheck" flag used in the
711          * initialisation structure. */
712         case ENGINE_CTRL_CHIL_SET_FORKCHECK:
713         case HWCRHK_CMD_FORK_CHECK:
714                 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
715                 if(i)
716                         hwcrhk_globals.flags |=
717                                 HWCryptoHook_InitFlags_SimpleForkCheck;
718                 else
719                         hwcrhk_globals.flags &=
720                                 ~HWCryptoHook_InitFlags_SimpleForkCheck;
721                 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
722                 break;
723         /* This will prevent the initialisation function from "installing"
724          * the mutex-handling callbacks, even if they are available from
725          * within the library (or were provided to the library from the
726          * calling application). This is to remove any baggage for
727          * applications not using multithreading. */
728         case ENGINE_CTRL_CHIL_NO_LOCKING:
729                 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
730                 disable_mutex_callbacks = 1;
731                 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
732                 break;
733         case HWCRHK_CMD_THREAD_LOCKING:
734                 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
735                 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
736                 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
737                 break;
738
739         /* The command isn't understood by this engine */
740         default:
741                 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
742                         HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
743                 to_return = 0;
744                 break;
745                 }
746
747         return to_return;
748         }
749
750 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
751         UI_METHOD *ui_method, void *callback_data)
752         {
753 #ifndef OPENSSL_NO_RSA
754         RSA *rtmp = NULL;
755 #endif
756         EVP_PKEY *res = NULL;
757 #ifndef OPENSSL_NO_RSA
758         HWCryptoHook_MPI e, n;
759         HWCryptoHook_RSAKeyHandle *hptr;
760 #endif
761 #if !defined(OPENSSL_NO_RSA)
762         char tempbuf[1024];
763         HWCryptoHook_ErrMsgBuf rmsg;
764         HWCryptoHook_PassphraseContext ppctx;
765 #endif
766
767 #if !defined(OPENSSL_NO_RSA)
768         rmsg.buf = tempbuf;
769         rmsg.size = sizeof(tempbuf);
770 #endif
771
772         if(!hwcrhk_context)
773                 {
774                 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
775                         HWCRHK_R_NOT_INITIALISED);
776                 goto err;
777                 }
778 #ifndef OPENSSL_NO_RSA
779         hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
780         if (!hptr)
781                 {
782                 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
783                         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,
789                 &rmsg, &ppctx))
790                 {
791                 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
792                         HWCRHK_R_CHIL_ERROR);
793                 ERR_add_error_data(1,rmsg.buf);
794                 goto err;
795                 }
796         if (!*hptr)
797                 {
798                 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
799                         HWCRHK_R_NO_KEY);
800                 goto err;
801                 }
802 #endif
803 #ifndef OPENSSL_NO_RSA
804         rtmp = RSA_new_method(eng);
805         RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
806         rtmp->e = BN_new();
807         rtmp->n = BN_new();
808         rtmp->flags |= RSA_FLAG_EXT_PKEY;
809         MPI2BN(rtmp->e, e);
810         MPI2BN(rtmp->n, n);
811         if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
812                 != HWCRYPTOHOOK_ERROR_MPISIZE)
813                 {
814                 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,HWCRHK_R_CHIL_ERROR);
815                 ERR_add_error_data(1,rmsg.buf);
816                 goto err;
817                 }
818
819         bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
820         bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
821         MPI2BN(rtmp->e, e);
822         MPI2BN(rtmp->n, n);
823
824         if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
825                 {
826                 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
827                         HWCRHK_R_CHIL_ERROR);
828                 ERR_add_error_data(1,rmsg.buf);
829                 goto err;
830                 }
831         rtmp->e->top = e.size / sizeof(BN_ULONG);
832         bn_fix_top(rtmp->e);
833         rtmp->n->top = n.size / sizeof(BN_ULONG);
834         bn_fix_top(rtmp->n);
835
836         res = EVP_PKEY_new();
837         EVP_PKEY_assign_RSA(res, rtmp);
838 #endif
839
840         if (!res)
841                 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
842                         HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
843
844         return res;
845  err:
846 #ifndef OPENSSL_NO_RSA
847         if (rtmp)
848                 RSA_free(rtmp);
849 #endif
850         return NULL;
851         }
852
853 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
854         UI_METHOD *ui_method, void *callback_data)
855         {
856         EVP_PKEY *res = NULL;
857
858 #ifndef OPENSSL_NO_RSA
859         res = hwcrhk_load_privkey(eng, key_id,
860                 ui_method, callback_data);
861 #endif
862
863         if (res)
864                 switch(res->type)
865                         {
866 #ifndef OPENSSL_NO_RSA
867                 case EVP_PKEY_RSA:
868                         {
869                         RSA *rsa = NULL;
870
871                         CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
872                         rsa = res->pkey.rsa;
873                         res->pkey.rsa = RSA_new();
874                         res->pkey.rsa->n = rsa->n;
875                         res->pkey.rsa->e = rsa->e;
876                         rsa->n = NULL;
877                         rsa->e = NULL;
878                         CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
879                         RSA_free(rsa);
880                         }
881                         break;
882 #endif
883                 default:
884                         HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
885                                 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
886                         goto err;
887                         }
888
889         return res;
890  err:
891         if (res)
892                 EVP_PKEY_free(res);
893         return NULL;
894         }
895
896 /* A little mod_exp */
897 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
898                         const BIGNUM *m, BN_CTX *ctx)
899         {
900         char tempbuf[1024];
901         HWCryptoHook_ErrMsgBuf rmsg;
902         /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
903            we use them directly, plus a little macro magic.  We only
904            thing we need to make sure of is that enough space is allocated. */
905         HWCryptoHook_MPI m_a, m_p, m_n, m_r;
906         int to_return, ret;
907  
908         to_return = 0; /* expect failure */
909         rmsg.buf = tempbuf;
910         rmsg.size = sizeof(tempbuf);
911
912         if(!hwcrhk_context)
913                 {
914                 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
915                 goto err;
916                 }
917         /* Prepare the params */
918         bn_expand2(r, m->top);  /* Check for error !! */
919         BN2MPI(m_a, a);
920         BN2MPI(m_p, p);
921         BN2MPI(m_n, m);
922         MPI2BN(r, m_r);
923
924         /* Perform the operation */
925         ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
926
927         /* Convert the response */
928         r->top = m_r.size / sizeof(BN_ULONG);
929         bn_fix_top(r);
930
931         if (ret < 0)
932                 {
933                 /* FIXME: When this error is returned, HWCryptoHook is
934                    telling us that falling back to software computation
935                    might be a good thing. */
936                 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
937                         {
938                         HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
939                         }
940                 else
941                         {
942                         HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
943                         }
944                 ERR_add_error_data(1,rmsg.buf);
945                 goto err;
946                 }
947
948         to_return = 1;
949 err:
950         return to_return;
951         }
952
953 #ifndef OPENSSL_NO_RSA 
954 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
955         {
956         char tempbuf[1024];
957         HWCryptoHook_ErrMsgBuf rmsg;
958         HWCryptoHook_RSAKeyHandle *hptr;
959         int to_return = 0, ret;
960
961         rmsg.buf = tempbuf;
962         rmsg.size = sizeof(tempbuf);
963
964         if(!hwcrhk_context)
965                 {
966                 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
967                 goto err;
968                 }
969
970         /* This provides support for nForce keys.  Since that's opaque data
971            all we do is provide a handle to the proper key and let HWCryptoHook
972            take care of the rest. */
973         if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
974                 != NULL)
975                 {
976                 HWCryptoHook_MPI m_a, m_r;
977
978                 if(!rsa->n)
979                         {
980                         HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
981                                 HWCRHK_R_MISSING_KEY_COMPONENTS);
982                         goto err;
983                         }
984
985                 /* Prepare the params */
986                 bn_expand2(r, rsa->n->top); /* Check for error !! */
987                 BN2MPI(m_a, I);
988                 MPI2BN(r, m_r);
989
990                 /* Perform the operation */
991                 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
992
993                 /* Convert the response */
994                 r->top = m_r.size / sizeof(BN_ULONG);
995                 bn_fix_top(r);
996
997                 if (ret < 0)
998                         {
999                         /* FIXME: When this error is returned, HWCryptoHook is
1000                            telling us that falling back to software computation
1001                            might be a good thing. */
1002                         if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1003                                 {
1004                                 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1005                                         HWCRHK_R_REQUEST_FALLBACK);
1006                                 }
1007                         else
1008                                 {
1009                                 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1010                                         HWCRHK_R_REQUEST_FAILED);
1011                                 }
1012                         ERR_add_error_data(1,rmsg.buf);
1013                         goto err;
1014                         }
1015                 }
1016         else
1017                 {
1018                 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1019
1020                 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1021                         {
1022                         HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1023                                 HWCRHK_R_MISSING_KEY_COMPONENTS);
1024                         goto err;
1025                         }
1026
1027                 /* Prepare the params */
1028                 bn_expand2(r, rsa->n->top); /* Check for error !! */
1029                 BN2MPI(m_a, I);
1030                 BN2MPI(m_p, rsa->p);
1031                 BN2MPI(m_q, rsa->q);
1032                 BN2MPI(m_dmp1, rsa->dmp1);
1033                 BN2MPI(m_dmq1, rsa->dmq1);
1034                 BN2MPI(m_iqmp, rsa->iqmp);
1035                 MPI2BN(r, m_r);
1036
1037                 /* Perform the operation */
1038                 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1039                         m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1040
1041                 /* Convert the response */
1042                 r->top = m_r.size / sizeof(BN_ULONG);
1043                 bn_fix_top(r);
1044
1045                 if (ret < 0)
1046                         {
1047                         /* FIXME: When this error is returned, HWCryptoHook is
1048                            telling us that falling back to software computation
1049                            might be a good thing. */
1050                         if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1051                                 {
1052                                 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1053                                         HWCRHK_R_REQUEST_FALLBACK);
1054                                 }
1055                         else
1056                                 {
1057                                 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1058                                         HWCRHK_R_REQUEST_FAILED);
1059                                 }
1060                         ERR_add_error_data(1,rmsg.buf);
1061                         goto err;
1062                         }
1063                 }
1064         /* If we're here, we must be here with some semblance of success :-) */
1065         to_return = 1;
1066 err:
1067         return to_return;
1068         }
1069 #endif
1070
1071 #ifndef OPENSSL_NO_RSA
1072 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1073 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1074                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1075         {
1076         return hwcrhk_mod_exp(r, a, p, m, ctx);
1077         }
1078
1079 static int hwcrhk_rsa_finish(RSA *rsa)
1080         {
1081         HWCryptoHook_RSAKeyHandle *hptr;
1082
1083         hptr = RSA_get_ex_data(rsa, hndidx_rsa);
1084         if (hptr)
1085                 {
1086                 p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1087                 OPENSSL_free(hptr);
1088                 RSA_set_ex_data(rsa, hndidx_rsa, NULL);
1089                 }
1090         return 1;
1091         }
1092
1093 #endif
1094
1095 #ifndef OPENSSL_NO_DH
1096 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1097 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1098                 const BIGNUM *a, const BIGNUM *p,
1099                 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1100         {
1101         return hwcrhk_mod_exp(r, a, p, m, ctx);
1102         }
1103 #endif
1104
1105 /* Random bytes are good */
1106 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1107         {
1108         char tempbuf[1024];
1109         HWCryptoHook_ErrMsgBuf rmsg;
1110         int to_return = 0; /* assume failure */
1111         int ret;
1112
1113         rmsg.buf = tempbuf;
1114         rmsg.size = sizeof(tempbuf);
1115
1116         if(!hwcrhk_context)
1117                 {
1118                 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1119                 goto err;
1120                 }
1121
1122         ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1123         if (ret < 0)
1124                 {
1125                 /* FIXME: When this error is returned, HWCryptoHook is
1126                    telling us that falling back to software computation
1127                    might be a good thing. */
1128                 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1129                         {
1130                         HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1131                                 HWCRHK_R_REQUEST_FALLBACK);
1132                         }
1133                 else
1134                         {
1135                         HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1136                                 HWCRHK_R_REQUEST_FAILED);
1137                         }
1138                 ERR_add_error_data(1,rmsg.buf);
1139                 goto err;
1140                 }
1141         to_return = 1;
1142  err:
1143         return to_return;
1144         }
1145
1146 static int hwcrhk_rand_status(void)
1147         {
1148         return 1;
1149         }
1150
1151 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1152  * these just wrap the POSIX functions and add some logging.
1153  */
1154
1155 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1156         HWCryptoHook_CallerContext *cactx)
1157         {
1158         mt->lockid = CRYPTO_get_new_dynlockid();
1159         if (mt->lockid == 0)
1160                 return 1; /* failure */
1161         return 0; /* success */
1162         }
1163
1164 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1165         {
1166         CRYPTO_w_lock(mt->lockid);
1167         return 0;
1168         }
1169
1170 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1171         {
1172         CRYPTO_w_unlock(mt->lockid);
1173         }
1174
1175 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1176         {
1177         CRYPTO_destroy_dynlockid(mt->lockid);
1178         }
1179
1180 static int hwcrhk_get_pass(const char *prompt_info,
1181         int *len_io, char *buf,
1182         HWCryptoHook_PassphraseContext *ppctx,
1183         HWCryptoHook_CallerContext *cactx)
1184         {
1185         pem_password_cb *callback = NULL;
1186         void *callback_data = NULL;
1187         UI_METHOD *ui_method = NULL;
1188         /* Despite what the documentation says prompt_info can be
1189          * an empty string.
1190          */
1191         if (prompt_info && !*prompt_info)
1192                 prompt_info = NULL;
1193
1194         if (cactx)
1195                 {
1196                 if (cactx->ui_method)
1197                         ui_method = cactx->ui_method;
1198                 if (cactx->password_callback)
1199                         callback = cactx->password_callback;
1200                 if (cactx->callback_data)
1201                         callback_data = cactx->callback_data;
1202                 }
1203         if (ppctx)
1204                 {
1205                 if (ppctx->ui_method)
1206                         {
1207                         ui_method = ppctx->ui_method;
1208                         callback = NULL;
1209                         }
1210                 if (ppctx->callback_data)
1211                         callback_data = ppctx->callback_data;
1212                 }
1213         if (callback == NULL && ui_method == NULL)
1214                 {
1215                 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1216                 return -1;
1217                 }
1218
1219         if (ui_method)
1220                 {
1221                 UI *ui = UI_new_method(ui_method);
1222                 if (ui)
1223                         {
1224                         int ok;
1225                         char *prompt = UI_construct_prompt(ui,
1226                                 "pass phrase", prompt_info);
1227
1228                         ok = UI_add_input_string(ui,prompt,
1229                                 UI_INPUT_FLAG_DEFAULT_PWD,
1230                                 buf,0,(*len_io) - 1);
1231                         UI_add_user_data(ui, callback_data);
1232                         UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1233
1234                         if (ok >= 0)
1235                                 do
1236                                         {
1237                                         ok=UI_process(ui);
1238                                         }
1239                                 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1240
1241                         if (ok >= 0)
1242                                 *len_io = strlen(buf);
1243
1244                         UI_free(ui);
1245                         OPENSSL_free(prompt);
1246                         }
1247                 }
1248         else
1249                 {
1250                 *len_io = callback(buf, *len_io, 0, callback_data);
1251                 }
1252         if(!*len_io)
1253                 return -1;
1254         return 0;
1255         }
1256
1257 static int hwcrhk_insert_card(const char *prompt_info,
1258                       const char *wrong_info,
1259                       HWCryptoHook_PassphraseContext *ppctx,
1260                       HWCryptoHook_CallerContext *cactx)
1261         {
1262         int ok = -1;
1263         UI *ui;
1264         void *callback_data = NULL;
1265         UI_METHOD *ui_method = NULL;
1266
1267         if (cactx)
1268                 {
1269                 if (cactx->ui_method)
1270                         ui_method = cactx->ui_method;
1271                 if (cactx->callback_data)
1272                         callback_data = cactx->callback_data;
1273                 }
1274         if (ppctx)
1275                 {
1276                 if (ppctx->ui_method)
1277                         ui_method = ppctx->ui_method;
1278                 if (ppctx->callback_data)
1279                         callback_data = ppctx->callback_data;
1280                 }
1281         if (ui_method == NULL)
1282                 {
1283                 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1284                         HWCRHK_R_NO_CALLBACK);
1285                 return -1;
1286                 }
1287
1288         ui = UI_new_method(ui_method);
1289
1290         if (ui)
1291                 {
1292                 char answer;
1293                 char buf[BUFSIZ];
1294                 /* Despite what the documentation says wrong_info can be
1295                  * an empty string.
1296                  */
1297                 if (wrong_info && *wrong_info)
1298                         BIO_snprintf(buf, sizeof(buf)-1,
1299                                 "Current card: \"%s\"\n", wrong_info);
1300                 else
1301                         buf[0] = 0;
1302                 ok = UI_dup_info_string(ui, buf);
1303                 if (ok >= 0 && prompt_info)
1304                         {
1305                         BIO_snprintf(buf, sizeof(buf)-1,
1306                                 "Insert card \"%s\"", prompt_info);
1307                         ok = UI_dup_input_boolean(ui, buf,
1308                                 "\n then hit <enter> or C<enter> to cancel\n",
1309                                 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1310                         }
1311                 UI_add_user_data(ui, callback_data);
1312
1313                 if (ok >= 0)
1314                         ok = UI_process(ui);
1315                 UI_free(ui);
1316
1317                 if (ok == -2 || (ok >= 0 && answer == 'C'))
1318                         ok = 1;
1319                 else if (ok < 0)
1320                         ok = -1;
1321                 else
1322                         ok = 0;
1323                 }
1324         return ok;
1325         }
1326
1327 static void hwcrhk_log_message(void *logstr, const char *message)
1328         {
1329         BIO *lstream = NULL;
1330
1331         CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1332         if (logstr)
1333                 lstream=*(BIO **)logstr;
1334         if (lstream)
1335                 {
1336                 BIO_printf(lstream, "%s\n", message);
1337                 }
1338         CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1339         }
1340
1341 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1342  * shared-library. */      
1343 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1344 static int bind_fn(ENGINE *e, const char *id)
1345         {
1346         if(id && (strcmp(id, engine_hwcrhk_id) != 0) &&
1347                         (strcmp(id, engine_hwcrhk_id_alt) != 0))
1348                 return 0;
1349         if(!bind_helper(e))
1350                 return 0;
1351         return 1;
1352         }       
1353 IMPLEMENT_DYNAMIC_CHECK_FN()
1354 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1355 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1356
1357 #endif /* !OPENSSL_NO_HW_CHIL */
1358 #endif /* !OPENSSL_NO_HW */