Reject excessively large primes in DH key generation.
[openssl.git] / engines / e_chil.c
index 30693353d15ac6639c907e7ffc554d171e720c23..d5e4cb67c44077349740c74ab61afa36aea56cb6 100644 (file)
@@ -1,7 +1,8 @@
-/* crypto/engine/e_chil.c -*- mode: C; c-file-style: "eay" -*- */
-/* Written by Richard Levitte (richard@levitte.org), Geoff Thorpe
- * (geoff@geoffthorpe.net) and Dr Stephen N Henson (steve@openssl.org)
- * for the OpenSSL project 2000.
+/* crypto/engine/e_chil.c */
+/*
+ * Written by Richard Levitte (richard@levitte.org), Geoff Thorpe
+ * (geoff@geoffthorpe.net) and Dr Stephen N Henson (steve@openssl.org) for
+ * the OpenSSL project 2000.
  */
 /* ====================================================================
  * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
@@ -11,7 +12,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
 #include <openssl/ui.h>
 #include <openssl/rand.h>
 #ifndef OPENSSL_NO_RSA
-#include <openssl/rsa.h>
+# include <openssl/rsa.h>
 #endif
 #ifndef OPENSSL_NO_DH
-#include <openssl/dh.h>
+# include <openssl/dh.h>
 #endif
 #include <openssl/bn.h>
 
 #ifndef OPENSSL_NO_HW
-#ifndef OPENSSL_NO_HW_CHIL
+# ifndef OPENSSL_NO_HW_CHIL
 
-/* Attribution notice: nCipher have said several times that it's OK for
+/*-
+ * Attribution notice: nCipher have said several times that it's OK for
  * us to implement a general interface to their boxes, and recently declared
  * their HWCryptoHook to be public, and therefore available for us to use.
  * Thanks, nCipher.
  * The hwcryptohook.h included here is from May 2000.
  * [Richard Levitte]
  */
-#ifdef FLAT_INC
-#include "hwcryptohook.h"
-#else
-#include "vendor_defns/hwcryptohook.h"
-#endif
+#  ifdef FLAT_INC
+#   include "hwcryptohook.h"
+#  else
+#   include "vendor_defns/hwcryptohook.h"
+#  endif
 
-#define HWCRHK_LIB_NAME "CHIL engine"
-#include "e_chil_err.c"
+#  define HWCRHK_LIB_NAME "CHIL engine"
+#  include "e_chil_err.c"
 
 static int hwcrhk_destroy(ENGINE *e);
 static int hwcrhk_init(ENGINE *e);
 static int hwcrhk_finish(ENGINE *e);
-static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); 
+static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void));
 
 /* Functions to handle mutexes */
-static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
-static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
-static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
-static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
+static int hwcrhk_mutex_init(HWCryptoHook_Mutex *,
+                             HWCryptoHook_CallerContext *);
+static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *);
+static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex *);
+static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *);
 
 /* BIGNUM stuff */
 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
-               const BIGNUM *m, BN_CTX *ctx);
+                          const BIGNUM *m, BN_CTX *ctx);
 
-#ifndef OPENSSL_NO_RSA
+#  ifndef OPENSSL_NO_RSA
 /* RSA stuff */
-static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
-#endif
-#ifndef OPENSSL_NO_RSA
+static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa,
+                              BN_CTX *ctx);
 /* This function is aliased to mod_exp (with the mont stuff dropped). */
 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
-               const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
-#endif
+                               const BIGNUM *m, BN_CTX *ctx,
+                               BN_MONT_CTX *m_ctx);
+static int hwcrhk_rsa_finish(RSA *rsa);
+#  endif
 
-#ifndef OPENSSL_NO_DH
+#  ifndef OPENSSL_NO_DH
 /* DH stuff */
 /* This function is alised to mod_exp (with the DH and mont dropped). */
 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
-       const BIGNUM *a, const BIGNUM *p,
-       const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
-#endif
+                             const BIGNUM *a, const BIGNUM *p,
+                             const BIGNUM *m, BN_CTX *ctx,
+                             BN_MONT_CTX *m_ctx);
+#  endif
 
 /* RAND stuff */
 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
@@ -132,1243 +137,1230 @@ static int hwcrhk_rand_status(void);
 
 /* KM stuff */
 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
-       UI_METHOD *ui_method, void *callback_data);
+                                     UI_METHOD *ui_method,
+                                     void *callback_data);
 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
-       UI_METHOD *ui_method, void *callback_data);
-#ifndef OPENSSL_NO_RSA
-static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
-       int ind,long argl, void *argp);
-#endif
+                                    UI_METHOD *ui_method,
+                                    void *callback_data);
 
 /* Interaction stuff */
 static int hwcrhk_insert_card(const char *prompt_info,
-       const char *wrong_info,
-       HWCryptoHook_PassphraseContext *ppctx,
-       HWCryptoHook_CallerContext *cactx);
+                              const char *wrong_info,
+                              HWCryptoHook_PassphraseContext * ppctx,
+                              HWCryptoHook_CallerContext * cactx);
 static int hwcrhk_get_pass(const char *prompt_info,
-       int *len_io, char *buf,
-       HWCryptoHook_PassphraseContext *ppctx,
-       HWCryptoHook_CallerContext *cactx);
+                           int *len_io, char *buf,
+                           HWCryptoHook_PassphraseContext * ppctx,
+                           HWCryptoHook_CallerContext * cactx);
 static void hwcrhk_log_message(void *logstr, const char *message);
 
 /* The definitions for control commands specific to this engine */
-#define HWCRHK_CMD_SO_PATH             ENGINE_CMD_BASE
-#define HWCRHK_CMD_FORK_CHECK          (ENGINE_CMD_BASE + 1)
-#define HWCRHK_CMD_THREAD_LOCKING      (ENGINE_CMD_BASE + 2)
-#define HWCRHK_CMD_SET_USER_INTERFACE   (ENGINE_CMD_BASE + 3)
-#define HWCRHK_CMD_SET_CALLBACK_DATA    (ENGINE_CMD_BASE + 4)
+#  define HWCRHK_CMD_SO_PATH              ENGINE_CMD_BASE
+#  define HWCRHK_CMD_FORK_CHECK           (ENGINE_CMD_BASE + 1)
+#  define HWCRHK_CMD_THREAD_LOCKING       (ENGINE_CMD_BASE + 2)
+#  define HWCRHK_CMD_SET_USER_INTERFACE   (ENGINE_CMD_BASE + 3)
+#  define HWCRHK_CMD_SET_CALLBACK_DATA    (ENGINE_CMD_BASE + 4)
 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
-       {HWCRHK_CMD_SO_PATH,
-               "SO_PATH",
-               "Specifies the path to the 'hwcrhk' shared library",
-               ENGINE_CMD_FLAG_STRING},
-       {HWCRHK_CMD_FORK_CHECK,
-               "FORK_CHECK",
-               "Turns fork() checking on (non-zero) or off (zero)",
-               ENGINE_CMD_FLAG_NUMERIC},
-       {HWCRHK_CMD_THREAD_LOCKING,
-               "THREAD_LOCKING",
-               "Turns thread-safe locking on (zero) or off (non-zero)",
-               ENGINE_CMD_FLAG_NUMERIC},
-       {HWCRHK_CMD_SET_USER_INTERFACE,
-               "SET_USER_INTERFACE",
-               "Set the global user interface (internal)",
-               ENGINE_CMD_FLAG_INTERNAL},
-       {HWCRHK_CMD_SET_CALLBACK_DATA,
-               "SET_CALLBACK_DATA",
-               "Set the global user interface extra data (internal)",
-               ENGINE_CMD_FLAG_INTERNAL},
-       {0, NULL, NULL, 0}
-       };
+    {HWCRHK_CMD_SO_PATH,
+     "SO_PATH",
+     "Specifies the path to the 'hwcrhk' shared library",
+     ENGINE_CMD_FLAG_STRING},
+    {HWCRHK_CMD_FORK_CHECK,
+     "FORK_CHECK",
+     "Turns fork() checking on (non-zero) or off (zero)",
+     ENGINE_CMD_FLAG_NUMERIC},
+    {HWCRHK_CMD_THREAD_LOCKING,
+     "THREAD_LOCKING",
+     "Turns thread-safe locking on (zero) or off (non-zero)",
+     ENGINE_CMD_FLAG_NUMERIC},
+    {HWCRHK_CMD_SET_USER_INTERFACE,
+     "SET_USER_INTERFACE",
+     "Set the global user interface (internal)",
+     ENGINE_CMD_FLAG_INTERNAL},
+    {HWCRHK_CMD_SET_CALLBACK_DATA,
+     "SET_CALLBACK_DATA",
+     "Set the global user interface extra data (internal)",
+     ENGINE_CMD_FLAG_INTERNAL},
+    {0, NULL, NULL, 0}
+};
 
-#ifndef OPENSSL_NO_RSA
+#  ifndef OPENSSL_NO_RSA
 /* Our internal RSA_METHOD that we provide pointers to */
