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