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