-static RSA_METHOD hwcrhk_rsa =
-       {
-       "CHIL RSA method",
-       NULL,
-       NULL,
-       NULL,
-       NULL,
-       hwcrhk_rsa_mod_exp,
-       hwcrhk_mod_exp_mont,
-       NULL,
-       NULL,
-       0,
-       NULL,
-       NULL,
-       NULL,
-       NULL
-       };
-#endif
+static RSA_METHOD hwcrhk_rsa = {
+    "CHIL RSA method",
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    hwcrhk_rsa_mod_exp,
+    hwcrhk_mod_exp_mont,
+    NULL,
+    hwcrhk_rsa_finish,
+    0,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+#  endif
 
-#ifndef OPENSSL_NO_DH
+#  ifndef OPENSSL_NO_DH
 /* Our internal DH_METHOD that we provide pointers to */
-static DH_METHOD hwcrhk_dh =
-       {
-       "CHIL DH method",
-       NULL,
-       NULL,
-       hwcrhk_mod_exp_dh,
-       NULL,
-       NULL,
-       0,
-       NULL,
-       NULL
-       };
-#endif
-
-static RAND_METHOD hwcrhk_rand =
-       {
-       /* "CHIL RAND method", */
-       NULL,
-       hwcrhk_rand_bytes,
-       NULL,
-       NULL,
-       hwcrhk_rand_bytes,
-       hwcrhk_rand_status,
-       };
+static DH_METHOD hwcrhk_dh = {
+    "CHIL DH method",
+    NULL,
+    NULL,
+    hwcrhk_mod_exp_dh,
+    NULL,
+    NULL,
+    0,
+    NULL,
+    NULL
+};
+#  endif
+
+static RAND_METHOD hwcrhk_rand = {
+    /* "CHIL RAND method", */
+    NULL,
+    hwcrhk_rand_bytes,
+    NULL,
+    NULL,
+    hwcrhk_rand_bytes,
+    hwcrhk_rand_status,
+};
 
 /* Constants used when creating the ENGINE */
 static const char *engine_hwcrhk_id = "chil";
 static const char *engine_hwcrhk_name = "CHIL hardware engine support";
-#ifndef OPENSSL_NO_DYNAMIC_ENGINE 
+#  ifndef OPENSSL_NO_DYNAMIC_ENGINE
 /* Compatibility hack, the dynamic library uses this form in the path */
 static const char *engine_hwcrhk_id_alt = "ncipher";
-#endif
+#  endif
 
 /* Internal stuff for HWCryptoHook */
 
 /* Some structures needed for proper use of thread locks */
-/* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
-   into HWCryptoHook_Mutex */
-struct HWCryptoHook_MutexValue
-       {
-       int lockid;
-       };
-
-/* hwcryptohook.h has some typedefs that turn
-   struct HWCryptoHook_PassphraseContextValue
-   into HWCryptoHook_PassphraseContext */
-struct HWCryptoHook_PassphraseContextValue
-       {
-        UI_METHOD *ui_method;
-       void *callback_data;
-       };
-
-/* hwcryptohook.h has some typedefs that turn
-   struct HWCryptoHook_CallerContextValue
-   into HWCryptoHook_CallerContext */
-struct HWCryptoHook_CallerContextValue
-       {
-       pem_password_cb *password_callback; /* Deprecated!  Only present for
-                                               backward compatibility! */
-        UI_METHOD *ui_method;
-       void *callback_data;
-       };
-
-/* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
-   BIGNUM's, so lets define a couple of conversion macros */
-#define BN2MPI(mp, bn) \
+/*
+ * hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
+ * into HWCryptoHook_Mutex
+ */
+struct HWCryptoHook_MutexValue {
+    int lockid;
+};
+
+/*
+ * hwcryptohook.h has some typedefs that turn struct
+ * HWCryptoHook_PassphraseContextValue into HWCryptoHook_PassphraseContext
+ */
+struct HWCryptoHook_PassphraseContextValue {
+    UI_METHOD *ui_method;
+    void *callback_data;
+};
+
+/*
+ * hwcryptohook.h has some typedefs that turn struct
+ * HWCryptoHook_CallerContextValue into HWCryptoHook_CallerContext
+ */
+struct HWCryptoHook_CallerContextValue {
+    pem_password_cb *password_callback; /* Deprecated! Only present for
+                                         * backward compatibility! */
+    UI_METHOD *ui_method;
+    void *callback_data;
+};
+
+/*
+ * The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
+ * BIGNUM's, so lets define a couple of conversion macros
+ */
+#  define BN2MPI(mp, bn) \
     {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
-#define MPI2BN(bn, mp) \
+#  define MPI2BN(bn, mp) \
     {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
 
 static BIO *logstream = NULL;
 static int disable_mutex_callbacks = 0;
 
-/* One might wonder why these are needed, since one can pass down at least
-   a UI_METHOD and a pointer to callback data to the key-loading functions.
-   The thing is that the ModExp and RSAImmed functions can load keys as well,
-   if the data they get is in a special, nCipher-defined format (hint: if you
-   look at the private exponent of the RSA data as a string, you'll see this
-   string: "nCipher KM tool key id", followed by some bytes, followed a key
-   identity string, followed by more bytes.  This happens when you use "embed"
-   keys instead of "hwcrhk" keys).  Unfortunately, those functions do not take
-   any passphrase or caller context, and our functions can't really take any
-   callback data either.  Still, the "insert_card" and "get_passphrase"
-   callbacks may be called down the line, and will need to know what user
-   interface callbacks to call, and having callback data from the application
-   may be a nice thing as well, so we need to keep track of that globally. */
+/*
+ * One might wonder why these are needed, since one can pass down at least a
+ * UI_METHOD and a pointer to callback data to the key-loading functions. The
+ * thing is that the ModExp and RSAImmed functions can load keys as well, if
+ * the data they get is in a special, nCipher-defined format (hint: if you
+ * look at the private exponent of the RSA data as a string, you'll see this
+ * string: "nCipher KM tool key id", followed by some bytes, followed a key
+ * identity string, followed by more bytes.  This happens when you use
+ * "embed" keys instead of "hwcrhk" keys).  Unfortunately, those functions do
+ * not take any passphrase or caller context, and our functions can't really
+ * take any callback data either.  Still, the "insert_card" and
+ * "get_passphrase" callbacks may be called down the line, and will need to
+ * know what user interface callbacks to call, and having callback data from
+ * the application may be a nice thing as well, so we need to keep track of
+ * that globally.
+ */
 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
 
 /* Stuff to pass to the HWCryptoHook library */
 static HWCryptoHook_InitInfo hwcrhk_globals = {
-       HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
-       &logstream,             /* logstream */
-       sizeof(BN_ULONG),       /* limbsize */
-       0,                      /* mslimb first: false for BNs */
-       -1,                     /* msbyte first: use native */
-       0,                      /* Max mutexes, 0 = no small limit */
-       0,                      /* Max simultaneous, 0 = default */
-
-       /* The next few are mutex stuff: we write wrapper functions
-          around the OS mutex functions.  We initialise them to 0
-          here, and change that to actual function pointers in hwcrhk_init()
-          if dynamic locks are supported (that is, if the application
-          programmer has made sure of setting up callbacks bafore starting
-          this engine) *and* if disable_mutex_callbacks hasn't been set by
-          a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
-       sizeof(HWCryptoHook_Mutex),
-       0,
-       0,
-       0,
-       0,
-
-       /* The next few are condvar stuff: we write wrapper functions
-          round the OS functions.  Currently not implemented and not
-          and absolute necessity even in threaded programs, therefore
-          0'ed.  Will hopefully be implemented some day, since it
-          enhances the efficiency of HWCryptoHook.  */
-       0, /* sizeof(HWCryptoHook_CondVar), */
-       0, /* hwcrhk_cv_init, */
-       0, /* hwcrhk_cv_wait, */
-       0, /* hwcrhk_cv_signal, */
-       0, /* hwcrhk_cv_broadcast, */
-       0, /* hwcrhk_cv_destroy, */
-
-       hwcrhk_get_pass,        /* pass phrase */
-       hwcrhk_insert_card,     /* insert a card */
-       hwcrhk_log_message      /* Log message */
+    HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
+    &logstream,                 /* logstream */
+    sizeof(BN_ULONG),           /* limbsize */
+    0,                          /* mslimb first: false for BNs */
+    -1,                         /* msbyte first: use native */
+    0,                          /* Max mutexes, 0 = no small limit */
+    0,                          /* Max simultaneous, 0 = default */
+
+    /*
+     * The next few are mutex stuff: we write wrapper functions around the OS
+     * mutex functions.  We initialise them to 0 here, and change that to
+     * actual function pointers in hwcrhk_init() if dynamic locks are
+     * supported (that is, if the application programmer has made sure of
+     * setting up callbacks bafore starting this engine) *and* if
+     * disable_mutex_callbacks hasn't been set by a call to
+     * ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING).
+     */
+    sizeof(HWCryptoHook_Mutex),
+    0,
+    0,
+    0,
+    0,
+
+    /*
+     * The next few are condvar stuff: we write wrapper functions round the
+     * OS functions.  Currently not implemented and not and absolute
+     * necessity even in threaded programs, therefore 0'ed.  Will hopefully
+     * be implemented some day, since it enhances the efficiency of
+     * HWCryptoHook.
+     */
+    0,                          /* sizeof(HWCryptoHook_CondVar), */
+    0,                          /* hwcrhk_cv_init, */
+    0,                          /* hwcrhk_cv_wait, */
+    0,                          /* hwcrhk_cv_signal, */
+    0,                          /* hwcrhk_cv_broadcast, */
+    0,                          /* hwcrhk_cv_destroy, */
+
+    hwcrhk_get_pass,            /* pass phrase */
+    hwcrhk_insert_card,         /* insert a card */
+    hwcrhk_log_message          /* Log message */
 };
 
-
 /* Now, to our own code */
 
-/* This internal function is used by ENGINE_chil() and possibly by the
- * "dynamic" ENGINE support too */
+/*
+ * This internal function is used by ENGINE_chil() and possibly by the
+ * "dynamic" ENGINE support too
+ */
 static int bind_helper(ENGINE *e)
-       {
-#ifndef OPENSSL_NO_RSA
-       const RSA_METHOD *meth1;
-#endif
-#ifndef OPENSSL_NO_DH
-       const DH_METHOD *meth2;
-#endif
-       if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
-                       !ENGINE_set_name(e, engine_hwcrhk_name) ||
-#ifndef OPENSSL_NO_RSA
-                       !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
-#endif
-#ifndef OPENSSL_NO_DH
-                       !ENGINE_set_DH(e, &hwcrhk_dh) ||
-#endif
-                       !ENGINE_set_RAND(e, &hwcrhk_rand) ||
-                       !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
-                       !ENGINE_set_init_function(e, hwcrhk_init) ||
-                       !ENGINE_set_finish_function(e, hwcrhk_finish) ||
-                       !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
-                       !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
-                       !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
-                       !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
-               return 0;
-
-#ifndef OPENSSL_NO_RSA
-       /* We know that the "PKCS1_SSLeay()" functions hook properly
-        * to the cswift-specific mod_exp and mod_exp_crt so we use
-        * those functions. NB: We don't use ENGINE_openssl() or
-        * anything "more generic" because something like the RSAref
-        * code may not hook properly, and if you own one of these
-        * cards then you have the right to do RSA operations on it
-        * anyway! */ 
-       meth1 = RSA_PKCS1_SSLeay();
-       hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
-       hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
-       hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
-       hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
-#endif
-
-#ifndef OPENSSL_NO_DH
-       /* Much the same for Diffie-Hellman */
-       meth2 = DH_OpenSSL();
-       hwcrhk_dh.generate_key = meth2->generate_key;
-       hwcrhk_dh.compute_key = meth2->compute_key;
-#endif
-
-       /* Ensure the hwcrhk error handling is set up */
-       ERR_load_HWCRHK_strings();
-       return 1;
-       }
+{
+#  ifndef OPENSSL_NO_RSA
+    const RSA_METHOD *meth1;
+#  endif
+#  ifndef OPENSSL_NO_DH
+    const DH_METHOD *meth2;
+#  endif
+    if (!ENGINE_set_id(e, engine_hwcrhk_id) ||
+        !ENGINE_set_name(e, engine_hwcrhk_name) ||
+#  ifndef OPENSSL_NO_RSA
+        !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
+#  endif
+#  ifndef OPENSSL_NO_DH
+        !ENGINE_set_DH(e, &hwcrhk_dh) ||
+#  endif
+        !ENGINE_set_RAND(e, &hwcrhk_rand) ||
+        !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
+        !ENGINE_set_init_function(e, hwcrhk_init) ||
+        !ENGINE_set_finish_function(e, hwcrhk_finish) ||
+        !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
+        !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
+        !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
+        !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
+        return 0;
+
+#  ifndef OPENSSL_NO_RSA
+    /*
+     * We know that the "PKCS1_SSLeay()" functions hook properly to the
+     * cswift-specific mod_exp and mod_exp_crt so we use those functions. NB:
+     * We don't use ENGINE_openssl() or anything "more generic" because
+     * something like the RSAref code may not hook properly, and if you own
+     * one of these cards then you have the right to do RSA operations on it
+     * anyway!
+     */
+    meth1 = RSA_PKCS1_SSLeay();
+    hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
+    hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
+    hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
+    hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
+#  endif
+
+#  ifndef OPENSSL_NO_DH
+    /* Much the same for Diffie-Hellman */
+    meth2 = DH_OpenSSL();
+    hwcrhk_dh.generate_key = meth2->generate_key;
+    hwcrhk_dh.compute_key = meth2->compute_key;
+#  endif
+
+    /* Ensure the hwcrhk error handling is set up */
+    ERR_load_HWCRHK_strings();
+    return 1;
+}
 
-#ifdef OPENSSL_NO_DYNAMIC_ENGINE
+#  ifdef OPENSSL_NO_DYNAMIC_ENGINE
 static ENGINE *engine_chil(void)
-       {
-       ENGINE *ret = ENGINE_new();
-       if(!ret)
-               return NULL;
-       if(!bind_helper(ret))
-               {
-               ENGINE_free(ret);
-               return NULL;
-               }
-       return ret;
-       }
+{
+    ENGINE *ret = ENGINE_new();
+    if (!ret)
+        return NULL;
+    if (!bind_helper(ret)) {
+        ENGINE_free(ret);
+        return NULL;
+    }
+    return ret;
+}
 
 void ENGINE_load_chil(void)
-       {
-       /* Copied from eng_[openssl|dyn].c */
-       ENGINE *toadd = engine_chil();
-       if(!toadd) return;
-       ENGINE_add(toadd);
-       ENGINE_free(toadd);
-       ERR_clear_error();
-       }
-#endif
+{
+    /* Copied from eng_[openssl|dyn].c */
+    ENGINE *toadd = engine_chil();
+    if (!toadd)
+        return;
+    ENGINE_add(toadd);
+    ENGINE_free(toadd);
+    ERR_clear_error();
+}
+#  endif
 
-/* This is a process-global DSO handle used for loading and unloading
- * the HWCryptoHook library. NB: This is only set (or unset) during an
- * init() or finish() call (reference counts permitting) and they're
- * operating with global locks, so this should be thread-safe
- * implicitly. */
+/*
+ * This is a process-global DSO handle used for loading and unloading the
+ * HWCryptoHook library. NB: This is only set (or unset) during an init() or
+ * finish() call (reference counts permitting) and they're operating with
+ * global locks, so this should be thread-safe implicitly.
+ */
 static DSO *hwcrhk_dso = NULL;
 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
-#ifndef OPENSSL_NO_RSA
-static int hndidx_rsa = -1;    /* Index for KM handle.  Not really used yet. */
-#endif
-
-/* These are the function pointers that are (un)set when the library has
- * successfully (un)loaded. */
+#  ifndef OPENSSL_NO_RSA
+/* Index for KM handle.  Not really used yet. */
+static int hndidx_rsa = -1;
+#  endif
+
+/*
+ * These are the function pointers that are (un)set when the library has
+ * successfully (un)loaded.
+ */
 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
-#ifndef OPENSSL_NO_RSA
+#  ifndef OPENSSL_NO_RSA
 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
-#endif
+#  endif
 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
-#ifndef OPENSSL_NO_RSA
+#  ifndef OPENSSL_NO_RSA
 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
-#endif
+#  endif
 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
 
 /* Used in the DSO operations. */
 static const char *HWCRHK_LIBNAME = NULL;
 static void free_HWCRHK_LIBNAME(void)
-       {
-       if(HWCRHK_LIBNAME)
-               OPENSSL_free((void*)HWCRHK_LIBNAME);
-       HWCRHK_LIBNAME = NULL;
-       }
+{
+    if (HWCRHK_LIBNAME)
+        OPENSSL_free((void *)HWCRHK_LIBNAME);
+    HWCRHK_LIBNAME = NULL;
+}
+
 static const char *get_HWCRHK_LIBNAME(void)
-       {
-       if(HWCRHK_LIBNAME)
-               return HWCRHK_LIBNAME;
-       return "nfhwcrhk";
-       }
+{
+    if (HWCRHK_LIBNAME)
+        return HWCRHK_LIBNAME;
+    return "nfhwcrhk";
+}
+
 static long set_HWCRHK_LIBNAME(const char *name)
-       {
-       free_HWCRHK_LIBNAME();
-       return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
-       }
+{
+    free_HWCRHK_LIBNAME();
+    return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
+}
+
 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
-#ifndef OPENSSL_NO_RSA
+#  ifndef OPENSSL_NO_RSA
 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
-#endif
+#  endif
 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
-#ifndef OPENSSL_NO_RSA
+#  ifndef OPENSSL_NO_RSA
 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
-#endif
+#  endif
 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
 
-/* HWCryptoHook library functions and mechanics - these are used by the
- * higher-level functions further down. NB: As and where there's no
- * error checking, take a look lower down where these functions are
- * called, the checking and error handling is probably down there. */
+/*
+ * HWCryptoHook library functions and mechanics - these are used by the
+ * higher-level functions further down. NB: As and where there's no error
+ * checking, take a look lower down where these functions are called, the
+ * checking and error handling is probably down there.
+ */
 
 /* utility function to obtain a context */
-static int get_context(HWCryptoHook_ContextHandle *hac,
-        HWCryptoHook_CallerContext *cac)
-       {
-       char tempbuf[1024];
-       HWCryptoHook_ErrMsgBuf rmsg;
-
-       rmsg.buf = tempbuf;
-       rmsg.size = sizeof(tempbuf);
-
-        *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
-               cac);
-       if (!*hac)
-                return 0;
-        return 1;
-       }
+static int get_context(HWCryptoHook_ContextHandle * hac,
+                       HWCryptoHook_CallerContext * cac)
+{
+    char tempbuf[1024];
+    HWCryptoHook_ErrMsgBuf rmsg;
+
+    rmsg.buf = tempbuf;
+    rmsg.size = sizeof(tempbuf);
+
+    *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg, cac);
+    if (!*hac)
+        return 0;
+    return 1;
+}
+
 /* similarly to release one. */
 static void release_context(HWCryptoHook_ContextHandle hac)
-       {
-       p_hwcrhk_Finish(hac);
-       }
+{
+    p_hwcrhk_Finish(hac);
+}
 
 /* Destructor (complements the "ENGINE_chil()" constructor) */
 static int hwcrhk_destroy(ENGINE *e)
-       {
-       free_HWCRHK_LIBNAME();
-       ERR_unload_HWCRHK_strings();
-       return 1;
-       }
+{
+    free_HWCRHK_LIBNAME();
+    ERR_unload_HWCRHK_strings();
+    return 1;
+}
 
 /* (de)initialisation functions. */
 static int hwcrhk_init(ENGINE *e)
-       {
-       HWCryptoHook_Init_t *p1;
-       HWCryptoHook_Finish_t *p2;
-       HWCryptoHook_ModExp_t *p3;
-#ifndef OPENSSL_NO_RSA
-       HWCryptoHook_RSA_t *p4;
-       HWCryptoHook_RSALoadKey_t *p5;
-       HWCryptoHook_RSAGetPublicKey_t *p6;
-       HWCryptoHook_RSAUnloadKey_t *p7;
-#endif
-       HWCryptoHook_RandomBytes_t *p8;
-       HWCryptoHook_ModExpCRT_t *p9;
-
-       if(hwcrhk_dso != NULL)
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
-               goto err;
-               }
-       /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
-       hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
-       if(hwcrhk_dso == NULL)
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
-               goto err;
-               }
-       if(!(p1 = (HWCryptoHook_Init_t *)
-                       DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
-               !(p2 = (HWCryptoHook_Finish_t *)
-                       DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
-               !(p3 = (HWCryptoHook_ModExp_t *)
-                       DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
-#ifndef OPENSSL_NO_RSA
-               !(p4 = (HWCryptoHook_RSA_t *)
-                       DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
-               !(p5 = (HWCryptoHook_RSALoadKey_t *)
-                       DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
-               !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
-                       DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
-               !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
-                       DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
-#endif
-               !(p8 = (HWCryptoHook_RandomBytes_t *)
-                       DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
-               !(p9 = (HWCryptoHook_ModExpCRT_t *)
-                       DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
-               goto err;
-               }
-       /* Copy the pointers */
-       p_hwcrhk_Init = p1;
-       p_hwcrhk_Finish = p2;
-       p_hwcrhk_ModExp = p3;
-#ifndef OPENSSL_NO_RSA
-       p_hwcrhk_RSA = p4;
-       p_hwcrhk_RSALoadKey = p5;
-       p_hwcrhk_RSAGetPublicKey = p6;
-       p_hwcrhk_RSAUnloadKey = p7;
-#endif
-       p_hwcrhk_RandomBytes = p8;
-       p_hwcrhk_ModExpCRT = p9;
-
-       /* Check if the application decided to support dynamic locks,
-          and if it does, use them. */
-       if (disable_mutex_callbacks == 0)
-               {
-               if (CRYPTO_get_dynlock_create_callback() != NULL &&
-                       CRYPTO_get_dynlock_lock_callback() != NULL &&
-                       CRYPTO_get_dynlock_destroy_callback() != NULL)
-                       {
-                       hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
-                       hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
-                       hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
-                       hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
-                       }
-               }
-
-       /* Try and get a context - if not, we may have a DSO but no
-        * accelerator! */
-       if(!get_context(&hwcrhk_context, &password_context))
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
-               goto err;
-               }
-       /* Everything's fine. */
-#ifndef OPENSSL_NO_RSA
-       if (hndidx_rsa == -1)
-               hndidx_rsa = RSA_get_ex_new_index(0,
-                       "nFast HWCryptoHook RSA key handle",
-                       NULL, NULL, hwcrhk_ex_free);
-#endif
-       return 1;
-err:
-       if(hwcrhk_dso)
-               DSO_free(hwcrhk_dso);
-       hwcrhk_dso = NULL;
-       p_hwcrhk_Init = NULL;
-       p_hwcrhk_Finish = NULL;
-       p_hwcrhk_ModExp = NULL;
-#ifndef OPENSSL_NO_RSA
-       p_hwcrhk_RSA = NULL;
-       p_hwcrhk_RSALoadKey = NULL;
-       p_hwcrhk_RSAGetPublicKey = NULL;
-       p_hwcrhk_RSAUnloadKey = NULL;
-#endif
-       p_hwcrhk_ModExpCRT = NULL;
-       p_hwcrhk_RandomBytes = NULL;
-       return 0;
-       }
+{
+    HWCryptoHook_Init_t *p1;
+    HWCryptoHook_Finish_t *p2;
+    HWCryptoHook_ModExp_t *p3;
+#  ifndef OPENSSL_NO_RSA
+    HWCryptoHook_RSA_t *p4;
+    HWCryptoHook_RSALoadKey_t *p5;
+    HWCryptoHook_RSAGetPublicKey_t *p6;
+    HWCryptoHook_RSAUnloadKey_t *p7;
+#  endif
+    HWCryptoHook_RandomBytes_t *p8;
+    HWCryptoHook_ModExpCRT_t *p9;
+
+    if (hwcrhk_dso != NULL) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_ALREADY_LOADED);
+        goto err;
+    }
+    /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
+    hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
+    if (hwcrhk_dso == NULL) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE);
+        goto err;
+    }
+    if (!(p1 = (HWCryptoHook_Init_t *)
+          DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
+        !(p2 = (HWCryptoHook_Finish_t *)
+          DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
+        !(p3 = (HWCryptoHook_ModExp_t *)
+          DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
+#  ifndef OPENSSL_NO_RSA
+        !(p4 = (HWCryptoHook_RSA_t *)
+          DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
+        !(p5 = (HWCryptoHook_RSALoadKey_t *)
+          DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
+        !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
+          DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
+        !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
+          DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
+#  endif
+        !(p8 = (HWCryptoHook_RandomBytes_t *)
+          DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
+        !(p9 = (HWCryptoHook_ModExpCRT_t *)
+          DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT))) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE);
+        goto err;
+    }
+    /* Copy the pointers */
+    p_hwcrhk_Init = p1;
+    p_hwcrhk_Finish = p2;
+    p_hwcrhk_ModExp = p3;
+#  ifndef OPENSSL_NO_RSA
+    p_hwcrhk_RSA = p4;
+    p_hwcrhk_RSALoadKey = p5;
+    p_hwcrhk_RSAGetPublicKey = p6;
+    p_hwcrhk_RSAUnloadKey = p7;
+#  endif
+    p_hwcrhk_RandomBytes = p8;
+    p_hwcrhk_ModExpCRT = p9;
+
+    /*
+     * Check if the application decided to support dynamic locks, and if it
+     * does, use them.
+     */
+    if (disable_mutex_callbacks == 0) {
+        if (CRYPTO_get_dynlock_create_callback() != NULL &&
+            CRYPTO_get_dynlock_lock_callback() != NULL &&
+            CRYPTO_get_dynlock_destroy_callback() != NULL) {
+            hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
+            hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
+            hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
+            hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
+        }
+    }
+
+    /*
+     * Try and get a context - if not, we may have a DSO but no accelerator!
+     */
+    if (!get_context(&hwcrhk_context, &password_context)) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_UNIT_FAILURE);
+        goto err;
+    }
+    /* Everything's fine. */
+#  ifndef OPENSSL_NO_RSA
+    if (hndidx_rsa == -1)
+        hndidx_rsa = RSA_get_ex_new_index(0,
+                                          "nFast HWCryptoHook RSA key handle",
+                                          NULL, NULL, NULL);
+#  endif
+    return 1;
+ err:
+    if (hwcrhk_dso)
+        DSO_free(hwcrhk_dso);
+    hwcrhk_dso = NULL;
+    p_hwcrhk_Init = NULL;
+    p_hwcrhk_Finish = NULL;
+    p_hwcrhk_ModExp = NULL;
+#  ifndef OPENSSL_NO_RSA
+    p_hwcrhk_RSA = NULL;
+    p_hwcrhk_RSALoadKey = NULL;
+    p_hwcrhk_RSAGetPublicKey = NULL;
+    p_hwcrhk_RSAUnloadKey = NULL;
+#  endif
+    p_hwcrhk_ModExpCRT = NULL;
+    p_hwcrhk_RandomBytes = NULL;
+    return 0;
+}
 
 static int hwcrhk_finish(ENGINE *e)
-       {
-       int to_return = 1;
-       free_HWCRHK_LIBNAME();
-       if(hwcrhk_dso == NULL)
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
-               to_return = 0;
-               goto err;
-               }
-       release_context(hwcrhk_context);
-       if(!DSO_free(hwcrhk_dso))
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
-               to_return = 0;
-               goto err;
-               }
+{
+    int to_return = 1;
+    free_HWCRHK_LIBNAME();
+    if (hwcrhk_dso == NULL) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_NOT_LOADED);
+        to_return = 0;
+        goto err;
+    }
+    release_context(hwcrhk_context);
+    if (!DSO_free(hwcrhk_dso)) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_DSO_FAILURE);
+        to_return = 0;
+        goto err;
+    }
  err:
