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