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