-       if (logstream)
-               BIO_free(logstream);
-       hwcrhk_dso = NULL;
-       p_hwcrhk_Init = NULL;
-       p_hwcrhk_Finish = NULL;
-       p_hwcrhk_ModExp = NULL;
-#ifndef OPENSSL_NO_RSA
-       p_hwcrhk_RSA = NULL;
-       p_hwcrhk_RSALoadKey = NULL;
-       p_hwcrhk_RSAGetPublicKey = NULL;
-       p_hwcrhk_RSAUnloadKey = NULL;
-#endif
-       p_hwcrhk_ModExpCRT = NULL;
-       p_hwcrhk_RandomBytes = NULL;
-       return to_return;
-       }
-
-static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
-       {
-       int to_return = 1;
-
-       switch(cmd)
-               {
-       case HWCRHK_CMD_SO_PATH:
-               if(hwcrhk_dso)
-                       {
-                       HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
-                       return 0;
-                       }
-               if(p == NULL)
-                       {
-                       HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
-                       return 0;
-                       }
-               return set_HWCRHK_LIBNAME((const char *)p);
-       case ENGINE_CTRL_SET_LOGSTREAM:
-               {
-               BIO *bio = (BIO *)p;
-
-               CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
-               if (logstream)
-                       {
-                       BIO_free(logstream);
-                       logstream = NULL;
-                       }
-               if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
-                       logstream = bio;
-               else
-                       HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
-               }
-               CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
-               break;
-       case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
-               CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
-               password_context.password_callback = (pem_password_cb *)f;
-               CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
-               break;
-       case ENGINE_CTRL_SET_USER_INTERFACE:
-       case HWCRHK_CMD_SET_USER_INTERFACE:
-               CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
-               password_context.ui_method = (UI_METHOD *)p;
-               CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
-               break;
-       case ENGINE_CTRL_SET_CALLBACK_DATA:
-       case HWCRHK_CMD_SET_CALLBACK_DATA:
-               CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
-               password_context.callback_data = p;
-               CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
-               break;
-       /* this enables or disables the "SimpleForkCheck" flag used in the
-        * initialisation structure. */
-       case ENGINE_CTRL_CHIL_SET_FORKCHECK:
-       case HWCRHK_CMD_FORK_CHECK:
-               CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
-               if(i)
-                       hwcrhk_globals.flags |=
-                               HWCryptoHook_InitFlags_SimpleForkCheck;
-               else
-                       hwcrhk_globals.flags &=
-                               ~HWCryptoHook_InitFlags_SimpleForkCheck;
-               CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
-               break;
-       /* This will prevent the initialisation function from "installing"
-        * the mutex-handling callbacks, even if they are available from
-        * within the library (or were provided to the library from the
-        * calling application). This is to remove any baggage for
-        * applications not using multithreading. */
-       case ENGINE_CTRL_CHIL_NO_LOCKING:
-               CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
-               disable_mutex_callbacks = 1;
-               CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
-               break;
-       case HWCRHK_CMD_THREAD_LOCKING:
-               CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
-               disable_mutex_callbacks = ((i == 0) ? 0 : 1);
-               CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
-               break;
-
-       /* The command isn't understood by this engine */
-       default:
-               HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
-                       HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
-               to_return = 0;
-               break;
-               }
-
-       return to_return;
-       }
-
-static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
-       UI_METHOD *ui_method, void *callback_data)
-       {
-#ifndef OPENSSL_NO_RSA
-       RSA *rtmp = NULL;
-#endif
-       EVP_PKEY *res = NULL;
-#ifndef OPENSSL_NO_RSA
-       HWCryptoHook_MPI e, n;
-       HWCryptoHook_RSAKeyHandle *hptr;
-#endif
-#if !defined(OPENSSL_NO_RSA)
-       char tempbuf[1024];
-       HWCryptoHook_ErrMsgBuf rmsg;
-       HWCryptoHook_PassphraseContext ppctx;
-#endif
-
-#if !defined(OPENSSL_NO_RSA)
-       rmsg.buf = tempbuf;
-       rmsg.size = sizeof(tempbuf);
-#endif
-
-       if(!hwcrhk_context)
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
-                       HWCRHK_R_NOT_INITIALISED);
-               goto err;
-               }
-#ifndef OPENSSL_NO_RSA
-       hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
-       if (!hptr)
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
-                       ERR_R_MALLOC_FAILURE);
-               goto err;
-               }
-        ppctx.ui_method = ui_method;
-       ppctx.callback_data = callback_data;
-       if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
-               &rmsg, &ppctx))
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
-                       HWCRHK_R_CHIL_ERROR);
-               ERR_add_error_data(1,rmsg.buf);
-               goto err;
-               }
-       if (!*hptr)
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
-                       HWCRHK_R_NO_KEY);
-               goto err;
-               }
-#endif
-#ifndef OPENSSL_NO_RSA
-       rtmp = RSA_new_method(eng);
-       RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
-       rtmp->e = BN_new();
-       rtmp->n = BN_new();
-       rtmp->flags |= RSA_FLAG_EXT_PKEY;
-       MPI2BN(rtmp->e, e);
-       MPI2BN(rtmp->n, n);
-       if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
-               != HWCRYPTOHOOK_ERROR_MPISIZE)
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,HWCRHK_R_CHIL_ERROR);
-               ERR_add_error_data(1,rmsg.buf);
-               goto err;
-               }
-
-       bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
-       bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
-       MPI2BN(rtmp->e, e);
-       MPI2BN(rtmp->n, n);
-
-       if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
-                       HWCRHK_R_CHIL_ERROR);
-               ERR_add_error_data(1,rmsg.buf);
-               goto err;
-               }
-       rtmp->e->top = e.size / sizeof(BN_ULONG);
-       bn_fix_top(rtmp->e);
-       rtmp->n->top = n.size / sizeof(BN_ULONG);
-       bn_fix_top(rtmp->n);
-
-       res = EVP_PKEY_new();
-       EVP_PKEY_assign_RSA(res, rtmp);
-#endif
+    if (logstream)
+        BIO_free(logstream);
+    hwcrhk_dso = NULL;
+    p_hwcrhk_Init = NULL;
+    p_hwcrhk_Finish = NULL;
+    p_hwcrhk_ModExp = NULL;
+#  ifndef OPENSSL_NO_RSA
+    p_hwcrhk_RSA = NULL;
+    p_hwcrhk_RSALoadKey = NULL;
+    p_hwcrhk_RSAGetPublicKey = NULL;
+    p_hwcrhk_RSAUnloadKey = NULL;
+#  endif
+    p_hwcrhk_ModExpCRT = NULL;
+    p_hwcrhk_RandomBytes = NULL;
+    return to_return;
+}
 
