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