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