-        if (!res)
-                HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
-                        HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
+static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
+{
+    int to_return = 1;
+
+    switch (cmd) {
+    case HWCRHK_CMD_SO_PATH:
+        if (hwcrhk_dso) {
+            HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_ALREADY_LOADED);
+            return 0;
+        }
+        if (p == NULL) {
+            HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, ERR_R_PASSED_NULL_PARAMETER);
+            return 0;
+        }
+        return set_HWCRHK_LIBNAME((const char *)p);
+    case ENGINE_CTRL_SET_LOGSTREAM:
+        {
+            BIO *bio = (BIO *)p;
+
+            CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+            if (logstream) {
+                BIO_free(logstream);
+                logstream = NULL;
+            }
+            if (CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO) > 1)
+                logstream = bio;
+            else
+                HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_BIO_WAS_FREED);
+        }
+        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+        break;
+    case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
+        CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+        password_context.password_callback = (pem_password_cb *)f;
+        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+        break;
+    case ENGINE_CTRL_SET_USER_INTERFACE:
+    case HWCRHK_CMD_SET_USER_INTERFACE:
+        CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+        password_context.ui_method = (UI_METHOD *)p;
+        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+        break;
+    case ENGINE_CTRL_SET_CALLBACK_DATA:
+    case HWCRHK_CMD_SET_CALLBACK_DATA:
+        CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+        password_context.callback_data = p;
+        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+        break;
+        /*
+         * this enables or disables the "SimpleForkCheck" flag used in the
+         * initialisation structure.
+         */
+    case ENGINE_CTRL_CHIL_SET_FORKCHECK:
+    case HWCRHK_CMD_FORK_CHECK:
+        CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+        if (i)
+            hwcrhk_globals.flags |= HWCryptoHook_InitFlags_SimpleForkCheck;
+        else
+            hwcrhk_globals.flags &= ~HWCryptoHook_InitFlags_SimpleForkCheck;
+        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+        break;
+        /*
+         * This will prevent the initialisation function from "installing"
+         * the mutex-handling callbacks, even if they are available from
+         * within the library (or were provided to the library from the
+         * calling application). This is to remove any baggage for
+         * applications not using multithreading.
+         */
+    case ENGINE_CTRL_CHIL_NO_LOCKING:
+        CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+        disable_mutex_callbacks = 1;
+        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+        break;
+    case HWCRHK_CMD_THREAD_LOCKING:
+        CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+        disable_mutex_callbacks = ((i == 0) ? 0 : 1);
+        CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+        break;
+
+        /* The command isn't understood by this engine */
+    default:
+        HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
+                  HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+        to_return = 0;
+        break;
+    }
+
+    return to_return;
+}
 
