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