-       return res;
+static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
+                                     UI_METHOD *ui_method,
+                                     void *callback_data)
+{
+#  ifndef OPENSSL_NO_RSA
+    RSA *rtmp = NULL;
+#  endif
+    EVP_PKEY *res = NULL;
+#  ifndef OPENSSL_NO_RSA
+    HWCryptoHook_MPI e, n;
+    HWCryptoHook_RSAKeyHandle *hptr;
+#  endif
+#  if !defined(OPENSSL_NO_RSA)
+    char tempbuf[1024];
+    HWCryptoHook_ErrMsgBuf rmsg;
+    HWCryptoHook_PassphraseContext ppctx;
+#  endif
+
+#  if !defined(OPENSSL_NO_RSA)
+    rmsg.buf = tempbuf;
+    rmsg.size = sizeof(tempbuf);
+#  endif
+
+    if (!hwcrhk_context) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NOT_INITIALISED);
+        goto err;
+    }
+#  ifndef OPENSSL_NO_RSA
+    hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
+    if (!hptr) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    ppctx.ui_method = ui_method;
+    ppctx.callback_data = callback_data;
+    if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr, &rmsg, &ppctx)) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
+        ERR_add_error_data(1, rmsg.buf);
+        goto err;
+    }
+    if (!*hptr) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NO_KEY);
+        goto err;
+    }
+#  endif
+#  ifndef OPENSSL_NO_RSA
+    rtmp = RSA_new_method(eng);
+    if (rtmp == NULL) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
+    rtmp->e = BN_new();
+    rtmp->n = BN_new();
+    if (rtmp->e == NULL || rtmp->n == NULL) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    rtmp->flags |= RSA_FLAG_EXT_PKEY;
+    MPI2BN(rtmp->e, e);
+    MPI2BN(rtmp->n, n);
+    if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
+        != HWCRYPTOHOOK_ERROR_MPISIZE) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
+        ERR_add_error_data(1, rmsg.buf);
+        goto err;
+    }
+
+    if (bn_expand2(rtmp->e, e.size / sizeof(BN_ULONG)) == NULL) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    if (bn_expand2(rtmp->n, n.size / sizeof(BN_ULONG)) == NULL) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    MPI2BN(rtmp->e, e);
+    MPI2BN(rtmp->n, n);
+
+    if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
+        ERR_add_error_data(1, rmsg.buf);
+        goto err;
+    }
+    rtmp->e->top = e.size / sizeof(BN_ULONG);
+    bn_fix_top(rtmp->e);
+    rtmp->n->top = n.size / sizeof(BN_ULONG);
+    bn_fix_top(rtmp->n);
+
+    res = EVP_PKEY_new();
+    if (res == NULL) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
+        goto err;
+    }
+    EVP_PKEY_assign_RSA(res, rtmp);
+#  endif
+
+    if (!res)
+        HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
+                  HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
+
+    return res;
  err:
-#ifndef OPENSSL_NO_RSA
-       if (rtmp)
-               RSA_free(rtmp);
-#endif
-       return NULL;
-       }
+#  ifndef OPENSSL_NO_RSA
+    if (rtmp)
+        RSA_free(rtmp);
+#  endif
+    return NULL;
+}
 
 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
-       UI_METHOD *ui_method, void *callback_data)
-       {
-       EVP_PKEY *res = NULL;
-
-#ifndef OPENSSL_NO_RSA
-        res = hwcrhk_load_privkey(eng, key_id,
-                ui_method, callback_data);
-#endif
-
-       if (res)
-               switch(res->type)
-                       {
-#ifndef OPENSSL_NO_RSA
-               case EVP_PKEY_RSA:
-                       {
-                       RSA *rsa = NULL;
-
-                       CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
-                       rsa = res->pkey.rsa;
-                       res->pkey.rsa = RSA_new();
-                       res->pkey.rsa->n = rsa->n;
-                       res->pkey.rsa->e = rsa->e;
-                       rsa->n = NULL;
-                       rsa->e = NULL;
-                       CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
-                       RSA_free(rsa);
-                       }
-                       break;
-#endif
-               default:
-                       HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
-                               HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
-                       goto err;
-                       }
-
-       return res;
+                                    UI_METHOD *ui_method, void *callback_data)
+{
+    EVP_PKEY *res = NULL;
+
+#  ifndef OPENSSL_NO_RSA
+    res = hwcrhk_load_privkey(eng, key_id, ui_method, callback_data);
+#  endif
+
+    if (res)
+        switch (res->type) {
+#  ifndef OPENSSL_NO_RSA
+        case EVP_PKEY_RSA:
+            {
+                RSA *rsa = NULL;
+
+                CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
+                rsa = res->pkey.rsa;
+                res->pkey.rsa = RSA_new();
+                res->pkey.rsa->n = rsa->n;
+                res->pkey.rsa->e = rsa->e;
+                rsa->n = NULL;
+                rsa->e = NULL;
+                CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
+                RSA_free(rsa);
+            }
+            break;
+#  endif
+        default:
+            HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
+                      HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+            goto err;
+        }
+
+    return res;
  err:
-       if (res)
-               EVP_PKEY_free(res);
-       return NULL;
-       }
+    if (res)
+        EVP_PKEY_free(res);
+    return NULL;
+}
 
 /* A little mod_exp */
 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
-                       const BIGNUM *m, BN_CTX *ctx)
-       {
-       char tempbuf[1024];
-       HWCryptoHook_ErrMsgBuf rmsg;
-       /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
-          we use them directly, plus a little macro magic.  We only
-          thing we need to make sure of is that enough space is allocated. */
-       HWCryptoHook_MPI m_a, m_p, m_n, m_r;
-       int to_return, ret;
-       to_return = 0; /* expect failure */
-       rmsg.buf = tempbuf;
-       rmsg.size = sizeof(tempbuf);
-
-       if(!hwcrhk_context)
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
-               goto err;
-               }
-       /* Prepare the params */
-       bn_expand2(r, m->top);  /* Check for error !! */
-       BN2MPI(m_a, a);
-       BN2MPI(m_p, p);
-       BN2MPI(m_n, m);
-       MPI2BN(r, m_r);
-
-       /* Perform the operation */
-       ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
-
-       /* Convert the response */
-       r->top = m_r.size / sizeof(BN_ULONG);
-       bn_fix_top(r);
-
-       if (ret < 0)
-               {
-               /* FIXME: When this error is returned, HWCryptoHook is
-                  telling us that falling back to software computation
-                  might be a good thing. */
-               if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
-                       {
-                       HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
-                       }
-               else
-                       {
-                       HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
-                       }
-               ERR_add_error_data(1,rmsg.buf);
-               goto err;
-               }
-
-       to_return = 1;
-err:
-       return to_return;
-       }
-
-#ifndef OPENSSL_NO_RSA 
-static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
-       {
-       char tempbuf[1024];
-       HWCryptoHook_ErrMsgBuf rmsg;
-       HWCryptoHook_RSAKeyHandle *hptr;
-       int to_return = 0, ret;
-
-       rmsg.buf = tempbuf;
-       rmsg.size = sizeof(tempbuf);
-
-       if(!hwcrhk_context)
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
-               goto err;
-               }
-
-       /* This provides support for nForce keys.  Since that's opaque data
-          all we do is provide a handle to the proper key and let HWCryptoHook
-          take care of the rest. */
-       if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
-               != NULL)
-               {
-               HWCryptoHook_MPI m_a, m_r;
-
-               if(!rsa->n)
-                       {
-                       HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
-                               HWCRHK_R_MISSING_KEY_COMPONENTS);
-                       goto err;
-                       }
-
-               /* Prepare the params */
-               bn_expand2(r, rsa->n->top); /* Check for error !! */
-               BN2MPI(m_a, I);
-               MPI2BN(r, m_r);
-
-               /* Perform the operation */
-               ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
-
-               /* Convert the response */
-               r->top = m_r.size / sizeof(BN_ULONG);
-               bn_fix_top(r);
-
-               if (ret < 0)
-                       {
-                       /* FIXME: When this error is returned, HWCryptoHook is
-                          telling us that falling back to software computation
-                          might be a good thing. */
-                       if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
-                               {
-                               HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
-                                       HWCRHK_R_REQUEST_FALLBACK);
-                               }
-                       else
-                               {
-                               HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
-                                       HWCRHK_R_REQUEST_FAILED);
-                               }
-                       ERR_add_error_data(1,rmsg.buf);
-                       goto err;
-                       }
-               }
-       else
-               {
-               HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
-
-               if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
-                       {
-                       HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
-                               HWCRHK_R_MISSING_KEY_COMPONENTS);
-                       goto err;
-                       }
-
-               /* Prepare the params */
-               bn_expand2(r, rsa->n->top); /* Check for error !! */
-               BN2MPI(m_a, I);
-               BN2MPI(m_p, rsa->p);
-               BN2MPI(m_q, rsa->q);
-               BN2MPI(m_dmp1, rsa->dmp1);
-               BN2MPI(m_dmq1, rsa->dmq1);
-               BN2MPI(m_iqmp, rsa->iqmp);
-               MPI2BN(r, m_r);
-
-               /* Perform the operation */
-               ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
-                       m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
-
-               /* Convert the response */
-               r->top = m_r.size / sizeof(BN_ULONG);
-               bn_fix_top(r);
-
-               if (ret < 0)
-                       {
-                       /* FIXME: When this error is returned, HWCryptoHook is
-                          telling us that falling back to software computation
-                          might be a good thing. */
-                       if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
-                               {
-                               HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
-                                       HWCRHK_R_REQUEST_FALLBACK);
-                               }
-                       else
-                               {
-                               HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
-                                       HWCRHK_R_REQUEST_FAILED);
-                               }
-                       ERR_add_error_data(1,rmsg.buf);
-                       goto err;
-                       }
-               }
-       /* If we're here, we must be here with some semblance of success :-) */
-       to_return = 1;
-err:
-       return to_return;
-       }
-#endif
+                          const BIGNUM *m, BN_CTX *ctx)
+{
+    char tempbuf[1024];
+    HWCryptoHook_ErrMsgBuf rmsg;
+    /*
+     * Since HWCryptoHook_MPI is pretty compatible with BIGNUM's, we use them
+     * directly, plus a little macro magic.  We only thing we need to make
+     * sure of is that enough space is allocated.
+     */
+    HWCryptoHook_MPI m_a, m_p, m_n, m_r;
+    int to_return, ret;
+
+    to_return = 0;              /* expect failure */
+    rmsg.buf = tempbuf;
+    rmsg.size = sizeof(tempbuf);
+
+    if (!hwcrhk_context) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_NOT_INITIALISED);
+        goto err;
+    }
+    /* Prepare the params */
+    if (bn_expand2(r, m->top) == NULL) {     /* Check for error !! */
+        HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    BN2MPI(m_a, a);
+    BN2MPI(m_p, p);
+    BN2MPI(m_n, m);
+    MPI2BN(r, m_r);
+
+    /* Perform the operation */
+    ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
+
+    /* Convert the response */
+    r->top = m_r.size / sizeof(BN_ULONG);
+    bn_fix_top(r);
+
+    if (ret < 0) {
+        /*
+         * FIXME: When this error is returned, HWCryptoHook is telling us
+         * that falling back to software computation might be a good thing.
+         */
+        if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
+            HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FALLBACK);
+        } else {
+            HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FAILED);
+        }
+        ERR_add_error_data(1, rmsg.buf);
+        goto err;
+    }
+
+    to_return = 1;
+ err:
+    return to_return;
+}
 
-#ifndef OPENSSL_NO_RSA
+#  ifndef OPENSSL_NO_RSA
+static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa,
+                              BN_CTX *ctx)
+{
+    char tempbuf[1024];
+    HWCryptoHook_ErrMsgBuf rmsg;
+    HWCryptoHook_RSAKeyHandle *hptr;
+    int to_return = 0, ret;
+
+    rmsg.buf = tempbuf;
+    rmsg.size = sizeof(tempbuf);
+
+    if (!hwcrhk_context) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, HWCRHK_R_NOT_INITIALISED);
+        goto err;
+    }
+
+    /*
+     * This provides support for nForce keys.  Since that's opaque data all
+     * we do is provide a handle to the proper key and let HWCryptoHook take
+     * care of the rest.
+     */
+    if ((hptr =
+         (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
+        != NULL) {
+        HWCryptoHook_MPI m_a, m_r;
+
+        if (!rsa->n) {
+            HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
+                      HWCRHK_R_MISSING_KEY_COMPONENTS);
+            goto err;
+        }
+
+        /* Prepare the params */
+        if (bn_expand2(r, rsa->n->top) == NULL) { /* Check for error !! */
+            HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        BN2MPI(m_a, I);
+        MPI2BN(r, m_r);
+
+        /* Perform the operation */
+        ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
+
+        /* Convert the response */
+        r->top = m_r.size / sizeof(BN_ULONG);
+        bn_fix_top(r);
+
+        if (ret < 0) {
+            /*
+             * FIXME: When this error is returned, HWCryptoHook is telling us
+             * that falling back to software computation might be a good
+             * thing.
+             */
+            if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
+                HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
+                          HWCRHK_R_REQUEST_FALLBACK);
+            } else {
+                HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
+                          HWCRHK_R_REQUEST_FAILED);
+            }
+            ERR_add_error_data(1, rmsg.buf);
+            goto err;
+        }
+    } else {
+        HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
+
+        if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) {
+            HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
+                      HWCRHK_R_MISSING_KEY_COMPONENTS);
+            goto err;
+        }
+
+        /* Prepare the params */
+        if (bn_expand2(r, rsa->n->top) == NULL) { /* Check for error !! */
+            HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        BN2MPI(m_a, I);
+        BN2MPI(m_p, rsa->p);
+        BN2MPI(m_q, rsa->q);
+        BN2MPI(m_dmp1, rsa->dmp1);
+        BN2MPI(m_dmq1, rsa->dmq1);
+        BN2MPI(m_iqmp, rsa->iqmp);
+        MPI2BN(r, m_r);
+
+        /* Perform the operation */
+        ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
+                                 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
+
+        /* Convert the response */
+        r->top = m_r.size / sizeof(BN_ULONG);
+        bn_fix_top(r);
+
+        if (ret < 0) {
+            /*
+             * FIXME: When this error is returned, HWCryptoHook is telling us
+             * that falling back to software computation might be a good
+             * thing.
+             */
+            if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
+                HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
+                          HWCRHK_R_REQUEST_FALLBACK);
+            } else {
+                HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
+                          HWCRHK_R_REQUEST_FAILED);
+            }
+            ERR_add_error_data(1, rmsg.buf);
+            goto err;
+        }
+    }
+    /*
+     * If we're here, we must be here with some semblance of success :-)
+     */
+    to_return = 1;
+ err:
+    return to_return;
+}
+#  endif
+
+#  ifndef OPENSSL_NO_RSA
 /* This function is aliased to mod_exp (with the mont stuff dropped). */
 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
-               const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
-       {
-       return hwcrhk_mod_exp(r, a, p, m, ctx);
-       }
-#endif
+                               const BIGNUM *m, BN_CTX *ctx,
+                               BN_MONT_CTX *m_ctx)
+{
+    return hwcrhk_mod_exp(r, a, p, m, ctx);
+}
 
-#ifndef OPENSSL_NO_DH
+static int hwcrhk_rsa_finish(RSA *rsa)
+{
+    HWCryptoHook_RSAKeyHandle *hptr;
+
+    hptr = RSA_get_ex_data(rsa, hndidx_rsa);
+    if (hptr) {
+        p_hwcrhk_RSAUnloadKey(*hptr, NULL);
+        OPENSSL_free(hptr);
+        RSA_set_ex_data(rsa, hndidx_rsa, NULL);
+    }
+    return 1;
+}
+
+#  endif
+
+#  ifndef OPENSSL_NO_DH
 /* This function is aliased to mod_exp (with the dh and mont dropped). */
 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
-               const BIGNUM *a, const BIGNUM *p,
-               const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
-       {
-       return hwcrhk_mod_exp(r, a, p, m, ctx);
-       }
-#endif
+                             const BIGNUM *a, const BIGNUM *p,
+                             const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+{
+    return hwcrhk_mod_exp(r, a, p, m, ctx);
+}
+#  endif
 
 /* Random bytes are good */
 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
-       {
-       char tempbuf[1024];
-       HWCryptoHook_ErrMsgBuf rmsg;
-       int to_return = 0; /* assume failure */
-       int ret;
-
-       rmsg.buf = tempbuf;
-       rmsg.size = sizeof(tempbuf);
-
-       if(!hwcrhk_context)
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
-               goto err;
-               }
-
-       ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
-       if (ret < 0)
-               {
-               /* FIXME: When this error is returned, HWCryptoHook is
-                  telling us that falling back to software computation
-                  might be a good thing. */
-               if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
-                       {
-                       HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
-                               HWCRHK_R_REQUEST_FALLBACK);
-                       }
-               else
-                       {
-                       HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
-                               HWCRHK_R_REQUEST_FAILED);
-                       }
-               ERR_add_error_data(1,rmsg.buf);
-               goto err;
-               }
-       to_return = 1;
+{
+    char tempbuf[1024];
+    HWCryptoHook_ErrMsgBuf rmsg;
+    int to_return = 0;          /* assume failure */
+    int ret;
+
+    rmsg.buf = tempbuf;
+    rmsg.size = sizeof(tempbuf);
+
+    if (!hwcrhk_context) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_NOT_INITIALISED);
+        goto err;
+    }
+
+    ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
+    if (ret < 0) {
+        /*
+         * FIXME: When this error is returned, HWCryptoHook is telling us
+         * that falling back to software computation might be a good thing.
+         */
+        if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
+            HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FALLBACK);
+        } else {
+            HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FAILED);
+        }
+        ERR_add_error_data(1, rmsg.buf);
+        goto err;
+    }
+    to_return = 1;
  err:
-       return to_return;
-       }
+    return to_return;
+}
 
 static int hwcrhk_rand_status(void)
-       {
-       return 1;
-       }
-
-/* This cleans up an RSA KM key, called when ex_data is freed */
-#ifndef OPENSSL_NO_RSA
-static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
-       int ind,long argl, void *argp)
 {
-       char tempbuf[1024];
-       HWCryptoHook_ErrMsgBuf rmsg;
-#ifndef OPENSSL_NO_RSA
-       HWCryptoHook_RSAKeyHandle *hptr;
-#endif
-#if !defined(OPENSSL_NO_RSA)
-       int ret;
-#endif
-
-       rmsg.buf = tempbuf;
-       rmsg.size = sizeof(tempbuf);
-
-#ifndef OPENSSL_NO_RSA
-       hptr = (HWCryptoHook_RSAKeyHandle *) item;
-       if(hptr)
-                {
-                ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
-                OPENSSL_free(hptr);
-                }
-#endif
+    return 1;
 }
-#endif
 
-/* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
+/*
+ * Mutex calls: since the HWCryptoHook model closely follows the POSIX model
  * these just wrap the POSIX functions and add some logging.
  */
 
-static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
-       HWCryptoHook_CallerContext *cactx)
-       {
-       mt->lockid = CRYPTO_get_new_dynlockid();
-       if (mt->lockid == 0)
-               return 1; /* failure */
-       return 0; /* success */
-       }
-
-static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
-       {
-       CRYPTO_w_lock(mt->lockid);
-       return 0;
-       }
+static int hwcrhk_mutex_init(HWCryptoHook_Mutex * mt,
+                             HWCryptoHook_CallerContext * cactx)
+{
+    mt->lockid = CRYPTO_get_new_dynlockid();
+    if (mt->lockid == 0)
+        return 1;               /* failure */
+    return 0;                   /* success */
+}
+
+static int hwcrhk_mutex_lock(HWCryptoHook_Mutex * mt)
+{
+    CRYPTO_w_lock(mt->lockid);
+    return 0;
+}
 
 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
-       {
-       CRYPTO_w_unlock(mt->lockid);
-       }
+{
+    CRYPTO_w_unlock(mt->lockid);
+}
 
-static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
-       {
-       CRYPTO_destroy_dynlockid(mt->lockid);
-       }
+static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex * mt)
+{
+    CRYPTO_destroy_dynlockid(mt->lockid);
+}
 
 static int hwcrhk_get_pass(const char *prompt_info,
-       int *len_io, char *buf,
-       HWCryptoHook_PassphraseContext *ppctx,
-       HWCryptoHook_CallerContext *cactx)
-       {
-       pem_password_cb *callback = NULL;
-       void *callback_data = NULL;
-        UI_METHOD *ui_method = NULL;
-       /* Despite what the documentation says prompt_info can be
-        * an empty string.
-        */
-       if (prompt_info && !*prompt_info)
-               prompt_info = NULL;
-
-        if (cactx)
-                {
-                if (cactx->ui_method)
-                        ui_method = cactx->ui_method;
-               if (cactx->password_callback)
-                       callback = cactx->password_callback;
-               if (cactx->callback_data)
-                       callback_data = cactx->callback_data;
-                }
-       if (ppctx)
-               {
-                if (ppctx->ui_method)
-                        {
-                        ui_method = ppctx->ui_method;
-                        callback = NULL;
-                        }
-               if (ppctx->callback_data)
-                       callback_data = ppctx->callback_data;
-               }
-       if (callback == NULL && ui_method == NULL)
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
-               return -1;
-               }
-
-        if (ui_method)
-                {
-                UI *ui = UI_new_method(ui_method);
-                if (ui)
-                        {
-                        int ok;
-                        char *prompt = UI_construct_prompt(ui,
-                                "pass phrase", prompt_info);
-
-                        ok = UI_add_input_string(ui,prompt,
-                                UI_INPUT_FLAG_DEFAULT_PWD,
-                               buf,0,(*len_io) - 1);
-                        UI_add_user_data(ui, callback_data);
-                       UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
-
-                       if (ok >= 0)
-                               do
-                                       {
-                                       ok=UI_process(ui);
-                                       }
-                               while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
-
-                        if (ok >= 0)
-                                *len_io = strlen(buf);
-
-                        UI_free(ui);
-                        OPENSSL_free(prompt);
-                        }
-                }
-        else
-                {
-                *len_io = callback(buf, *len_io, 0, callback_data);
+                           int *len_io, char *buf,
+                           HWCryptoHook_PassphraseContext * ppctx,
+                           HWCryptoHook_CallerContext * cactx)
+{
+    pem_password_cb *callback = NULL;
+    void *callback_data = NULL;
+    UI_METHOD *ui_method = NULL;
+    /*
+     * Despite what the documentation says prompt_info can be an empty
+     * string.
+     */
+    if (prompt_info && !*prompt_info)
+        prompt_info = NULL;
+
+    if (cactx) {
+        if (cactx->ui_method)
+            ui_method = cactx->ui_method;
+        if (cactx->password_callback)
+            callback = cactx->password_callback;
+        if (cactx->callback_data)
+            callback_data = cactx->callback_data;
+    }
+    if (ppctx) {
+        if (ppctx->ui_method) {
+            ui_method = ppctx->ui_method;
+            callback = NULL;
+        }
+        if (ppctx->callback_data)
+            callback_data = ppctx->callback_data;
+    }
+    if (callback == NULL && ui_method == NULL) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS, HWCRHK_R_NO_CALLBACK);
+        return -1;
+    }
+
+    if (ui_method) {
+        UI *ui = UI_new_method(ui_method);
+        if (ui) {
+            int ok;
+            char *prompt = UI_construct_prompt(ui,
+                                               "pass phrase", prompt_info);
+
+            ok = UI_add_input_string(ui, prompt,
+                                     UI_INPUT_FLAG_DEFAULT_PWD,
+                                     buf, 0, (*len_io) - 1);
+            UI_add_user_data(ui, callback_data);
+            UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
+
+            if (ok >= 0)
+                do {
+                    ok = UI_process(ui);
                 }
-       if(!*len_io)
-               return -1;
-       return 0;
-       }
+                while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
+
+            if (ok >= 0)
+                *len_io = strlen(buf);
+
+            UI_free(ui);
+            OPENSSL_free(prompt);
+        }
+    } else {
+        *len_io = callback(buf, *len_io, 0, callback_data);
+    }
+    if (!*len_io)
+        return -1;
+    return 0;
+}
 
 static int hwcrhk_insert_card(const char *prompt_info,
-                     const char *wrong_info,
-                     HWCryptoHook_PassphraseContext *ppctx,
-                     HWCryptoHook_CallerContext *cactx)
-        {
-        int ok = -1;
-        UI *ui;
-       void *callback_data = NULL;
-        UI_METHOD *ui_method = NULL;
-
-        if (cactx)
-                {
-                if (cactx->ui_method)
-                        ui_method = cactx->ui_method;
-               if (cactx->callback_data)
-                       callback_data = cactx->callback_data;
-                }
-       if (ppctx)
-               {
-                if (ppctx->ui_method)
-                        ui_method = ppctx->ui_method;
-               if (ppctx->callback_data)
-                       callback_data = ppctx->callback_data;
-               }
-       if (ui_method == NULL)
-               {
-               HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
-                       HWCRHK_R_NO_CALLBACK);
-               return -1;
-               }
-
-       ui = UI_new_method(ui_method);
-
-       if (ui)
-               {
-               char answer;
-               char buf[BUFSIZ];
-               /* Despite what the documentation says wrong_info can be
-                * an empty string.
-                */
-               if (wrong_info && *wrong_info)
-                       BIO_snprintf(buf, sizeof(buf)-1,
-                               "Current card: \"%s\"\n", wrong_info);
-               else
-                       buf[0] = 0;
-               ok = UI_dup_info_string(ui, buf);
-               if (ok >= 0 && prompt_info)
-                       {
-                       BIO_snprintf(buf, sizeof(buf)-1,
-                               "Insert card \"%s\"", prompt_info);
-                       ok = UI_dup_input_boolean(ui, buf,
-                               "\n then hit <enter> or C<enter> to cancel\n",
-                               "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
-                       }
-               UI_add_user_data(ui, callback_data);
-
-               if (ok >= 0)
-                       ok = UI_process(ui);
-               UI_free(ui);
-
-               if (ok == -2 || (ok >= 0 && answer == 'C'))
-                       ok = 1;
-               else if (ok < 0)
-                       ok = -1;
-               else
-                       ok = 0;
-               }
-       return ok;
-       }
+                              const char *wrong_info,
+                              HWCryptoHook_PassphraseContext * ppctx,
+                              HWCryptoHook_CallerContext * cactx)
+{
+    int ok = -1;
+    UI *ui;
+    void *callback_data = NULL;
+    UI_METHOD *ui_method = NULL;
+
+    if (cactx) {
+        if (cactx->ui_method)
+            ui_method = cactx->ui_method;
+        if (cactx->callback_data)
+            callback_data = cactx->callback_data;
+    }
+    if (ppctx) {
+        if (ppctx->ui_method)
+            ui_method = ppctx->ui_method;
+        if (ppctx->callback_data)
+            callback_data = ppctx->callback_data;
+    }
+    if (ui_method == NULL) {
+        HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD, HWCRHK_R_NO_CALLBACK);
+        return -1;
+    }
+
+    ui = UI_new_method(ui_method);
+
+    if (ui) {
+        char answer = '\0';
+        char buf[BUFSIZ];
+        /*
+         * Despite what the documentation says wrong_info can be an empty
+         * string.
+         */
+        if (wrong_info && *wrong_info)
+            BIO_snprintf(buf, sizeof(buf) - 1,
+                         "Current card: \"%s\"\n", wrong_info);
+        else
+            buf[0] = 0;
+        ok = UI_dup_info_string(ui, buf);
+        if (ok >= 0 && prompt_info) {
+            BIO_snprintf(buf, sizeof(buf) - 1,
+                         "Insert card \"%s\"", prompt_info);
+            ok = UI_dup_input_boolean(ui, buf,
+                                      "\n then hit <enter> or C<enter> to cancel\n",
+                                      "\r\n", "Cc", UI_INPUT_FLAG_ECHO,
+                                      &answer);
+        }
+        UI_add_user_data(ui, callback_data);
+
+        if (ok >= 0)
+            ok = UI_process(ui);
+        UI_free(ui);
+
+        if (ok == -2 || (ok >= 0 && answer == 'C'))
+            ok = 1;
+        else if (ok < 0)
+            ok = -1;
+        else
+            ok = 0;
+    }
+    return ok;
+}
 
 static void hwcrhk_log_message(void *logstr, const char *message)
-       {
-       BIO *lstream = NULL;
-
-       CRYPTO_w_lock(CRYPTO_LOCK_BIO);
-       if (logstr)
-               lstream=*(BIO **)logstr;
-       if (lstream)
-               {
-               BIO_printf(lstream, "%s\n", message);
-               }
-       CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
-       }
-
-/* This stuff is needed if this ENGINE is being compiled into a self-contained
- * shared-library. */     
-#ifndef OPENSSL_NO_DYNAMIC_ENGINE
+{
+    BIO *lstream = NULL;
+
+    CRYPTO_w_lock(CRYPTO_LOCK_BIO);
+    if (logstr)
+        lstream = *(BIO **)logstr;
+    if (lstream) {
+        BIO_printf(lstream, "%s\n", message);
+    }
+    CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
+}
+
+/*
+ * This stuff is needed if this ENGINE is being compiled into a
+ * self-contained shared-library.
+ */
+#  ifndef OPENSSL_NO_DYNAMIC_ENGINE
 static int bind_fn(ENGINE *e, const char *id)
-       {
-       if(id && (strcmp(id, engine_hwcrhk_id) != 0) &&
-                       (strcmp(id, engine_hwcrhk_id_alt) != 0))
-               return 0;
-       if(!bind_helper(e))
-               return 0;
-       return 1;
-       }       
-IMPLEMENT_DYNAMIC_CHECK_FN()
-IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
-#endif /* OPENSSL_NO_DYNAMIC_ENGINE */
+{
+    if (id && (strcmp(id, engine_hwcrhk_id) != 0) &&
+        (strcmp(id, engine_hwcrhk_id_alt) != 0))
+        return 0;
+    if (!bind_helper(e))
+        return 0;
+    return 1;
+}
 
-#endif /* !OPENSSL_NO_HW_CHIL */
-#endif /* !OPENSSL_NO_HW */
+IMPLEMENT_DYNAMIC_CHECK_FN()
+    IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
+#  endif                        /* OPENSSL_NO_DYNAMIC_ENGINE */
+# endif                         /* !OPENSSL_NO_HW_CHIL */
+#endif                          /* !OPENSSL_NO_HW */