Step 2 of move of engines: copy engines to new directory and rename them
authorRichard Levitte <levitte@openssl.org>
Fri, 11 Oct 2002 17:08:27 +0000 (17:08 +0000)
committerRichard Levitte <levitte@openssl.org>
Fri, 11 Oct 2002 17:08:27 +0000 (17:08 +0000)
to be prefixed with e_ instead of hw_.  They aren't necessarely hardware
engines.  The files commited here are exact copies of the corresponding
hw_ files found in crypto/engine/.

25 files changed:
engines/e.ec [new file with mode: 0644]
engines/e_4758_cca.c [new file with mode: 0644]
engines/e_4758_cca_err.c [new file with mode: 0644]
engines/e_4758_cca_err.h [new file with mode: 0644]
engines/e_aep.c [new file with mode: 0644]
engines/e_aep_err.c [new file with mode: 0644]
engines/e_aep_err.h [new file with mode: 0644]
engines/e_atalla.c [new file with mode: 0644]
engines/e_atalla_err.c [new file with mode: 0644]
engines/e_atalla_err.h [new file with mode: 0644]
engines/e_cswift.c [new file with mode: 0644]
engines/e_cswift_err.c [new file with mode: 0644]
engines/e_cswift_err.h [new file with mode: 0644]
engines/e_ncipher.c [new file with mode: 0644]
engines/e_ncipher_err.c [new file with mode: 0644]
engines/e_ncipher_err.h [new file with mode: 0644]
engines/e_nuron.c [new file with mode: 0644]
engines/e_nuron_err.c [new file with mode: 0644]
engines/e_nuron_err.h [new file with mode: 0644]
engines/e_sureware.c [new file with mode: 0644]
engines/e_sureware_err.c [new file with mode: 0644]
engines/e_sureware_err.h [new file with mode: 0644]
engines/e_ubsec.c [new file with mode: 0644]
engines/e_ubsec_err.c [new file with mode: 0644]
engines/e_ubsec_err.h [new file with mode: 0644]

diff --git a/engines/e.ec b/engines/e.ec
new file mode 100644 (file)
index 0000000..5481a43
--- /dev/null
@@ -0,0 +1,8 @@
+L AEPHK                hw_aep_err.h                    hw_aep_err.c
+L ATALLA       hw_atalla_err.h                 hw_atalla_err.c
+L CSWIFT       hw_cswift_err.h                 hw_cswift_err.c
+L HWCRHK       hw_ncipher_err.h                hw_ncipher_err.c
+L NURON                hw_nuron_err.h                  hw_nuron_err.c
+L SUREWARE     hw_sureware_err.h               hw_sureware_err.c
+L UBSEC                hw_ubsec_err.h                  hw_ubsec_err.c
+L CCA4758      hw_4758_cca_err.h               hw_4758_cca_err.c
diff --git a/engines/e_4758_cca.c b/engines/e_4758_cca.c
new file mode 100644 (file)
index 0000000..6d41b9e
--- /dev/null
@@ -0,0 +1,967 @@
+/* Author: Maurice Gittens <maurice@gittens.nl>                       */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+/* #include <openssl/pem.h> */
+#include "cryptlib.h"
+#include <openssl/dso.h>
+#include <openssl/x509.h>
+#include <openssl/objects.h>
+#include <openssl/engine.h>
+
+#ifndef OPENSSL_NO_HW
+#ifndef OPENSSL_NO_HW_4758_CCA
+
+#ifdef FLAT_INC
+#include "hw_4758_cca.h"
+#else
+#include "vendor_defns/hw_4758_cca.h"
+#endif
+
+#include "hw_4758_cca_err.c"
+
+static int ibm_4758_cca_destroy(ENGINE *e);
+static int ibm_4758_cca_init(ENGINE *e);
+static int ibm_4758_cca_finish(ENGINE *e);
+static int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
+
+/* rsa functions */
+/*---------------*/
+#ifndef OPENSSL_NO_RSA
+static int cca_rsa_pub_enc(int flen, const unsigned char *from,
+               unsigned char *to, RSA *rsa,int padding);
+static int cca_rsa_priv_dec(int flen, const unsigned char *from,
+               unsigned char *to, RSA *rsa,int padding);
+static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
+               unsigned char *sigret, unsigned int *siglen, const RSA *rsa);
+static int cca_rsa_verify(int dtype, const unsigned char *m, unsigned int m_len,
+               unsigned char *sigbuf, unsigned int siglen, const RSA *rsa);
+
+/* utility functions */
+/*-----------------------*/
+static EVP_PKEY *ibm_4758_load_privkey(ENGINE*, const char*,
+               UI_METHOD *ui_method, void *callback_data);
+static EVP_PKEY *ibm_4758_load_pubkey(ENGINE*, const char*,
+               UI_METHOD *ui_method, void *callback_data);
+
+static int getModulusAndExponent(const unsigned char *token, long *exponentLength,
+               unsigned char *exponent, long *modulusLength,
+               long *modulusFieldLength, unsigned char *modulus);
+#endif
+
+/* RAND number functions */
+/*-----------------------*/
+static int cca_get_random_bytes(unsigned char*, int );
+static int cca_random_status(void);
+
+static void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
+               int idx,long argl, void *argp);
+
+/* Function pointers for CCA verbs */
+/*---------------------------------*/
+#ifndef OPENSSL_NO_RSA
+static F_KEYRECORDREAD keyRecordRead;
+static F_DIGITALSIGNATUREGENERATE digitalSignatureGenerate;
+static F_DIGITALSIGNATUREVERIFY digitalSignatureVerify;
+static F_PUBLICKEYEXTRACT publicKeyExtract;
+static F_PKAENCRYPT pkaEncrypt;
+static F_PKADECRYPT pkaDecrypt;
+#endif
+static F_RANDOMNUMBERGENERATE randomNumberGenerate;
+
+/* static variables */
+/*------------------*/
+static const char *CCA4758_LIB_NAME = NULL;
+static const char *get_CCA4758_LIB_NAME(void)
+       {
+       if(CCA4758_LIB_NAME)
+               return CCA4758_LIB_NAME;
+       return CCA_LIB_NAME;
+       }
+static void free_CCA4758_LIB_NAME(void)
+       {
+       if(CCA4758_LIB_NAME)
+               OPENSSL_free((void*)CCA4758_LIB_NAME);
+       CCA4758_LIB_NAME = NULL;
+       }
+static long set_CCA4758_LIB_NAME(const char *name)
+       {
+       free_CCA4758_LIB_NAME();
+       return (((CCA4758_LIB_NAME = BUF_strdup(name)) != NULL) ? 1 : 0);
+       }
+#ifndef OPENSSL_NO_RSA
+static const char* n_keyRecordRead = CSNDKRR;
+static const char* n_digitalSignatureGenerate = CSNDDSG;
+static const char* n_digitalSignatureVerify = CSNDDSV;
+static const char* n_publicKeyExtract = CSNDPKX;
+static const char* n_pkaEncrypt = CSNDPKE;
+static const char* n_pkaDecrypt = CSNDPKD;
+#endif
+static const char* n_randomNumberGenerate = CSNBRNG;
+
+static int hndidx = -1;
+static DSO *dso = NULL;
+
+/* openssl engine initialization structures */
+/*------------------------------------------*/
+
+#define CCA4758_CMD_SO_PATH            ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN   cca4758_cmd_defns[] = {
+       {CCA4758_CMD_SO_PATH,
+               "SO_PATH",
+               "Specifies the path to the '4758cca' shared library",
+               ENGINE_CMD_FLAG_STRING},
+       {0, NULL, NULL, 0}
+       };
+
+#ifndef OPENSSL_NO_RSA
+static RSA_METHOD ibm_4758_cca_rsa =
+       {
+       "IBM 4758 CCA RSA method",
+       cca_rsa_pub_enc,
+       NULL,
+       NULL,
+       cca_rsa_priv_dec,
+       NULL, /*rsa_mod_exp,*/
+       NULL, /*mod_exp_mont,*/
+       NULL, /* init */
+       NULL, /* finish */
+       RSA_FLAG_SIGN_VER,        /* flags */
+       NULL, /* app_data */
+       cca_rsa_sign, /* rsa_sign */
+       cca_rsa_verify  /* rsa_verify */
+       };
+#endif
+
+static RAND_METHOD ibm_4758_cca_rand =
+       {
+       /* "IBM 4758 RAND method", */
+       NULL, /* seed */
+       cca_get_random_bytes, /* get random bytes from the card */
+       NULL, /* cleanup */
+       NULL, /* add */
+       cca_get_random_bytes, /* pseudo rand */
+       cca_random_status, /* status */
+       };
+
+static const char *engine_4758_cca_id = "4758cca";
+static const char *engine_4758_cca_name = "IBM 4758 CCA hardware engine support";
+
+/* engine implementation */
+/*-----------------------*/
+static int bind_helper(ENGINE *e)
+       {
+       if(!ENGINE_set_id(e, engine_4758_cca_id) ||
+                       !ENGINE_set_name(e, engine_4758_cca_name) ||
+#ifndef OPENSSL_NO_RSA
+                       !ENGINE_set_RSA(e, &ibm_4758_cca_rsa) ||
+#endif
+                       !ENGINE_set_RAND(e, &ibm_4758_cca_rand) ||
+                       !ENGINE_set_destroy_function(e, ibm_4758_cca_destroy) ||
+                       !ENGINE_set_init_function(e, ibm_4758_cca_init) ||
+                       !ENGINE_set_finish_function(e, ibm_4758_cca_finish) ||
+                       !ENGINE_set_ctrl_function(e, ibm_4758_cca_ctrl) ||
+                       !ENGINE_set_load_privkey_function(e, ibm_4758_load_privkey) ||
+                       !ENGINE_set_load_pubkey_function(e, ibm_4758_load_pubkey) ||
+                       !ENGINE_set_cmd_defns(e, cca4758_cmd_defns))
+               return 0;
+       /* Ensure the error handling is set up */
+       ERR_load_CCA4758_strings();
+       return 1;
+       }
+
+static ENGINE *engine_4758_cca(void)
+       {
+       ENGINE *ret = ENGINE_new();
+       if(!ret)
+               return NULL;
+       if(!bind_helper(ret))
+               {
+               ENGINE_free(ret);
+               return NULL;
+               }
+       return ret;
+       }
+
+void ENGINE_load_4758cca(void)
+       {
+       ENGINE *e_4758 = engine_4758_cca();
+       if (!e_4758) return;
+       ENGINE_add(e_4758);
+       ENGINE_free(e_4758);
+       ERR_clear_error();   
+       }
+
+static int ibm_4758_cca_destroy(ENGINE *e)
+       {
+       ERR_unload_CCA4758_strings();
+       free_CCA4758_LIB_NAME();
+       return 1;
+       }
+
+static int ibm_4758_cca_init(ENGINE *e)
+       {
+       if(dso)
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_ALREADY_LOADED);
+               goto err;
+               }
+
+       dso = DSO_load(NULL, get_CCA4758_LIB_NAME(), NULL, 0);
+       if(!dso)
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
+               goto err;
+               }
+
+#ifndef OPENSSL_NO_RSA
+       if(!(keyRecordRead = (F_KEYRECORDREAD)
+                               DSO_bind_func(dso, n_keyRecordRead)) ||
+                       !(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
+                               DSO_bind_func(dso, n_randomNumberGenerate)) ||
+                       !(digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)
+                               DSO_bind_func(dso, n_digitalSignatureGenerate)) ||
+                       !(digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)
+                               DSO_bind_func(dso, n_digitalSignatureVerify)) ||
+                       !(publicKeyExtract = (F_PUBLICKEYEXTRACT)
+                               DSO_bind_func(dso, n_publicKeyExtract)) ||
+                       !(pkaEncrypt = (F_PKAENCRYPT)
+                               DSO_bind_func(dso, n_pkaEncrypt)) ||
+                       !(pkaDecrypt = (F_PKADECRYPT)
+                               DSO_bind_func(dso, n_pkaDecrypt)))
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
+               goto err;
+               }
+#else
+       if(!(randomNumberGenerate = (F_RANDOMNUMBERGENERATE)
+                               DSO_bind_func(dso, n_randomNumberGenerate)))
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_INIT,CCA4758_R_DSO_FAILURE);
+               goto err;
+               }
+#endif
+
+       hndidx = RSA_get_ex_new_index(0, "IBM 4758 CCA RSA key handle",
+               NULL, NULL, cca_ex_free);
+
+       return 1;
+err:
+       if(dso)
+               DSO_free(dso);
+       dso = NULL;
+
+       keyRecordRead = (F_KEYRECORDREAD)0;
+       randomNumberGenerate = (F_RANDOMNUMBERGENERATE)0;
+       digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)0;
+       digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
+       publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
+       pkaEncrypt = (F_PKAENCRYPT)0;
+       pkaDecrypt = (F_PKADECRYPT)0;
+       return 0;
+       }
+
+static int ibm_4758_cca_finish(ENGINE *e)
+       {
+       free_CCA4758_LIB_NAME();
+       if(!dso)
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH,
+                               CCA4758_R_NOT_LOADED);
+               return 0;
+               }
+       if(!DSO_free(dso))
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH,
+                               CCA4758_R_UNIT_FAILURE);
+               return 0;
+               }
+       dso = NULL;
+       keyRecordRead = (F_KEYRECORDREAD)0;
+       randomNumberGenerate = (F_RANDOMNUMBERGENERATE)0;
+       digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE)0;
+       digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0;
+       publicKeyExtract = (F_PUBLICKEYEXTRACT)0;
+       pkaEncrypt = (F_PKAENCRYPT)0;
+       pkaDecrypt = (F_PKADECRYPT)0;
+       return 1;
+       }
+
+static int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+       {
+       int initialised = ((dso == NULL) ? 0 : 1);
+       switch(cmd)
+               {
+       case CCA4758_CMD_SO_PATH:
+               if(p == NULL)
+                       {
+                       CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
+                                       ERR_R_PASSED_NULL_PARAMETER);
+                       return 0;
+                       }
+               if(initialised)
+                       {
+                       CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
+                                       CCA4758_R_ALREADY_LOADED);
+                       return 0;
+                       }
+               return set_CCA4758_LIB_NAME((const char *)p);
+       default:
+               break;
+               }
+       CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL,
+                       CCA4758_R_COMMAND_NOT_IMPLEMENTED);
+       return 0;
+       }
+
+#ifndef OPENSSL_NO_RSA
+
+#define MAX_CCA_PKA_TOKEN_SIZE 2500
+
+static EVP_PKEY *ibm_4758_load_privkey(ENGINE* e, const char* key_id,
+                       UI_METHOD *ui_method, void *callback_data)
+       {
+       RSA *rtmp = NULL;
+       EVP_PKEY *res = NULL;
+       unsigned char* keyToken = NULL;
+       unsigned char pubKeyToken[MAX_CCA_PKA_TOKEN_SIZE];
+       long pubKeyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
+       long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
+       long returnCode;
+       long reasonCode;
+       long exitDataLength = 0;
+       long ruleArrayLength = 0;
+       unsigned char exitData[8];
+       unsigned char ruleArray[8];
+       unsigned char keyLabel[64];
+       long keyLabelLength = strlen(key_id);
+       unsigned char modulus[256];
+       long modulusFieldLength = sizeof(modulus);
+       long modulusLength = 0;
+       unsigned char exponent[256];
+       long exponentLength = sizeof(exponent);
+
+       if (keyLabelLength > sizeof(keyLabel))
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+               CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+               return NULL;
+               }
+
+       memset(keyLabel,' ', sizeof(keyLabel));
+       memcpy(keyLabel, key_id, keyLabelLength);
+
+       keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
+       if (!keyToken)
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+                               ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
+
+       keyRecordRead(&returnCode, &reasonCode, &exitDataLength,
+               exitData, &ruleArrayLength, ruleArray, keyLabel,
+               &keyTokenLength, keyToken+sizeof(long));
+
+       if (returnCode)
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+                       CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
+               goto err;
+               }
+
+       publicKeyExtract(&returnCode, &reasonCode, &exitDataLength,
+               exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
+               keyToken+sizeof(long), &pubKeyTokenLength, pubKeyToken);
+
+       if (returnCode)
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+                       CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
+               goto err;
+               }
+
+       if (!getModulusAndExponent(pubKeyToken, &exponentLength,
+                       exponent, &modulusLength, &modulusFieldLength,
+                       modulus))
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+                       CCA4758_R_FAILED_LOADING_PRIVATE_KEY);
+               goto err;
+               }
+
+       (*(long*)keyToken) = keyTokenLength;
+       rtmp = RSA_new_method(e);
+       RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
+
+       rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
+       rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
+       rtmp->flags |= RSA_FLAG_EXT_PKEY;
+
+       res = EVP_PKEY_new();
+       EVP_PKEY_assign_RSA(res, rtmp);
+
+       return res;
+err:
+       if (keyToken)
+               OPENSSL_free(keyToken);
+       if (res)
+               EVP_PKEY_free(res);
+       if (rtmp)
+               RSA_free(rtmp);
+       return NULL;
+       }
+
+static EVP_PKEY *ibm_4758_load_pubkey(ENGINE* e, const char* key_id,
+                       UI_METHOD *ui_method, void *callback_data)
+       {
+       RSA *rtmp = NULL;
+       EVP_PKEY *res = NULL;
+       unsigned char* keyToken = NULL;
+       long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE;
+       long returnCode;
+       long reasonCode;
+       long exitDataLength = 0;
+       long ruleArrayLength = 0;
+       unsigned char exitData[8];
+       unsigned char ruleArray[8];
+       unsigned char keyLabel[64];
+       long keyLabelLength = strlen(key_id);
+       unsigned char modulus[512];
+       long modulusFieldLength = sizeof(modulus);
+       long modulusLength = 0;
+       unsigned char exponent[512];
+       long exponentLength = sizeof(exponent);
+
+       if (keyLabelLength > sizeof(keyLabel))
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+                       CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+               return NULL;
+               }
+
+       memset(keyLabel,' ', sizeof(keyLabel));
+       memcpy(keyLabel, key_id, keyLabelLength);
+
+       keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long));
+       if (!keyToken)
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PUBKEY,
+                               ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
+
+       keyRecordRead(&returnCode, &reasonCode, &exitDataLength, exitData,
+               &ruleArrayLength, ruleArray, keyLabel, &keyTokenLength,
+               keyToken+sizeof(long));
+
+       if (returnCode)
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+                               ERR_R_MALLOC_FAILURE);
+               goto err;
+               }
+
+       if (!getModulusAndExponent(keyToken+sizeof(long), &exponentLength,
+                       exponent, &modulusLength, &modulusFieldLength, modulus))
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,
+                       CCA4758_R_FAILED_LOADING_PUBLIC_KEY);
+               goto err;
+               }
+
+       (*(long*)keyToken) = keyTokenLength;
+       rtmp = RSA_new_method(e);
+       RSA_set_ex_data(rtmp, hndidx, (char *)keyToken);
+       rtmp->e = BN_bin2bn(exponent, exponentLength, NULL);
+       rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL);
+       rtmp->flags |= RSA_FLAG_EXT_PKEY;
+       res = EVP_PKEY_new();
+       EVP_PKEY_assign_RSA(res, rtmp);
+
+       return res;
+err:
+       if (keyToken)
+               OPENSSL_free(keyToken);
+       if (res)
+               EVP_PKEY_free(res);
+       if (rtmp)
+               RSA_free(rtmp);
+       return NULL;
+       }
+
+static int cca_rsa_pub_enc(int flen, const unsigned char *from,
+                       unsigned char *to, RSA *rsa,int padding)
+       {
+       long returnCode;
+       long reasonCode;
+       long lflen = flen;
+       long exitDataLength = 0;
+       unsigned char exitData[8];
+       long ruleArrayLength = 1;
+       unsigned char ruleArray[8] = "PKCS-1.2";
+       long dataStructureLength = 0;
+       unsigned char dataStructure[8];
+       long outputLength = RSA_size(rsa);
+       long keyTokenLength;
+       unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
+
+       keyTokenLength = *(long*)keyToken;
+       keyToken+=sizeof(long);
+
+       pkaEncrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
+               &ruleArrayLength, ruleArray, &lflen, (unsigned char*)from,
+               &dataStructureLength, dataStructure, &keyTokenLength,
+               keyToken, &outputLength, to);
+
+       if (returnCode || reasonCode)
+               return -(returnCode << 16 | reasonCode);
+       return outputLength;
+       }
+
+static int cca_rsa_priv_dec(int flen, const unsigned char *from,
+                       unsigned char *to, RSA *rsa,int padding)
+       {
+       long returnCode;
+       long reasonCode;
+       long lflen = flen;
+       long exitDataLength = 0;
+       unsigned char exitData[8];
+       long ruleArrayLength = 1;
+       unsigned char ruleArray[8] = "PKCS-1.2";
+       long dataStructureLength = 0;
+       unsigned char dataStructure[8];
+       long outputLength = RSA_size(rsa);
+       long keyTokenLength;
+       unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
+
+       keyTokenLength = *(long*)keyToken;
+       keyToken+=sizeof(long);
+
+       pkaDecrypt(&returnCode, &reasonCode, &exitDataLength, exitData,
+               &ruleArrayLength, ruleArray, &lflen, (unsigned char*)from,
+               &dataStructureLength, dataStructure, &keyTokenLength,
+               keyToken, &outputLength, to);
+
+       return (returnCode | reasonCode) ? 0 : 1;
+       }
+
+#define SSL_SIG_LEN 36
+
+static int cca_rsa_verify(int type, const unsigned char *m, unsigned int m_len,
+               unsigned char *sigbuf, unsigned int siglen, const RSA *rsa)
+       {
+       long returnCode;
+       long reasonCode;
+       long lsiglen = siglen;
+       long exitDataLength = 0;
+       unsigned char exitData[8];
+       long ruleArrayLength = 1;
+       unsigned char ruleArray[8] = "PKCS-1.1";
+       long keyTokenLength;
+       unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
+       long length = SSL_SIG_LEN;
+       long keyLength ;
+       unsigned char *hashBuffer = NULL;
+       X509_SIG sig;
+       ASN1_TYPE parameter;
+       X509_ALGOR algorithm;
+       ASN1_OCTET_STRING digest;
+
+       keyTokenLength = *(long*)keyToken;
+       keyToken+=sizeof(long);
+
+       if (type == NID_md5 || type == NID_sha1)
+               {
+               sig.algor = &algorithm;
+               algorithm.algorithm = OBJ_nid2obj(type);
+
+               if (!algorithm.algorithm)
+                       {
+                       CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+                               CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
+                       return 0;
+                       }
+
+               if (!algorithm.algorithm->length)
+                       {
+                       CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+                               CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
+                       return 0;
+                       }
+
+               parameter.type = V_ASN1_NULL;
+               parameter.value.ptr = NULL;
+               algorithm.parameter = &parameter;
+
+               sig.digest = &digest;
+               sig.digest->data = (unsigned char*)m;
+               sig.digest->length = m_len;
+
+               length = i2d_X509_SIG(&sig, NULL);
+               }
+
+       keyLength = RSA_size(rsa);
+
+       if (length - RSA_PKCS1_PADDING > keyLength)
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+                       CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+               return 0;
+               }
+
+       switch (type)
+               {
+               case NID_md5_sha1 :
+                       if (m_len != SSL_SIG_LEN)
+                               {
+                               CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+                               CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+                               return 0;
+                               }
+
+                       hashBuffer = (unsigned char *)m;
+                       length = m_len;
+                       break;
+               case NID_md5 :
+                       {
+                       unsigned char *ptr;
+                       ptr = hashBuffer = OPENSSL_malloc(
+                                       (unsigned int)keyLength+1);
+                       if (!hashBuffer)
+                               {
+                               CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+                                               ERR_R_MALLOC_FAILURE);
+                               return 0;
+                               }
+
+                       i2d_X509_SIG(&sig, &ptr);
+                       }
+                       break;
+               case NID_sha1 :
+                       {
+                       unsigned char *ptr;
+                       ptr = hashBuffer = OPENSSL_malloc(
+                                       (unsigned int)keyLength+1);
+                       if (!hashBuffer)
+                               {
+                               CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+                                               ERR_R_MALLOC_FAILURE);
+                               return 0;
+                               }
+                       i2d_X509_SIG(&sig, &ptr);
+                       }
+                       break;
+               default:
+                       return 0;
+               }
+
+       digitalSignatureVerify(&returnCode, &reasonCode, &exitDataLength,
+               exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
+               keyToken, &length, hashBuffer, &lsiglen, sigbuf);
+
+       if (type == NID_sha1 || type == NID_md5)
+               {
+               memset(hashBuffer, 0, keyLength+1);
+               OPENSSL_free(hashBuffer);
+               }
+
+       return ((returnCode || reasonCode) ? 0 : 1);
+       }
+
+#define SSL_SIG_LEN 36
+
+static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len,
+               unsigned char *sigret, unsigned int *siglen, const RSA *rsa)
+       {
+       long returnCode;
+       long reasonCode;
+       long exitDataLength = 0;
+       unsigned char exitData[8];
+       long ruleArrayLength = 1;
+       unsigned char ruleArray[8] = "PKCS-1.1";
+       long outputLength=256;
+       long outputBitLength;
+       long keyTokenLength;
+       unsigned char *hashBuffer = NULL;
+       unsigned char* keyToken = (unsigned char*)RSA_get_ex_data(rsa, hndidx);
+       long length = SSL_SIG_LEN;
+       long keyLength ;
+       X509_SIG sig;
+       ASN1_TYPE parameter;
+       X509_ALGOR algorithm;
+       ASN1_OCTET_STRING digest;
+
+       keyTokenLength = *(long*)keyToken;
+       keyToken+=sizeof(long);
+
+       if (type == NID_md5 || type == NID_sha1)
+               {
+               sig.algor = &algorithm;
+               algorithm.algorithm = OBJ_nid2obj(type);
+
+               if (!algorithm.algorithm)
+                       {
+                       CCA4758err(CCA4758_F_IBM_4758_CCA_SIGN,
+                               CCA4758_R_UNKNOWN_ALGORITHM_TYPE);
+                       return 0;
+                       }
+
+               if (!algorithm.algorithm->length)
+                       {
+                       CCA4758err(CCA4758_F_IBM_4758_CCA_SIGN,
+                               CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD);
+                       return 0;
+                       }
+
+               parameter.type = V_ASN1_NULL;
+               parameter.value.ptr = NULL;
+               algorithm.parameter = &parameter;
+
+               sig.digest = &digest;
+               sig.digest->data = (unsigned char*)m;
+               sig.digest->length = m_len;
+
+               length = i2d_X509_SIG(&sig, NULL);
+               }
+
+       keyLength = RSA_size(rsa);
+
+       if (length - RSA_PKCS1_PADDING > keyLength)
+               {
+               CCA4758err(CCA4758_F_IBM_4758_CCA_SIGN,
+                       CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+               return 0;
+               }
+
+       switch (type)
+               {
+               case NID_md5_sha1 :
+                       if (m_len != SSL_SIG_LEN)
+                               {
+                               CCA4758err(CCA4758_F_IBM_4758_CCA_SIGN,
+                               CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+                               return 0;
+                               }
+                       hashBuffer = (unsigned char*)m;
+                       length = m_len;
+                       break;
+               case NID_md5 :
+                       {
+                       unsigned char *ptr;
+                       ptr = hashBuffer = OPENSSL_malloc(
+                                       (unsigned int)keyLength+1);
+                       if (!hashBuffer)
+                               {
+                               CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+                                               ERR_R_MALLOC_FAILURE);
+                               return 0;
+                               }
+                       i2d_X509_SIG(&sig, &ptr);
+                       }
+                       break;
+               case NID_sha1 :
+                       {
+                       unsigned char *ptr;
+                       ptr = hashBuffer = OPENSSL_malloc(
+                                       (unsigned int)keyLength+1);
+                       if (!hashBuffer)
+                               {
+                               CCA4758err(CCA4758_F_IBM_4758_CCA_VERIFY,
+                                               ERR_R_MALLOC_FAILURE);
+                               return 0;
+                               }
+                       i2d_X509_SIG(&sig, &ptr);
+                       }
+                       break;
+               default:
+                       return 0;
+               }
+
+       digitalSignatureGenerate(&returnCode, &reasonCode, &exitDataLength,
+               exitData, &ruleArrayLength, ruleArray, &keyTokenLength,
+               keyToken, &length, hashBuffer, &outputLength, &outputBitLength,
+               sigret);
+
+       if (type == NID_sha1 || type == NID_md5)
+               {
+               memset(hashBuffer, 0, keyLength+1);
+               OPENSSL_free(hashBuffer);
+               }
+
+       *siglen = outputLength;
+
+       return ((returnCode || reasonCode) ? 0 : 1);
+       }
+
+static int getModulusAndExponent(const unsigned char*token, long *exponentLength,
+               unsigned char *exponent, long *modulusLength, long *modulusFieldLength,
+               unsigned char *modulus)
+       {
+       unsigned long len;
+
+       if (*token++ != (char)0x1E) /* internal PKA token? */
+               return 0;
+
+       if (*token++) /* token version must be zero */
+               return 0;
+
+       len = *token++;
+       len = len << 8;
+       len |= (unsigned char)*token++;
+
+       token += 4; /* skip reserved bytes */
+
+       if (*token++ == (char)0x04)
+               {
+               if (*token++) /* token version must be zero */
+                       return 0;
+
+               len = *token++;
+               len = len << 8;
+               len |= (unsigned char)*token++;
+
+               token+=2; /* skip reserved section */
+
+               len = *token++;
+               len = len << 8;
+               len |= (unsigned char)*token++;
+
+               *exponentLength = len;
+
+               len = *token++;
+               len = len << 8;
+               len |= (unsigned char)*token++;
+
+               *modulusLength = len;
+
+               len = *token++;
+               len = len << 8;
+               len |= (unsigned char)*token++;
+
+               *modulusFieldLength = len;
+
+               memcpy(exponent, token, *exponentLength);
+               token+= *exponentLength;
+
+               memcpy(modulus, token, *modulusFieldLength);
+               return 1;
+               }
+       return 0;
+       }
+
+#endif /* OPENSSL_NO_RSA */
+
+static int cca_random_status(void)
+       {
+       return 1;
+       }
+
+static int cca_get_random_bytes(unsigned char* buf, int num)
+       {
+       long ret_code;
+       long reason_code;
+       long exit_data_length;
+       unsigned char exit_data[4];
+       unsigned char form[] = "RANDOM  ";
+       unsigned char rand_buf[8];
+
+       while(num >= sizeof(rand_buf))
+               {
+               randomNumberGenerate(&ret_code, &reason_code, &exit_data_length,
+                       exit_data, form, rand_buf);
+               if (ret_code)
+                       return 0;
+               num -= sizeof(rand_buf);
+               memcpy(buf, rand_buf, sizeof(rand_buf));
+               buf += sizeof(rand_buf);
+               }
+
+       if (num)
+               {
+               randomNumberGenerate(&ret_code, &reason_code, NULL, NULL,
+                       form, rand_buf);
+               if (ret_code)
+                       return 0;
+               memcpy(buf, rand_buf, num);
+               }
+
+       return 1;
+       }
+
+static void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad, int idx,
+               long argl, void *argp)
+       {
+       if (item)
+               OPENSSL_free(item);
+       }
+
+/* Goo to handle building as a dynamic engine */
+#ifdef ENGINE_DYNAMIC_SUPPORT 
+static int bind_fn(ENGINE *e, const char *id)
+       {
+       if(id && (strcmp(id, engine_4758_cca_id) != 0))
+               return 0;
+       if(!bind_helper(e))
+               return 0;
+       return 1;
+       }       
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
+#endif /* ENGINE_DYNAMIC_SUPPORT */
+
+#endif /* !OPENSSL_NO_HW_4758_CCA */
+#endif /* !OPENSSL_NO_HW */
diff --git a/engines/e_4758_cca_err.c b/engines/e_4758_cca_err.c
new file mode 100644 (file)
index 0000000..7ea5c63
--- /dev/null
@@ -0,0 +1,149 @@
+/* hw_4758_cca_err.c */
+/* ====================================================================
+ * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "hw_4758_cca_err.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA CCA4758_str_functs[]=
+       {
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_CTRL,0),    "IBM_4758_CCA_CTRL"},
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_FINISH,0),  "IBM_4758_CCA_FINISH"},
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_INIT,0),    "IBM_4758_CCA_INIT"},
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY,0),    "IBM_4758_CCA_LOAD_PRIVKEY"},
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_LOAD_PUBKEY,0),     "IBM_4758_CCA_LOAD_PUBKEY"},
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_SIGN,0),    "IBM_4758_CCA_SIGN"},
+{ERR_PACK(0,CCA4758_F_IBM_4758_CCA_VERIFY,0),  "IBM_4758_CCA_VERIFY"},
+{0,NULL}
+       };
+
+static ERR_STRING_DATA CCA4758_str_reasons[]=
+       {
+{CCA4758_R_ALREADY_LOADED                ,"already loaded"},
+{CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD       ,"asn1 oid unknown for md"},
+{CCA4758_R_COMMAND_NOT_IMPLEMENTED       ,"command not implemented"},
+{CCA4758_R_DSO_FAILURE                   ,"dso failure"},
+{CCA4758_R_FAILED_LOADING_PRIVATE_KEY    ,"failed loading private key"},
+{CCA4758_R_FAILED_LOADING_PUBLIC_KEY     ,"failed loading public key"},
+{CCA4758_R_NOT_LOADED                    ,"not loaded"},
+{CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL   ,"size too large or too small"},
+{CCA4758_R_UNIT_FAILURE                  ,"unit failure"},
+{CCA4758_R_UNKNOWN_ALGORITHM_TYPE        ,"unknown algorithm type"},
+{0,NULL}
+       };
+
+#endif
+
+#ifdef CCA4758_LIB_NAME
+static ERR_STRING_DATA CCA4758_lib_name[]=
+        {
+{0     ,CCA4758_LIB_NAME},
+{0,NULL}
+       };
+#endif
+
+
+static int CCA4758_lib_error_code=0;
+static int CCA4758_error_init=1;
+
+static void ERR_load_CCA4758_strings(void)
+       {
+       if (CCA4758_lib_error_code == 0)
+               CCA4758_lib_error_code=ERR_get_next_error_library();
+
+       if (CCA4758_error_init)
+               {
+               CCA4758_error_init=0;
+#ifndef OPENSSL_NO_ERR
+               ERR_load_strings(CCA4758_lib_error_code,CCA4758_str_functs);
+               ERR_load_strings(CCA4758_lib_error_code,CCA4758_str_reasons);
+#endif
+
+#ifdef CCA4758_LIB_NAME
+               CCA4758_lib_name->error = ERR_PACK(CCA4758_lib_error_code,0,0);
+               ERR_load_strings(0,CCA4758_lib_name);
+#endif
+               }
+       }
+
+static void ERR_unload_CCA4758_strings(void)
+       {
+       if (CCA4758_error_init == 0)
+               {
+#ifndef OPENSSL_NO_ERR
+               ERR_unload_strings(CCA4758_lib_error_code,CCA4758_str_functs);
+               ERR_unload_strings(CCA4758_lib_error_code,CCA4758_str_reasons);
+#endif
+
+#ifdef CCA4758_LIB_NAME
+               ERR_unload_strings(0,CCA4758_lib_name);
+#endif
+               CCA4758_error_init=1;
+               }
+       }
+
+static void ERR_CCA4758_error(int function, int reason, char *file, int line)
+       {
+       if (CCA4758_lib_error_code == 0)
+               CCA4758_lib_error_code=ERR_get_next_error_library();
+       ERR_PUT_error(CCA4758_lib_error_code,function,reason,file,line);
+       }
diff --git a/engines/e_4758_cca_err.h b/engines/e_4758_cca_err.h
new file mode 100644 (file)
index 0000000..2fc563a
--- /dev/null
@@ -0,0 +1,93 @@
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_CCA4758_ERR_H
+#define HEADER_CCA4758_ERR_H
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+static void ERR_load_CCA4758_strings(void);
+static void ERR_unload_CCA4758_strings(void);
+static void ERR_CCA4758_error(int function, int reason, char *file, int line);
+#define CCA4758err(f,r) ERR_CCA4758_error((f),(r),__FILE__,__LINE__)
+
+/* Error codes for the CCA4758 functions. */
+
+/* Function codes. */
+#define CCA4758_F_IBM_4758_CCA_CTRL                     100
+#define CCA4758_F_IBM_4758_CCA_FINISH                   101
+#define CCA4758_F_IBM_4758_CCA_INIT                     102
+#define CCA4758_F_IBM_4758_CCA_LOAD_PRIVKEY             103
+#define CCA4758_F_IBM_4758_CCA_LOAD_PUBKEY              104
+#define CCA4758_F_IBM_4758_CCA_SIGN                     105
+#define CCA4758_F_IBM_4758_CCA_VERIFY                   106
+
+/* Reason codes. */
+#define CCA4758_R_ALREADY_LOADED                        100
+#define CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD               101
+#define CCA4758_R_COMMAND_NOT_IMPLEMENTED               102
+#define CCA4758_R_DSO_FAILURE                           103
+#define CCA4758_R_FAILED_LOADING_PRIVATE_KEY            104
+#define CCA4758_R_FAILED_LOADING_PUBLIC_KEY             105
+#define CCA4758_R_NOT_LOADED                            106
+#define CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL           107
+#define CCA4758_R_UNIT_FAILURE                          108
+#define CCA4758_R_UNKNOWN_ALGORITHM_TYPE                109
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/engines/e_aep.c b/engines/e_aep.c
new file mode 100644 (file)
index 0000000..8b8380a
--- /dev/null
@@ -0,0 +1,1119 @@
+/* crypto/engine/hw_aep.c */
+/*
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <openssl/bn.h>
+#include <string.h>
+
+#include <openssl/e_os2.h>
+#if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
+#include <sys/types.h>
+#include <unistd.h>
+#else
+#include <process.h>
+typedef int pid_t;
+#endif
+
+#include <openssl/crypto.h>
+#include <openssl/dso.h>
+#include <openssl/engine.h>
+#include <openssl/buffer.h>
+
+#ifndef OPENSSL_NO_HW
+#ifndef OPENSSL_NO_HW_AEP
+#ifdef FLAT_INC
+#include "aep.h"
+#else
+#include "vendor_defns/aep.h"
+#endif
+
+#define AEP_LIB_NAME "aep engine"
+#define FAIL_TO_SW 0x10101010
+
+#include "hw_aep_err.c"
+
+static int aep_init(ENGINE *e);
+static int aep_finish(ENGINE *e);
+static int aep_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
+static int aep_destroy(ENGINE *e);
+
+static AEP_RV aep_get_connection(AEP_CONNECTION_HNDL_PTR hConnection);
+static AEP_RV aep_return_connection(AEP_CONNECTION_HNDL hConnection);
+static AEP_RV aep_close_connection(AEP_CONNECTION_HNDL hConnection);
+static AEP_RV aep_close_all_connections(int use_engine_lock, int *in_use);
+
+/* BIGNUM stuff */
+static int aep_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+       const BIGNUM *m, BN_CTX *ctx);
+
+static AEP_RV aep_mod_exp_crt(BIGNUM *r,const  BIGNUM *a, const BIGNUM *p,
+       const BIGNUM *q, const BIGNUM *dmp1,const BIGNUM *dmq1,
+       const BIGNUM *iqmp, BN_CTX *ctx);
+
+/* RSA stuff */
+#ifndef OPENSSL_NO_RSA
+static int aep_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
+#endif
+
+/* This function is aliased to mod_exp (with the mont stuff dropped). */
+static int aep_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+       const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+
+/* DSA stuff */
+#ifndef OPENSSL_NO_DSA
+static int aep_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
+       BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
+       BN_CTX *ctx, BN_MONT_CTX *in_mont);
+
+static int aep_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
+       const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+       BN_MONT_CTX *m_ctx);
+#endif
+
+/* DH stuff */
+/* This function is aliased to mod_exp (with the DH and mont dropped). */
+#ifndef OPENSSL_NO_DH
+static int aep_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
+
+/* rand stuff   */
+#ifdef AEPRAND
+static int aep_rand(unsigned char *buf, int num);
+static int aep_rand_status(void);
+#endif
+
+/* Bignum conversion stuff */
+static AEP_RV GetBigNumSize(AEP_VOID_PTR ArbBigNum, AEP_U32* BigNumSize);
+static AEP_RV MakeAEPBigNum(AEP_VOID_PTR ArbBigNum, AEP_U32 BigNumSize,
+       unsigned char* AEP_BigNum);
+static AEP_RV ConvertAEPBigNum(void* ArbBigNum, AEP_U32 BigNumSize,
+       unsigned char* AEP_BigNum);
+
+/* The definitions for control commands specific to this engine */
+#define AEP_CMD_SO_PATH                ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN aep_cmd_defns[] =
+       {
+       { AEP_CMD_SO_PATH,
+         "SO_PATH",
+         "Specifies the path to the 'aep' shared library",
+         ENGINE_CMD_FLAG_STRING
+       },
+       {0, NULL, NULL, 0}
+       };
+
+#ifndef OPENSSL_NO_RSA
+/* Our internal RSA_METHOD that we provide pointers to */
+static RSA_METHOD aep_rsa =
+       {
+       "Aep RSA method",
+       NULL,                /*rsa_pub_encrypt*/
+       NULL,                /*rsa_pub_decrypt*/
+       NULL,                /*rsa_priv_encrypt*/
+       NULL,                /*rsa_priv_encrypt*/
+       aep_rsa_mod_exp,     /*rsa_mod_exp*/
+       aep_mod_exp_mont,    /*bn_mod_exp*/
+       NULL,                /*init*/
+       NULL,                /*finish*/
+       0,                   /*flags*/
+       NULL,                /*app_data*/
+       NULL,                /*rsa_sign*/
+       NULL                 /*rsa_verify*/
+       };
+#endif
+
+#ifndef OPENSSL_NO_DSA
+/* Our internal DSA_METHOD that we provide pointers to */
+static DSA_METHOD aep_dsa =
+       {
+       "Aep DSA method",
+       NULL,                /* dsa_do_sign */
+       NULL,                /* dsa_sign_setup */
+       NULL,                /* dsa_do_verify */
+       aep_dsa_mod_exp,     /* dsa_mod_exp */
+       aep_mod_exp_dsa,     /* bn_mod_exp */
+       NULL,                /* init */
+       NULL,                /* finish */
+       0,                   /* flags */
+       NULL                 /* app_data */
+       };
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* Our internal DH_METHOD that we provide pointers to */
+static DH_METHOD aep_dh =
+       {
+       "Aep DH method",
+       NULL,
+       NULL,
+       aep_mod_exp_dh,
+       NULL,
+       NULL,
+       0,
+       NULL
+       };
+#endif
+
+#ifdef AEPRAND
+/* our internal RAND_method that we provide pointers to  */
+static RAND_METHOD aep_random =
+       {
+       /*"AEP RAND method", */
+       NULL,
+       aep_rand,
+       NULL,
+       NULL,
+       aep_rand,
+       aep_rand_status,
+       };
+#endif
+
+/*Define an array of structures to hold connections*/
+static AEP_CONNECTION_ENTRY aep_app_conn_table[MAX_PROCESS_CONNECTIONS];
+
+/*Used to determine if this is a new process*/
+static pid_t    recorded_pid = 0;
+
+#ifdef AEPRAND
+static AEP_U8   rand_block[RAND_BLK_SIZE];
+static AEP_U32  rand_block_bytes = 0;
+#endif
+
+/* Constants used when creating the ENGINE */
+static const char *engine_aep_id = "aep";
+static const char *engine_aep_name = "Aep hardware engine support";
+
+static int max_key_len = 2176;
+
+
+/* This internal function is used by ENGINE_aep() and possibly by the
+ * "dynamic" ENGINE support too */
+static int bind_aep(ENGINE *e)
+       {
+#ifndef OPENSSL_NO_RSA
+       const RSA_METHOD  *meth1;
+#endif
+#ifndef OPENSSL_NO_DSA
+       const DSA_METHOD  *meth2;
+#endif
+#ifndef OPENSSL_NO_DH
+       const DH_METHOD   *meth3;
+#endif
+
+       if(!ENGINE_set_id(e, engine_aep_id) ||
+               !ENGINE_set_name(e, engine_aep_name) ||
+#ifndef OPENSSL_NO_RSA
+               !ENGINE_set_RSA(e, &aep_rsa) ||
+#endif
+#ifndef OPENSSL_NO_DSA
+               !ENGINE_set_DSA(e, &aep_dsa) ||
+#endif
+#ifndef OPENSSL_NO_DH
+               !ENGINE_set_DH(e, &aep_dh) ||
+#endif
+#ifdef AEPRAND
+               !ENGINE_set_RAND(e, &aep_random) ||
+#endif
+               !ENGINE_set_init_function(e, aep_init) ||
+               !ENGINE_set_destroy_function(e, aep_destroy) ||
+               !ENGINE_set_finish_function(e, aep_finish) ||
+               !ENGINE_set_ctrl_function(e, aep_ctrl) ||
+               !ENGINE_set_cmd_defns(e, aep_cmd_defns))
+               return 0;
+
+#ifndef OPENSSL_NO_RSA
+       /* We know that the "PKCS1_SSLeay()" functions hook properly
+        * to the aep-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();
+       aep_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
+       aep_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
+       aep_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
+       aep_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
+#endif
+
+
+#ifndef OPENSSL_NO_DSA
+       /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish
+        * bits. */
+       meth2 = DSA_OpenSSL();
+       aep_dsa.dsa_do_sign    = meth2->dsa_do_sign;
+       aep_dsa.dsa_sign_setup = meth2->dsa_sign_setup;
+       aep_dsa.dsa_do_verify  = meth2->dsa_do_verify;
+
+       aep_dsa = *DSA_get_default_method(); 
+       aep_dsa.dsa_mod_exp = aep_dsa_mod_exp; 
+       aep_dsa.bn_mod_exp = aep_mod_exp_dsa;
+#endif
+
+#ifndef OPENSSL_NO_DH
+       /* Much the same for Diffie-Hellman */
+       meth3 = DH_OpenSSL();
+       aep_dh.generate_key = meth3->generate_key;
+       aep_dh.compute_key  = meth3->compute_key;
+       aep_dh.bn_mod_exp   = meth3->bn_mod_exp;
+#endif
+
+       /* Ensure the aep error handling is set up */
+       ERR_load_AEPHK_strings();
+
+       return 1;
+}
+
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_helper(ENGINE *e, const char *id)
+       {
+       if(id && (strcmp(id, engine_aep_id) != 0))
+               return 0;
+       if(!bind_aep(e))
+               return 0;
+       return 1;
+       }       
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
+#else
+static ENGINE *engine_aep(void)
+       {
+       ENGINE *ret = ENGINE_new();
+       if(!ret)
+               return NULL;
+       if(!bind_aep(ret))
+               {
+               ENGINE_free(ret);
+               return NULL;
+               }
+       return ret;
+       }
+
+void ENGINE_load_aep(void)
+       {
+       /* Copied from eng_[openssl|dyn].c */
+       ENGINE *toadd = engine_aep();
+       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 Aep 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 *aep_dso = NULL;
+
+/* These are the static string constants for the DSO file name and the function
+ * symbol names to bind to. 
+*/
+static const char *AEP_LIBNAME = NULL;
+static const char *get_AEP_LIBNAME(void)
+       {
+       if(AEP_LIBNAME)
+               return AEP_LIBNAME;
+       return "aep";
+       }
+static void free_AEP_LIBNAME(void)
+       {
+       if(AEP_LIBNAME)
+               OPENSSL_free((void*)AEP_LIBNAME);
+       AEP_LIBNAME = NULL;
+       }
+static long set_AEP_LIBNAME(const char *name)
+       {
+       free_AEP_LIBNAME();
+       return ((AEP_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
+       }
+
+static const char *AEP_F1    = "AEP_ModExp";
+static const char *AEP_F2    = "AEP_ModExpCrt";
+#ifdef AEPRAND
+static const char *AEP_F3    = "AEP_GenRandom";
+#endif
+static const char *AEP_F4    = "AEP_Finalize";
+static const char *AEP_F5    = "AEP_Initialize";
+static const char *AEP_F6    = "AEP_OpenConnection";
+static const char *AEP_F7    = "AEP_SetBNCallBacks";
+static const char *AEP_F8    = "AEP_CloseConnection";
+
+/* These are the function pointers that are (un)set when the library has
+ * successfully (un)loaded. */
+static t_AEP_OpenConnection    *p_AEP_OpenConnection  = NULL;
+static t_AEP_CloseConnection   *p_AEP_CloseConnection = NULL;
+static t_AEP_ModExp            *p_AEP_ModExp          = NULL;
+static t_AEP_ModExpCrt         *p_AEP_ModExpCrt       = NULL;
+#ifdef AEPRAND
+static t_AEP_GenRandom         *p_AEP_GenRandom       = NULL;
+#endif
+static t_AEP_Initialize        *p_AEP_Initialize      = NULL;
+static t_AEP_Finalize          *p_AEP_Finalize        = NULL;
+static t_AEP_SetBNCallBacks    *p_AEP_SetBNCallBacks  = NULL;
+
+/* (de)initialisation functions. */
+static int aep_init(ENGINE *e)
+       {
+       t_AEP_ModExp          *p1;
+       t_AEP_ModExpCrt       *p2;
+#ifdef AEPRAND
+       t_AEP_GenRandom       *p3;
+#endif
+       t_AEP_Finalize        *p4;
+       t_AEP_Initialize      *p5;
+       t_AEP_OpenConnection  *p6;
+       t_AEP_SetBNCallBacks  *p7;
+       t_AEP_CloseConnection *p8;
+
+       int to_return = 0;
+       if(aep_dso != NULL)
+               {
+               AEPHKerr(AEPHK_F_AEP_INIT,AEPHK_R_ALREADY_LOADED);
+               goto err;
+               }
+       /* Attempt to load libaep.so. */
+
+       aep_dso = DSO_load(NULL, get_AEP_LIBNAME(), NULL, 0);
+  
+       if(aep_dso == NULL)
+               {
+               AEPHKerr(AEPHK_F_AEP_INIT,AEPHK_R_NOT_LOADED);
+               goto err;
+               }
+
+       if(     !(p1 = (t_AEP_ModExp *)     DSO_bind_func( aep_dso,AEP_F1))  ||
+               !(p2 = (t_AEP_ModExpCrt*)   DSO_bind_func( aep_dso,AEP_F2))  ||
+#ifdef AEPRAND
+               !(p3 = (t_AEP_GenRandom*)   DSO_bind_func( aep_dso,AEP_F3))  ||
+#endif
+               !(p4 = (t_AEP_Finalize*)    DSO_bind_func( aep_dso,AEP_F4))  ||
+               !(p5 = (t_AEP_Initialize*)  DSO_bind_func( aep_dso,AEP_F5))  ||
+               !(p6 = (t_AEP_OpenConnection*) DSO_bind_func( aep_dso,AEP_F6))  ||
+               !(p7 = (t_AEP_SetBNCallBacks*) DSO_bind_func( aep_dso,AEP_F7))  ||
+               !(p8 = (t_AEP_CloseConnection*) DSO_bind_func( aep_dso,AEP_F8)))
+               {
+               AEPHKerr(AEPHK_F_AEP_INIT,AEPHK_R_NOT_LOADED);
+               goto err;
+               }
+
+       /* Copy the pointers */
+  
+       p_AEP_ModExp           = p1;
+       p_AEP_ModExpCrt        = p2;
+#ifdef AEPRAND
+       p_AEP_GenRandom        = p3;
+#endif
+       p_AEP_Finalize         = p4;
+       p_AEP_Initialize       = p5;
+       p_AEP_OpenConnection   = p6;
+       p_AEP_SetBNCallBacks   = p7;
+       p_AEP_CloseConnection  = p8;
+       to_return = 1;
+       return to_return;
+
+ err: 
+
+       if(aep_dso)
+               DSO_free(aep_dso);
+               
+       p_AEP_OpenConnection    = NULL;
+       p_AEP_ModExp            = NULL;
+       p_AEP_ModExpCrt         = NULL;
+#ifdef AEPRAND
+       p_AEP_GenRandom         = NULL;
+#endif
+       p_AEP_Initialize        = NULL;
+       p_AEP_Finalize          = NULL;
+       p_AEP_SetBNCallBacks    = NULL;
+       p_AEP_CloseConnection   = NULL;
+
+       return to_return;
+       }
+
+/* Destructor (complements the "ENGINE_aep()" constructor) */
+static int aep_destroy(ENGINE *e)
+       {
+       free_AEP_LIBNAME();
+       ERR_unload_AEPHK_strings();
+       return 1;
+       }
+
+static int aep_finish(ENGINE *e)
+       {
+       int to_return = 0, in_use;
+       AEP_RV rv;
+
+       if(aep_dso == NULL)
+               {
+               AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_NOT_LOADED);
+               goto err;
+               }
+
+       rv = aep_close_all_connections(0, &in_use);
+       if (rv != AEP_R_OK)
+               {
+               AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_CLOSE_HANDLES_FAILED);
+               goto err;
+               }
+       if (in_use)
+               {
+               AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_CONNECTIONS_IN_USE);
+               goto err;
+               }
+
+       rv = p_AEP_Finalize();
+       if (rv != AEP_R_OK)
+               {
+               AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_FINALIZE_FAILED);
+               goto err;
+               }
+
+       if(!DSO_free(aep_dso))
+               {
+               AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_UNIT_FAILURE);
+               goto err;
+               }
+
+       aep_dso = NULL;
+       p_AEP_CloseConnection   = NULL;
+       p_AEP_OpenConnection    = NULL;
+       p_AEP_ModExp            = NULL;
+       p_AEP_ModExpCrt         = NULL;
+#ifdef AEPRAND
+       p_AEP_GenRandom         = NULL;
+#endif
+       p_AEP_Initialize        = NULL;
+       p_AEP_Finalize          = NULL;
+       p_AEP_SetBNCallBacks    = NULL;
+
+       to_return = 1;
+ err:
+       return to_return;
+       }
+
+static int aep_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+       {
+       int initialised = ((aep_dso == NULL) ? 0 : 1);
+       switch(cmd)
+               {
+       case AEP_CMD_SO_PATH:
+               if(p == NULL)
+                       {
+                       AEPHKerr(AEPHK_F_AEP_CTRL,
+                               ERR_R_PASSED_NULL_PARAMETER);
+                       return 0;
+                       }
+               if(initialised)
+                       {
+                       AEPHKerr(AEPHK_F_AEP_CTRL,
+                               AEPHK_R_ALREADY_LOADED);
+                       return 0;
+                       }
+               return set_AEP_LIBNAME((const char*)p);
+       default:
+               break;
+               }
+       AEPHKerr(AEPHK_F_AEP_CTRL,AEPHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+       return 0;
+       }
+
+static int aep_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+       const BIGNUM *m, BN_CTX *ctx)
+       {
+       int to_return = 0;
+       int     r_len = 0;
+       AEP_CONNECTION_HNDL hConnection;
+       AEP_RV rv;
+       
+       r_len = BN_num_bits(m);
+
+       /* Perform in software if modulus is too large for hardware. */
+
+       if (r_len > max_key_len){
+               AEPHKerr(AEPHK_F_AEP_MOD_EXP, AEPHK_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+               return BN_mod_exp(r, a, p, m, ctx);
+       } 
+
+       /*Grab a connection from the pool*/
+       rv = aep_get_connection(&hConnection);
+       if (rv != AEP_R_OK)
+               {     
+               AEPHKerr(AEPHK_F_AEP_MOD_EXP,AEPHK_R_GET_HANDLE_FAILED);
+               return BN_mod_exp(r, a, p, m, ctx);
+               }
+
+       /*To the card with the mod exp*/
+       rv = p_AEP_ModExp(hConnection,(void*)a, (void*)p,(void*)m, (void*)r,NULL);
+
+       if (rv !=  AEP_R_OK)
+               {
+               AEPHKerr(AEPHK_F_AEP_MOD_EXP,AEPHK_R_MOD_EXP_FAILED);
+               rv = aep_close_connection(hConnection);
+               return BN_mod_exp(r, a, p, m, ctx);
+               }
+
+       /*Return the connection to the pool*/
+       rv = aep_return_connection(hConnection);
+       if (rv != AEP_R_OK)
+               {
+               AEPHKerr(AEPHK_F_AEP_RAND,AEPHK_R_RETURN_CONNECTION_FAILED); 
+               goto err;
+               }
+
+       to_return = 1;
+ err:
+       return to_return;
+       }
+       
+static AEP_RV aep_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+       const BIGNUM *q, const BIGNUM *dmp1,
+       const BIGNUM *dmq1,const BIGNUM *iqmp, BN_CTX *ctx)
+       {
+       AEP_RV rv = AEP_R_OK;
+       AEP_CONNECTION_HNDL hConnection;
+
+       /*Grab a connection from the pool*/
+       rv = aep_get_connection(&hConnection);
+       if (rv != AEP_R_OK)
+               {
+               AEPHKerr(AEPHK_F_AEP_MOD_EXP_CRT,AEPHK_R_GET_HANDLE_FAILED);
+               return FAIL_TO_SW;
+               }
+
+       /*To the card with the mod exp*/
+       rv = p_AEP_ModExpCrt(hConnection,(void*)a, (void*)p, (void*)q, (void*)dmp1,(void*)dmq1,
+               (void*)iqmp,(void*)r,NULL);
+       if (rv != AEP_R_OK)
+               {
+               AEPHKerr(AEPHK_F_AEP_MOD_EXP_CRT,AEPHK_R_MOD_EXP_CRT_FAILED);
+               rv = aep_close_connection(hConnection);
+               return FAIL_TO_SW;
+               }
+
+       /*Return the connection to the pool*/
+       rv = aep_return_connection(hConnection);
+       if (rv != AEP_R_OK)
+               {
+               AEPHKerr(AEPHK_F_AEP_RAND,AEPHK_R_RETURN_CONNECTION_FAILED); 
+               goto err;
+               }
+ err:
+       return rv;
+       }
+       
+
+#ifdef AEPRAND
+static int aep_rand(unsigned char *buf,int len )
+       {
+       AEP_RV rv = AEP_R_OK;
+       AEP_CONNECTION_HNDL hConnection;
+
+       CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+
+       /*Can the request be serviced with what's already in the buffer?*/
+       if (len <= rand_block_bytes)
+               {
+               memcpy(buf, &rand_block[RAND_BLK_SIZE - rand_block_bytes], len);
+               rand_block_bytes -= len;
+               CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+               }
+       else
+               /*If not the get another block of random bytes*/
+               {
+               CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+
+               rv = aep_get_connection(&hConnection);
+               if (rv !=  AEP_R_OK)
+                       { 
+                       AEPHKerr(AEPHK_F_AEP_RAND,AEPHK_R_GET_HANDLE_FAILED);             
+                       goto err_nounlock;
+                       }
+
+               if (len > RAND_BLK_SIZE)
+                       {
+                       rv = p_AEP_GenRandom(hConnection, len, 2, buf, NULL);
+                       if (rv !=  AEP_R_OK)
+                               {  
+                               AEPHKerr(AEPHK_F_AEP_RAND,AEPHK_R_GET_RANDOM_FAILED); 
+                               goto err_nounlock;
+                               }
+                       }
+               else
+                       {
+                       CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+
+                       rv = p_AEP_GenRandom(hConnection, RAND_BLK_SIZE, 2, &rand_block[0], NULL);
+                       if (rv !=  AEP_R_OK)
+                               {       
+                               AEPHKerr(AEPHK_F_AEP_RAND,AEPHK_R_GET_RANDOM_FAILED); 
+             
+                               goto err;
+                               }
+
+                       rand_block_bytes = RAND_BLK_SIZE;
+
+                       memcpy(buf, &rand_block[RAND_BLK_SIZE - rand_block_bytes], len);
+                       rand_block_bytes -= len;
+
+                       CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+                       }
+
+               rv = aep_return_connection(hConnection);
+               if (rv != AEP_R_OK)
+                       {
+                       AEPHKerr(AEPHK_F_AEP_RAND,AEPHK_R_RETURN_CONNECTION_FAILED); 
+         
+                       goto err_nounlock;
+                       }
+               }
+  
+       return 1;
+ err:
+       CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+ err_nounlock:
+       return 0;
+       }
+       
+static int aep_rand_status(void)
+{
+       return 1;
+}
+#endif
+
+#ifndef OPENSSL_NO_RSA
+static int aep_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
+       {
+       BN_CTX *ctx = NULL;
+       int to_return = 0;
+       AEP_RV rv = AEP_R_OK;
+
+       if ((ctx = BN_CTX_new()) == NULL)
+               goto err;
+
+       if (!aep_dso)
+               {
+               AEPHKerr(AEPHK_F_AEP_RSA_MOD_EXP,AEPHK_R_NOT_LOADED);
+               goto err;
+               }
+
+       /*See if we have all the necessary bits for a crt*/
+       if (rsa->q && rsa->dmp1 && rsa->dmq1 && rsa->iqmp)
+               {
+               rv =  aep_mod_exp_crt(r0,I,rsa->p,rsa->q, rsa->dmp1,rsa->dmq1,rsa->iqmp,ctx);
+
+               if (rv == FAIL_TO_SW){
+                       const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
+                       to_return = (*meth->rsa_mod_exp)(r0, I, rsa);
+                       goto err;
+               }
+               else if (rv != AEP_R_OK)
+                       goto err;
+               }
+       else
+               {
+               if (!rsa->d || !rsa->n)
+                       {
+                       AEPHKerr(AEPHK_F_AEP_RSA_MOD_EXP,AEPHK_R_MISSING_KEY_COMPONENTS);
+                       goto err;
+                       }
+               rv = aep_mod_exp(r0,I,rsa->d,rsa->n,ctx);
+               if  (rv != AEP_R_OK)
+                       goto err;
+       
+               }
+
+       to_return = 1;
+
+ err:
+       if(ctx)
+               BN_CTX_free(ctx);
+       return to_return;
+}
+#endif
+
+#ifndef OPENSSL_NO_DSA
+static int aep_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
+       BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
+       BN_CTX *ctx, BN_MONT_CTX *in_mont)
+       {
+       BIGNUM t;
+       int to_return = 0;
+       BN_init(&t);
+
+       /* let rr = a1 ^ p1 mod m */
+       if (!aep_mod_exp(rr,a1,p1,m,ctx)) goto end;
+       /* let t = a2 ^ p2 mod m */
+       if (!aep_mod_exp(&t,a2,p2,m,ctx)) goto end;
+       /* let rr = rr * t mod m */
+       if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end;
+       to_return = 1;
+ end: 
+       BN_free(&t);
+       return to_return;
+       }
+
+static int aep_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
+       const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+       BN_MONT_CTX *m_ctx)
+       {  
+       return aep_mod_exp(r, a, p, m, ctx); 
+       }
+#endif
+
+/* This function is aliased to mod_exp (with the mont stuff dropped). */
+static int aep_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+       const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+       {
+       return aep_mod_exp(r, a, p, m, ctx);
+       }
+
+#ifndef OPENSSL_NO_DH
+/* This function is aliased to mod_exp (with the dh and mont dropped). */
+static int aep_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 aep_mod_exp(r, a, p, m, ctx);
+       }
+#endif
+
+static AEP_RV aep_get_connection(AEP_CONNECTION_HNDL_PTR phConnection)
+       {
+       int count;
+       AEP_RV rv = AEP_R_OK;
+
+       /*Get the current process id*/
+       pid_t curr_pid;
+
+       CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+
+       curr_pid = getpid();
+
+       /*Check if this is the first time this is being called from the current
+         process*/
+       if (recorded_pid != curr_pid)
+               {
+               /*Remember our pid so we can check if we're in a new process*/
+               recorded_pid = curr_pid;
+
+               /*Call Finalize to make sure we have not inherited some data
+                 from a parent process*/
+               p_AEP_Finalize();
+     
+               /*Initialise the AEP API*/
+               rv = p_AEP_Initialize(NULL);
+
+               if (rv != AEP_R_OK)
+                       {
+                       AEPHKerr(AEPHK_F_AEP_GET_CONNECTION,AEPHK_R_INIT_FAILURE);
+                       recorded_pid = 0;
+                       goto end;
+                       }
+
+               /*Set the AEP big num call back functions*/
+               rv = p_AEP_SetBNCallBacks(&GetBigNumSize, &MakeAEPBigNum,
+                       &ConvertAEPBigNum);
+
+               if (rv != AEP_R_OK)
+                       {
+                       AEPHKerr(AEPHK_F_AEP_GET_CONNECTION,AEPHK_R_SETBNCALLBACK_FAILURE);
+                       recorded_pid = 0;
+                       goto end;
+                       }
+
+#ifdef AEPRAND
+               /*Reset the rand byte count*/
+               rand_block_bytes = 0;
+#endif
+
+               /*Init the structures*/
+               for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
+                       {
+                       aep_app_conn_table[count].conn_state = NotConnected;
+                       aep_app_conn_table[count].conn_hndl  = 0;
+                       }
+
+               /*Open a connection*/
+               rv = p_AEP_OpenConnection(phConnection);
+
+               if (rv != AEP_R_OK)
+                       {
+                       AEPHKerr(AEPHK_F_AEP_GET_CONNECTION,AEPHK_R_UNIT_FAILURE);
+                       recorded_pid = 0;
+                       goto end;
+                       }
+
+               aep_app_conn_table[0].conn_state = InUse;
+               aep_app_conn_table[0].conn_hndl = *phConnection;
+               goto end;
+               }
+       /*Check the existing connections to see if we can find a free one*/
+       for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
+               {
+               if (aep_app_conn_table[count].conn_state == Connected)
+                       {
+                       aep_app_conn_table[count].conn_state = InUse;
+                       *phConnection = aep_app_conn_table[count].conn_hndl;
+                       goto end;
+                       }
+               }
+       /*If no connections available, we're going to have to try
+         to open a new one*/
+       for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
+               {
+               if (aep_app_conn_table[count].conn_state == NotConnected)
+                       {
+                       /*Open a connection*/
+                       rv = p_AEP_OpenConnection(phConnection);
+
+                       if (rv != AEP_R_OK)
+                               {             
+                               AEPHKerr(AEPHK_F_AEP_GET_CONNECTION,AEPHK_R_UNIT_FAILURE);
+                               goto end;
+                               }
+
+                       aep_app_conn_table[count].conn_state = InUse;
+                       aep_app_conn_table[count].conn_hndl = *phConnection;
+                       goto end;
+                       }
+               }
+       rv = AEP_R_GENERAL_ERROR;
+ end:
+       CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+       return rv;
+       }
+
+
+static AEP_RV aep_return_connection(AEP_CONNECTION_HNDL hConnection)
+       {
+       int count;
+
+       CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+
+       /*Find the connection item that matches this connection handle*/
+       for(count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
+               {
+               if (aep_app_conn_table[count].conn_hndl == hConnection)
+                       {
+                       aep_app_conn_table[count].conn_state = Connected;
+                       break;
+                       }
+               }
+
+       CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+
+       return AEP_R_OK;
+       }
+
+static AEP_RV aep_close_connection(AEP_CONNECTION_HNDL hConnection)
+       {
+       int count;
+       AEP_RV rv = AEP_R_OK;
+
+       CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+
+       /*Find the connection item that matches this connection handle*/
+       for(count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
+               {
+               if (aep_app_conn_table[count].conn_hndl == hConnection)
+                       {
+                       rv = p_AEP_CloseConnection(aep_app_conn_table[count].conn_hndl);
+                       if (rv != AEP_R_OK)
+                               goto end;
+                       aep_app_conn_table[count].conn_state = NotConnected;
+                       aep_app_conn_table[count].conn_hndl  = 0;
+                       break;
+                       }
+               }
+
+ end:
+       CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+       return rv;
+       }
+
+static AEP_RV aep_close_all_connections(int use_engine_lock, int *in_use)
+       {
+       int count;
+       AEP_RV rv = AEP_R_OK;
+
+       *in_use = 0;
+       if (use_engine_lock) CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
+       for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
+               {
+               switch (aep_app_conn_table[count].conn_state)
+                       {
+               case Connected:
+                       rv = p_AEP_CloseConnection(aep_app_conn_table[count].conn_hndl);
+                       if (rv != AEP_R_OK)
+                               goto end;
+                       aep_app_conn_table[count].conn_state = NotConnected;
+                       aep_app_conn_table[count].conn_hndl  = 0;
+                       break;
+               case InUse:
+                       (*in_use)++;
+                       break;
+               case NotConnected:
+                       break;
+                       }
+               }
+ end:
+       if (use_engine_lock) CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+       return rv;
+       }
+
+/*BigNum call back functions, used to convert OpenSSL bignums into AEP bignums.
+  Note only 32bit Openssl build support*/
+
+static AEP_RV GetBigNumSize(AEP_VOID_PTR ArbBigNum, AEP_U32* BigNumSize)
+       {
+       BIGNUM* bn;
+
+       /*Cast the ArbBigNum pointer to our BIGNUM struct*/
+       bn = (BIGNUM*) ArbBigNum;
+
+#ifdef SIXTY_FOUR_BIT_LONG
+       *BigNumSize = bn->top << 3;
+#else
+       /*Size of the bignum in bytes is equal to the bn->top (no of 32 bit
+         words) multiplies by 4*/
+       *BigNumSize = bn->top << 2;
+#endif
+
+       return AEP_R_OK;
+       }
+
+static AEP_RV MakeAEPBigNum(AEP_VOID_PTR ArbBigNum, AEP_U32 BigNumSize,
+       unsigned char* AEP_BigNum)
+       {
+       BIGNUM* bn;
+
+#ifndef SIXTY_FOUR_BIT_LONG
+       unsigned char* buf;
+       int i;
+#endif
+
+       /*Cast the ArbBigNum pointer to our BIGNUM struct*/
+       bn = (BIGNUM*) ArbBigNum;
+
+#ifdef SIXTY_FOUR_BIT_LONG
+       memcpy(AEP_BigNum, bn->d, BigNumSize);
+#else
+       /*Must copy data into a (monotone) least significant byte first format
+         performing endian conversion if necessary*/
+       for(i=0;i<bn->top;i++)
+               {
+               buf = (unsigned char*)&bn->d[i];
+
+               *((AEP_U32*)AEP_BigNum) = (AEP_U32)
+                       ((unsigned) buf[1] << 8 | buf[0]) |
+                       ((unsigned) buf[3] << 8 | buf[2])  << 16;
+
+               AEP_BigNum += 4;
+               }
+#endif
+
+       return AEP_R_OK;
+       }
+
+/*Turn an AEP Big Num back to a user big num*/
+static AEP_RV ConvertAEPBigNum(void* ArbBigNum, AEP_U32 BigNumSize,
+       unsigned char* AEP_BigNum)
+       {
+       BIGNUM* bn;
+#ifndef SIXTY_FOUR_BIT_LONG
+       int i;
+#endif
+
+       bn = (BIGNUM*)ArbBigNum;
+
+       /*Expand the result bn so that it can hold our big num.
+         Size is in bits*/
+       bn_expand(bn, (int)(BigNumSize << 3));
+
+#ifdef SIXTY_FOUR_BIT_LONG
+       bn->top = BigNumSize >> 3;
+       
+       if((BigNumSize & 7) != 0)
+               bn->top++;
+
+       memset(bn->d, 0, bn->top << 3); 
+
+       memcpy(bn->d, AEP_BigNum, BigNumSize);
+#else
+       bn->top = BigNumSize >> 2;
+       for(i=0;i<bn->top;i++)
+               {
+               bn->d[i] = (AEP_U32)
+                       ((unsigned) AEP_BigNum[3] << 8 | AEP_BigNum[2]) << 16 |
+                       ((unsigned) AEP_BigNum[1] << 8 | AEP_BigNum[0]);
+               AEP_BigNum += 4;
+               }
+#endif
+
+       return AEP_R_OK;
+}      
+       
+#endif /* !OPENSSL_NO_HW_AEP */
+#endif /* !OPENSSL_NO_HW */
diff --git a/engines/e_aep_err.c b/engines/e_aep_err.c
new file mode 100644 (file)
index 0000000..092f532
--- /dev/null
@@ -0,0 +1,157 @@
+/* hw_aep_err.c */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "hw_aep_err.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA AEPHK_str_functs[]=
+       {
+{ERR_PACK(0,AEPHK_F_AEP_CTRL,0),       "AEP_CTRL"},
+{ERR_PACK(0,AEPHK_F_AEP_FINISH,0),     "AEP_FINISH"},
+{ERR_PACK(0,AEPHK_F_AEP_GET_CONNECTION,0),     "AEP_GET_CONNECTION"},
+{ERR_PACK(0,AEPHK_F_AEP_INIT,0),       "AEP_INIT"},
+{ERR_PACK(0,AEPHK_F_AEP_MOD_EXP,0),    "AEP_MOD_EXP"},
+{ERR_PACK(0,AEPHK_F_AEP_MOD_EXP_CRT,0),        "AEP_MOD_EXP_CRT"},
+{ERR_PACK(0,AEPHK_F_AEP_RAND,0),       "AEP_RAND"},
+{ERR_PACK(0,AEPHK_F_AEP_RSA_MOD_EXP,0),        "AEP_RSA_MOD_EXP"},
+{0,NULL}
+       };
+
+static ERR_STRING_DATA AEPHK_str_reasons[]=
+       {
+{AEPHK_R_ALREADY_LOADED                  ,"already loaded"},
+{AEPHK_R_CLOSE_HANDLES_FAILED            ,"close handles failed"},
+{AEPHK_R_CONNECTIONS_IN_USE              ,"connections in use"},
+{AEPHK_R_CTRL_COMMAND_NOT_IMPLEMENTED    ,"ctrl command not implemented"},
+{AEPHK_R_FINALIZE_FAILED                 ,"finalize failed"},
+{AEPHK_R_GET_HANDLE_FAILED               ,"get handle failed"},
+{AEPHK_R_GET_RANDOM_FAILED               ,"get random failed"},
+{AEPHK_R_INIT_FAILURE                    ,"init failure"},
+{AEPHK_R_MISSING_KEY_COMPONENTS          ,"missing key components"},
+{AEPHK_R_MOD_EXP_CRT_FAILED              ,"mod exp crt failed"},
+{AEPHK_R_MOD_EXP_FAILED                  ,"mod exp failed"},
+{AEPHK_R_NOT_LOADED                      ,"not loaded"},
+{AEPHK_R_OK                              ,"ok"},
+{AEPHK_R_RETURN_CONNECTION_FAILED        ,"return connection failed"},
+{AEPHK_R_SETBNCALLBACK_FAILURE           ,"setbncallback failure"},
+{AEPHK_R_SIZE_TOO_LARGE_OR_TOO_SMALL     ,"size too large or too small"},
+{AEPHK_R_UNIT_FAILURE                    ,"unit failure"},
+{0,NULL}
+       };
+
+#endif
+
+#ifdef AEPHK_LIB_NAME
+static ERR_STRING_DATA AEPHK_lib_name[]=
+        {
+{0     ,AEPHK_LIB_NAME},
+{0,NULL}
+       };
+#endif
+
+
+static int AEPHK_lib_error_code=0;
+static int AEPHK_error_init=1;
+
+static void ERR_load_AEPHK_strings(void)
+       {
+       if (AEPHK_lib_error_code == 0)
+               AEPHK_lib_error_code=ERR_get_next_error_library();
+
+       if (AEPHK_error_init)
+               {
+               AEPHK_error_init=0;
+#ifndef OPENSSL_NO_ERR
+               ERR_load_strings(AEPHK_lib_error_code,AEPHK_str_functs);
+               ERR_load_strings(AEPHK_lib_error_code,AEPHK_str_reasons);
+#endif
+
+#ifdef AEPHK_LIB_NAME
+               AEPHK_lib_name->error = ERR_PACK(AEPHK_lib_error_code,0,0);
+               ERR_load_strings(0,AEPHK_lib_name);
+#endif
+               }
+       }
+
+static void ERR_unload_AEPHK_strings(void)
+       {
+       if (AEPHK_error_init == 0)
+               {
+#ifndef OPENSSL_NO_ERR
+               ERR_unload_strings(AEPHK_lib_error_code,AEPHK_str_functs);
+               ERR_unload_strings(AEPHK_lib_error_code,AEPHK_str_reasons);
+#endif
+
+#ifdef AEPHK_LIB_NAME
+               ERR_unload_strings(0,AEPHK_lib_name);
+#endif
+               AEPHK_error_init=1;
+               }
+       }
+
+static void ERR_AEPHK_error(int function, int reason, char *file, int line)
+       {
+       if (AEPHK_lib_error_code == 0)
+               AEPHK_lib_error_code=ERR_get_next_error_library();
+       ERR_PUT_error(AEPHK_lib_error_code,function,reason,file,line);
+       }
diff --git a/engines/e_aep_err.h b/engines/e_aep_err.h
new file mode 100644 (file)
index 0000000..8fe4cf9
--- /dev/null
@@ -0,0 +1,101 @@
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_AEPHK_ERR_H
+#define HEADER_AEPHK_ERR_H
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+static void ERR_load_AEPHK_strings(void);
+static void ERR_unload_AEPHK_strings(void);
+static void ERR_AEPHK_error(int function, int reason, char *file, int line);
+#define AEPHKerr(f,r) ERR_AEPHK_error((f),(r),__FILE__,__LINE__)
+
+/* Error codes for the AEPHK functions. */
+
+/* Function codes. */
+#define AEPHK_F_AEP_CTRL                                100
+#define AEPHK_F_AEP_FINISH                              101
+#define AEPHK_F_AEP_GET_CONNECTION                      102
+#define AEPHK_F_AEP_INIT                                103
+#define AEPHK_F_AEP_MOD_EXP                             104
+#define AEPHK_F_AEP_MOD_EXP_CRT                                 105
+#define AEPHK_F_AEP_RAND                                106
+#define AEPHK_F_AEP_RSA_MOD_EXP                                 107
+
+/* Reason codes. */
+#define AEPHK_R_ALREADY_LOADED                          100
+#define AEPHK_R_CLOSE_HANDLES_FAILED                    101
+#define AEPHK_R_CONNECTIONS_IN_USE                      102
+#define AEPHK_R_CTRL_COMMAND_NOT_IMPLEMENTED            103
+#define AEPHK_R_FINALIZE_FAILED                                 104
+#define AEPHK_R_GET_HANDLE_FAILED                       105
+#define AEPHK_R_GET_RANDOM_FAILED                       106
+#define AEPHK_R_INIT_FAILURE                            107
+#define AEPHK_R_MISSING_KEY_COMPONENTS                  108
+#define AEPHK_R_MOD_EXP_CRT_FAILED                      109
+#define AEPHK_R_MOD_EXP_FAILED                          110
+#define AEPHK_R_NOT_LOADED                              111
+#define AEPHK_R_OK                                      112
+#define AEPHK_R_RETURN_CONNECTION_FAILED                113
+#define AEPHK_R_SETBNCALLBACK_FAILURE                   114
+#define AEPHK_R_SIZE_TOO_LARGE_OR_TOO_SMALL             116
+#define AEPHK_R_UNIT_FAILURE                            115
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/engines/e_atalla.c b/engines/e_atalla.c
new file mode 100644 (file)
index 0000000..6151c46
--- /dev/null
@@ -0,0 +1,592 @@
+/* crypto/engine/hw_atalla.c */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include "cryptlib.h"
+#include <openssl/dso.h>
+#include <openssl/engine.h>
+
+#ifndef OPENSSL_NO_HW
+#ifndef OPENSSL_NO_HW_ATALLA
+
+#ifdef FLAT_INC
+#include "atalla.h"
+#else
+#include "vendor_defns/atalla.h"
+#endif
+
+#define ATALLA_LIB_NAME "atalla engine"
+#include "hw_atalla_err.c"
+
+static int atalla_destroy(ENGINE *e);
+static int atalla_init(ENGINE *e);
+static int atalla_finish(ENGINE *e);
+static int atalla_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
+
+/* BIGNUM stuff */
+static int atalla_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+               const BIGNUM *m, BN_CTX *ctx);
+
+#ifndef OPENSSL_NO_RSA
+/* RSA stuff */
+static int atalla_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
+#endif
+/* This function is aliased to mod_exp (with the mont stuff dropped). */
+static int atalla_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+               const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+
+#ifndef OPENSSL_NO_DSA
+/* DSA stuff */
+static int atalla_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
+               BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
+               BN_CTX *ctx, BN_MONT_CTX *in_mont);
+static int atalla_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
+               const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+               BN_MONT_CTX *m_ctx);
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* DH stuff */
+/* This function is alised to mod_exp (with the DH and mont dropped). */
+static int atalla_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
+
+/* The definitions for control commands specific to this engine */
+#define ATALLA_CMD_SO_PATH             ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN atalla_cmd_defns[] = {
+       {ATALLA_CMD_SO_PATH,
+               "SO_PATH",
+               "Specifies the path to the 'atasi' shared library",
+               ENGINE_CMD_FLAG_STRING},
+       {0, NULL, NULL, 0}
+       };
+
+#ifndef OPENSSL_NO_RSA
+/* Our internal RSA_METHOD that we provide pointers to */
+static RSA_METHOD atalla_rsa =
+       {
+       "Atalla RSA method",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       atalla_rsa_mod_exp,
+       atalla_mod_exp_mont,
+       NULL,
+       NULL,
+       0,
+       NULL,
+       NULL,
+       NULL
+       };
+#endif
+
+#ifndef OPENSSL_NO_DSA
+/* Our internal DSA_METHOD that we provide pointers to */
+static DSA_METHOD atalla_dsa =
+       {
+       "Atalla DSA method",
+       NULL, /* dsa_do_sign */
+       NULL, /* dsa_sign_setup */
+       NULL, /* dsa_do_verify */
+       atalla_dsa_mod_exp, /* dsa_mod_exp */
+       atalla_mod_exp_dsa, /* bn_mod_exp */
+       NULL, /* init */
+       NULL, /* finish */
+       0, /* flags */
+       NULL /* app_data */
+       };
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* Our internal DH_METHOD that we provide pointers to */
+static DH_METHOD atalla_dh =
+       {
+       "Atalla DH method",
+       NULL,
+       NULL,
+       atalla_mod_exp_dh,
+       NULL,
+       NULL,
+       0,
+       NULL
+       };
+#endif
+
+/* Constants used when creating the ENGINE */
+static const char *engine_atalla_id = "atalla";
+static const char *engine_atalla_name = "Atalla hardware engine support";
+
+/* This internal function is used by ENGINE_atalla() 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_DSA
+       const DSA_METHOD *meth2;
+#endif
+#ifndef OPENSSL_NO_DH
+       const DH_METHOD *meth3;
+#endif
+       if(!ENGINE_set_id(e, engine_atalla_id) ||
+                       !ENGINE_set_name(e, engine_atalla_name) ||
+#ifndef OPENSSL_NO_RSA
+                       !ENGINE_set_RSA(e, &atalla_rsa) ||
+#endif
+#ifndef OPENSSL_NO_DSA
+                       !ENGINE_set_DSA(e, &atalla_dsa) ||
+#endif
+#ifndef OPENSSL_NO_DH
+                       !ENGINE_set_DH(e, &atalla_dh) ||
+#endif
+                       !ENGINE_set_destroy_function(e, atalla_destroy) ||
+                       !ENGINE_set_init_function(e, atalla_init) ||
+                       !ENGINE_set_finish_function(e, atalla_finish) ||
+                       !ENGINE_set_ctrl_function(e, atalla_ctrl) ||
+                       !ENGINE_set_cmd_defns(e, atalla_cmd_defns))
+               return 0;
+
+#ifndef OPENSSL_NO_RSA
+       /* We know that the "PKCS1_SSLeay()" functions hook properly
+        * to the atalla-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();
+       atalla_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
+       atalla_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
+       atalla_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
+       atalla_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
+#endif
+
+#ifndef OPENSSL_NO_DSA
+       /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish
+        * bits. */
+       meth2 = DSA_OpenSSL();
+       atalla_dsa.dsa_do_sign = meth2->dsa_do_sign;
+       atalla_dsa.dsa_sign_setup = meth2->dsa_sign_setup;
+       atalla_dsa.dsa_do_verify = meth2->dsa_do_verify;
+#endif
+
+#ifndef OPENSSL_NO_DH
+       /* Much the same for Diffie-Hellman */
+       meth3 = DH_OpenSSL();
+       atalla_dh.generate_key = meth3->generate_key;
+       atalla_dh.compute_key = meth3->compute_key;
+#endif
+
+       /* Ensure the atalla error handling is set up */
+       ERR_load_ATALLA_strings();
+       return 1;
+       }
+
+static ENGINE *engine_atalla(void)
+       {
+       ENGINE *ret = ENGINE_new();
+       if(!ret)
+               return NULL;
+       if(!bind_helper(ret))
+               {
+               ENGINE_free(ret);
+               return NULL;
+               }
+       return ret;
+       }
+
+void ENGINE_load_atalla(void)
+       {
+       /* Copied from eng_[openssl|dyn].c */
+       ENGINE *toadd = engine_atalla();
+       if(!toadd) return;
+       ENGINE_add(toadd);
+       ENGINE_free(toadd);
+       ERR_clear_error();
+       }
+
+/* This is a process-global DSO handle used for loading and unloading
+ * the Atalla 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 *atalla_dso = NULL;
+
+/* These are the function pointers that are (un)set when the library has
+ * successfully (un)loaded. */
+static tfnASI_GetHardwareConfig *p_Atalla_GetHardwareConfig = NULL;
+static tfnASI_RSAPrivateKeyOpFn *p_Atalla_RSAPrivateKeyOpFn = NULL;
+static tfnASI_GetPerformanceStatistics *p_Atalla_GetPerformanceStatistics = NULL;
+
+/* These are the static string constants for the DSO file name and the function
+ * symbol names to bind to. Regrettably, the DSO name on *nix appears to be
+ * "atasi.so" rather than something more consistent like "libatasi.so". At the
+ * time of writing, I'm not sure what the file name on win32 is but clearly
+ * native name translation is not possible (eg libatasi.so on *nix, and
+ * atasi.dll on win32). For the purposes of testing, I have created a symbollic
+ * link called "libatasi.so" so that we can use native name-translation - a
+ * better solution will be needed. */
+static const char *ATALLA_LIBNAME = NULL;
+static const char *get_ATALLA_LIBNAME(void)
+       {
+               if(ATALLA_LIBNAME)
+                       return ATALLA_LIBNAME;
+               return "atasi";
+       }
+static void free_ATALLA_LIBNAME(void)
+       {
+               if(ATALLA_LIBNAME)
+                       OPENSSL_free((void*)ATALLA_LIBNAME);
+               ATALLA_LIBNAME = NULL;
+       }
+static long set_ATALLA_LIBNAME(const char *name)
+       {
+       free_ATALLA_LIBNAME();
+       return (((ATALLA_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
+       }
+static const char *ATALLA_F1 = "ASI_GetHardwareConfig";
+static const char *ATALLA_F2 = "ASI_RSAPrivateKeyOpFn";
+static const char *ATALLA_F3 = "ASI_GetPerformanceStatistics";
+
+/* Destructor (complements the "ENGINE_atalla()" constructor) */
+static int atalla_destroy(ENGINE *e)
+       {
+       free_ATALLA_LIBNAME();
+       /* Unload the atalla error strings so any error state including our
+        * functs or reasons won't lead to a segfault (they simply get displayed
+        * without corresponding string data because none will be found). */
+       ERR_unload_ATALLA_strings();
+       return 1;
+       }
+
+/* (de)initialisation functions. */
+static int atalla_init(ENGINE *e)
+       {
+       tfnASI_GetHardwareConfig *p1;
+       tfnASI_RSAPrivateKeyOpFn *p2;
+       tfnASI_GetPerformanceStatistics *p3;
+       /* Not sure of the origin of this magic value, but Ben's code had it
+        * and it seemed to have been working for a few people. :-) */
+       unsigned int config_buf[1024];
+
+       if(atalla_dso != NULL)
+               {
+               ATALLAerr(ATALLA_F_ATALLA_INIT,ATALLA_R_ALREADY_LOADED);
+               goto err;
+               }
+       /* Attempt to load libatasi.so/atasi.dll/whatever. Needs to be
+        * changed unfortunately because the Atalla drivers don't have
+        * standard library names that can be platform-translated well. */
+       /* TODO: Work out how to actually map to the names the Atalla
+        * drivers really use - for now a symbollic link needs to be
+        * created on the host system from libatasi.so to atasi.so on
+        * unix variants. */
+       atalla_dso = DSO_load(NULL, get_ATALLA_LIBNAME(), NULL, 0);
+       if(atalla_dso == NULL)
+               {
+               ATALLAerr(ATALLA_F_ATALLA_INIT,ATALLA_R_NOT_LOADED);
+               goto err;
+               }
+       if(!(p1 = (tfnASI_GetHardwareConfig *)DSO_bind_func(
+                               atalla_dso, ATALLA_F1)) ||
+                       !(p2 = (tfnASI_RSAPrivateKeyOpFn *)DSO_bind_func(
+                               atalla_dso, ATALLA_F2)) ||
+                       !(p3 = (tfnASI_GetPerformanceStatistics *)DSO_bind_func(
+                               atalla_dso, ATALLA_F3)))
+               {
+               ATALLAerr(ATALLA_F_ATALLA_INIT,ATALLA_R_NOT_LOADED);
+               goto err;
+               }
+       /* Copy the pointers */
+       p_Atalla_GetHardwareConfig = p1;
+       p_Atalla_RSAPrivateKeyOpFn = p2;
+       p_Atalla_GetPerformanceStatistics = p3;
+       /* Perform a basic test to see if there's actually any unit
+        * running. */
+       if(p1(0L, config_buf) != 0)
+               {
+               ATALLAerr(ATALLA_F_ATALLA_INIT,ATALLA_R_UNIT_FAILURE);
+               goto err;
+               }
+       /* Everything's fine. */
+       return 1;
+err:
+       if(atalla_dso)
+               DSO_free(atalla_dso);
+       p_Atalla_GetHardwareConfig = NULL;
+       p_Atalla_RSAPrivateKeyOpFn = NULL;
+       p_Atalla_GetPerformanceStatistics = NULL;
+       return 0;
+       }
+
+static int atalla_finish(ENGINE *e)
+       {
+       free_ATALLA_LIBNAME();
+       if(atalla_dso == NULL)
+               {
+               ATALLAerr(ATALLA_F_ATALLA_FINISH,ATALLA_R_NOT_LOADED);
+               return 0;
+               }
+       if(!DSO_free(atalla_dso))
+               {
+               ATALLAerr(ATALLA_F_ATALLA_FINISH,ATALLA_R_UNIT_FAILURE);
+               return 0;
+               }
+       atalla_dso = NULL;
+       p_Atalla_GetHardwareConfig = NULL;
+       p_Atalla_RSAPrivateKeyOpFn = NULL;
+       p_Atalla_GetPerformanceStatistics = NULL;
+       return 1;
+       }
+
+static int atalla_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+       {
+       int initialised = ((atalla_dso == NULL) ? 0 : 1);
+       switch(cmd)
+               {
+       case ATALLA_CMD_SO_PATH:
+               if(p == NULL)
+                       {
+                       ATALLAerr(ATALLA_F_ATALLA_CTRL,ERR_R_PASSED_NULL_PARAMETER);
+                       return 0;
+                       }
+               if(initialised)
+                       {
+                       ATALLAerr(ATALLA_F_ATALLA_CTRL,ATALLA_R_ALREADY_LOADED);
+                       return 0;
+                       }
+               return set_ATALLA_LIBNAME((const char *)p);
+       default:
+               break;
+               }
+       ATALLAerr(ATALLA_F_ATALLA_CTRL,ATALLA_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+       return 0;
+       }
+
+static int atalla_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                       const BIGNUM *m, BN_CTX *ctx)
+       {
+       /* I need somewhere to store temporary serialised values for
+        * use with the Atalla API calls. A neat cheat - I'll use
+        * BIGNUMs from the BN_CTX but access their arrays directly as
+        * byte arrays <grin>. This way I don't have to clean anything
+        * up. */
+       BIGNUM *modulus;
+       BIGNUM *exponent;
+       BIGNUM *argument;
+       BIGNUM *result;
+       RSAPrivateKey keydata;
+       int to_return, numbytes;
+
+       modulus = exponent = argument = result = NULL;
+       to_return = 0; /* expect failure */
+
+       if(!atalla_dso)
+               {
+               ATALLAerr(ATALLA_F_ATALLA_MOD_EXP,ATALLA_R_NOT_LOADED);
+               goto err;
+               }
+       /* Prepare the params */
+       BN_CTX_start(ctx);
+       modulus = BN_CTX_get(ctx);
+       exponent = BN_CTX_get(ctx);
+       argument = BN_CTX_get(ctx);
+       result = BN_CTX_get(ctx);
+       if (!result)
+               {
+               ATALLAerr(ATALLA_F_ATALLA_MOD_EXP,ATALLA_R_BN_CTX_FULL);
+               goto err;
+               }
+       if(!bn_wexpand(modulus, m->top) || !bn_wexpand(exponent, m->top) ||
+          !bn_wexpand(argument, m->top) || !bn_wexpand(result, m->top))
+               {
+               ATALLAerr(ATALLA_F_ATALLA_MOD_EXP,ATALLA_R_BN_EXPAND_FAIL);
+               goto err;
+               }
+       /* Prepare the key-data */
+       memset(&keydata, 0,sizeof keydata);
+       numbytes = BN_num_bytes(m);
+       memset(exponent->d, 0, numbytes);
+       memset(modulus->d, 0, numbytes);
+       BN_bn2bin(p, (unsigned char *)exponent->d + numbytes - BN_num_bytes(p));
+       BN_bn2bin(m, (unsigned char *)modulus->d + numbytes - BN_num_bytes(m));
+       keydata.privateExponent.data = (unsigned char *)exponent->d;
+       keydata.privateExponent.len = numbytes;
+       keydata.modulus.data = (unsigned char *)modulus->d;
+       keydata.modulus.len = numbytes;
+       /* Prepare the argument */
+       memset(argument->d, 0, numbytes);
+       memset(result->d, 0, numbytes);
+       BN_bn2bin(a, (unsigned char *)argument->d + numbytes - BN_num_bytes(a));
+       /* Perform the operation */
+       if(p_Atalla_RSAPrivateKeyOpFn(&keydata, (unsigned char *)result->d,
+                       (unsigned char *)argument->d,
+                       keydata.modulus.len) != 0)
+               {
+               ATALLAerr(ATALLA_F_ATALLA_MOD_EXP,ATALLA_R_REQUEST_FAILED);
+               goto err;
+               }
+       /* Convert the response */
+       BN_bin2bn((unsigned char *)result->d, numbytes, r);
+       to_return = 1;
+err:
+       BN_CTX_end(ctx);
+       return to_return;
+       }
+
+#ifndef OPENSSL_NO_RSA
+static int atalla_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
+       {
+       BN_CTX *ctx = NULL;
+       int to_return = 0;
+
+       if(!atalla_dso)
+               {
+               ATALLAerr(ATALLA_F_ATALLA_RSA_MOD_EXP,ATALLA_R_NOT_LOADED);
+               goto err;
+               }
+       if((ctx = BN_CTX_new()) == NULL)
+               goto err;
+       if(!rsa->d || !rsa->n)
+               {
+               ATALLAerr(ATALLA_F_ATALLA_RSA_MOD_EXP,ATALLA_R_MISSING_KEY_COMPONENTS);
+               goto err;
+               }
+       to_return = atalla_mod_exp(r0, I, rsa->d, rsa->n, ctx);
+err:
+       if(ctx)
+               BN_CTX_free(ctx);
+       return to_return;
+       }
+#endif
+
+#ifndef OPENSSL_NO_DSA
+/* This code was liberated and adapted from the commented-out code in
+ * dsa_ossl.c. Because of the unoptimised form of the Atalla acceleration
+ * (it doesn't have a CRT form for RSA), this function means that an
+ * Atalla system running with a DSA server certificate can handshake
+ * around 5 or 6 times faster/more than an equivalent system running with
+ * RSA. Just check out the "signs" statistics from the RSA and DSA parts
+ * of "openssl speed -engine atalla dsa1024 rsa1024". */
+static int atalla_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
+               BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
+               BN_CTX *ctx, BN_MONT_CTX *in_mont)
+       {
+       BIGNUM t;
+       int to_return = 0;
+       BN_init(&t);
+       /* let rr = a1 ^ p1 mod m */
+       if (!atalla_mod_exp(rr,a1,p1,m,ctx)) goto end;
+       /* let t = a2 ^ p2 mod m */
+       if (!atalla_mod_exp(&t,a2,p2,m,ctx)) goto end;
+       /* let rr = rr * t mod m */
+       if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end;
+       to_return = 1;
+end:
+       BN_free(&t);
+       return to_return;
+       }
+
+static int atalla_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
+               const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+               BN_MONT_CTX *m_ctx)
+       {
+       return atalla_mod_exp(r, a, p, m, ctx);
+       }
+#endif
+
+/* This function is aliased to mod_exp (with the mont stuff dropped). */
+static int atalla_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+               const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+       {
+       return atalla_mod_exp(r, a, p, m, ctx);
+       }
+
+#ifndef OPENSSL_NO_DH
+/* This function is aliased to mod_exp (with the dh and mont dropped). */
+static int atalla_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 atalla_mod_exp(r, a, p, m, ctx);
+       }
+#endif
+
+/* This stuff is needed if this ENGINE is being compiled into a self-contained
+ * shared-library. */
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_fn(ENGINE *e, const char *id)
+       {
+       if(id && (strcmp(id, engine_atalla_id) != 0))
+               return 0;
+       if(!bind_helper(e))
+               return 0;
+       return 1;
+       }
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
+#endif /* ENGINE_DYNAMIC_SUPPORT */
+
+#endif /* !OPENSSL_NO_HW_ATALLA */
+#endif /* !OPENSSL_NO_HW */
diff --git a/engines/e_atalla_err.c b/engines/e_atalla_err.c
new file mode 100644 (file)
index 0000000..1df9c45
--- /dev/null
@@ -0,0 +1,145 @@
+/* hw_atalla_err.c */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "hw_atalla_err.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA ATALLA_str_functs[]=
+       {
+{ERR_PACK(0,ATALLA_F_ATALLA_CTRL,0),   "ATALLA_CTRL"},
+{ERR_PACK(0,ATALLA_F_ATALLA_FINISH,0), "ATALLA_FINISH"},
+{ERR_PACK(0,ATALLA_F_ATALLA_INIT,0),   "ATALLA_INIT"},
+{ERR_PACK(0,ATALLA_F_ATALLA_MOD_EXP,0),        "ATALLA_MOD_EXP"},
+{ERR_PACK(0,ATALLA_F_ATALLA_RSA_MOD_EXP,0),    "ATALLA_RSA_MOD_EXP"},
+{0,NULL}
+       };
+
+static ERR_STRING_DATA ATALLA_str_reasons[]=
+       {
+{ATALLA_R_ALREADY_LOADED                 ,"already loaded"},
+{ATALLA_R_BN_CTX_FULL                    ,"bn ctx full"},
+{ATALLA_R_BN_EXPAND_FAIL                 ,"bn expand fail"},
+{ATALLA_R_CTRL_COMMAND_NOT_IMPLEMENTED   ,"ctrl command not implemented"},
+{ATALLA_R_MISSING_KEY_COMPONENTS         ,"missing key components"},
+{ATALLA_R_NOT_LOADED                     ,"not loaded"},
+{ATALLA_R_REQUEST_FAILED                 ,"request failed"},
+{ATALLA_R_UNIT_FAILURE                   ,"unit failure"},
+{0,NULL}
+       };
+
+#endif
+
+#ifdef ATALLA_LIB_NAME
+static ERR_STRING_DATA ATALLA_lib_name[]=
+        {
+{0     ,ATALLA_LIB_NAME},
+{0,NULL}
+       };
+#endif
+
+
+static int ATALLA_lib_error_code=0;
+static int ATALLA_error_init=1;
+
+static void ERR_load_ATALLA_strings(void)
+       {
+       if (ATALLA_lib_error_code == 0)
+               ATALLA_lib_error_code=ERR_get_next_error_library();
+
+       if (ATALLA_error_init)
+               {
+               ATALLA_error_init=0;
+#ifndef OPENSSL_NO_ERR
+               ERR_load_strings(ATALLA_lib_error_code,ATALLA_str_functs);
+               ERR_load_strings(ATALLA_lib_error_code,ATALLA_str_reasons);
+#endif
+
+#ifdef ATALLA_LIB_NAME
+               ATALLA_lib_name->error = ERR_PACK(ATALLA_lib_error_code,0,0);
+               ERR_load_strings(0,ATALLA_lib_name);
+#endif
+               }
+       }
+
+static void ERR_unload_ATALLA_strings(void)
+       {
+       if (ATALLA_error_init == 0)
+               {
+#ifndef OPENSSL_NO_ERR
+               ERR_unload_strings(ATALLA_lib_error_code,ATALLA_str_functs);
+               ERR_unload_strings(ATALLA_lib_error_code,ATALLA_str_reasons);
+#endif
+
+#ifdef ATALLA_LIB_NAME
+               ERR_unload_strings(0,ATALLA_lib_name);
+#endif
+               ATALLA_error_init=1;
+               }
+       }
+
+static void ERR_ATALLA_error(int function, int reason, char *file, int line)
+       {
+       if (ATALLA_lib_error_code == 0)
+               ATALLA_lib_error_code=ERR_get_next_error_library();
+       ERR_PUT_error(ATALLA_lib_error_code,function,reason,file,line);
+       }
diff --git a/engines/e_atalla_err.h b/engines/e_atalla_err.h
new file mode 100644 (file)
index 0000000..cdac052
--- /dev/null
@@ -0,0 +1,89 @@
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_ATALLA_ERR_H
+#define HEADER_ATALLA_ERR_H
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+static void ERR_load_ATALLA_strings(void);
+static void ERR_unload_ATALLA_strings(void);
+static void ERR_ATALLA_error(int function, int reason, char *file, int line);
+#define ATALLAerr(f,r) ERR_ATALLA_error((f),(r),__FILE__,__LINE__)
+
+/* Error codes for the ATALLA functions. */
+
+/* Function codes. */
+#define ATALLA_F_ATALLA_CTRL                            100
+#define ATALLA_F_ATALLA_FINISH                          101
+#define ATALLA_F_ATALLA_INIT                            102
+#define ATALLA_F_ATALLA_MOD_EXP                                 103
+#define ATALLA_F_ATALLA_RSA_MOD_EXP                     104
+
+/* Reason codes. */
+#define ATALLA_R_ALREADY_LOADED                                 100
+#define ATALLA_R_BN_CTX_FULL                            101
+#define ATALLA_R_BN_EXPAND_FAIL                                 102
+#define ATALLA_R_CTRL_COMMAND_NOT_IMPLEMENTED           103
+#define ATALLA_R_MISSING_KEY_COMPONENTS                         104
+#define ATALLA_R_NOT_LOADED                             105
+#define ATALLA_R_REQUEST_FAILED                                 106
+#define ATALLA_R_UNIT_FAILURE                           107
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/engines/e_cswift.c b/engines/e_cswift.c
new file mode 100644 (file)
index 0000000..1b4e4e8
--- /dev/null
@@ -0,0 +1,995 @@
+/* crypto/engine/hw_cswift.c */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include "cryptlib.h"
+#include <openssl/dso.h>
+#include <openssl/engine.h>
+
+#ifndef OPENSSL_NO_HW
+#ifndef OPENSSL_NO_HW_CSWIFT
+
+/* Attribution notice: Rainbow have generously allowed me to reproduce
+ * the necessary definitions here from their API. This means the support
+ * can build independently of whether application builders have the
+ * API or hardware. This will allow developers to easily produce software
+ * that has latent hardware support for any users that have accelerators
+ * installed, without the developers themselves needing anything extra.
+ *
+ * I have only clipped the parts from the CryptoSwift header files that
+ * are (or seem) relevant to the CryptoSwift support code. This is
+ * simply to keep the file sizes reasonable.
+ * [Geoff]
+ */
+#ifdef FLAT_INC
+#include "cswift.h"
+#else
+#include "vendor_defns/cswift.h"
+#endif
+
+#define CSWIFT_LIB_NAME "cswift engine"
+#include "hw_cswift_err.c"
+
+static int cswift_destroy(ENGINE *e);
+static int cswift_init(ENGINE *e);
+static int cswift_finish(ENGINE *e);
+static int cswift_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
+
+/* BIGNUM stuff */
+static int cswift_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+               const BIGNUM *m, BN_CTX *ctx);
+static int cswift_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+               const BIGNUM *q, const BIGNUM *dmp1, const BIGNUM *dmq1,
+               const BIGNUM *iqmp, BN_CTX *ctx);
+
+#ifndef OPENSSL_NO_RSA
+/* RSA stuff */
+static int cswift_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
+#endif
+/* This function is aliased to mod_exp (with the mont stuff dropped). */
+static int cswift_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+               const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+
+#ifndef OPENSSL_NO_DSA
+/* DSA stuff */
+static DSA_SIG *cswift_dsa_sign(const unsigned char *dgst, int dlen, DSA *dsa);
+static int cswift_dsa_verify(const unsigned char *dgst, int dgst_len,
+                               DSA_SIG *sig, DSA *dsa);
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* DH stuff */
+/* This function is alised to mod_exp (with the DH and mont dropped). */
+static int cswift_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
+
+/* RAND stuff */
+static int cswift_rand_bytes(unsigned char *buf, int num);
+static int cswift_rand_status(void);
+
+/* The definitions for control commands specific to this engine */
+#define CSWIFT_CMD_SO_PATH             ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN cswift_cmd_defns[] = {
+       {CSWIFT_CMD_SO_PATH,
+               "SO_PATH",
+               "Specifies the path to the 'cswift' shared library",
+               ENGINE_CMD_FLAG_STRING},
+       {0, NULL, NULL, 0}
+       };
+
+#ifndef OPENSSL_NO_RSA
+/* Our internal RSA_METHOD that we provide pointers to */
+static RSA_METHOD cswift_rsa =
+       {
+       "CryptoSwift RSA method",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       cswift_rsa_mod_exp,
+       cswift_mod_exp_mont,
+       NULL,
+       NULL,
+       0,
+       NULL,
+       NULL,
+       NULL
+       };
+#endif
+
+#ifndef OPENSSL_NO_DSA
+/* Our internal DSA_METHOD that we provide pointers to */
+static DSA_METHOD cswift_dsa =
+       {
+       "CryptoSwift DSA method",
+       cswift_dsa_sign,
+       NULL, /* dsa_sign_setup */
+       cswift_dsa_verify,
+       NULL, /* dsa_mod_exp */
+       NULL, /* bn_mod_exp */
+       NULL, /* init */
+       NULL, /* finish */
+       0, /* flags */
+       NULL /* app_data */
+       };
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* Our internal DH_METHOD that we provide pointers to */
+static DH_METHOD cswift_dh =
+       {
+       "CryptoSwift DH method",
+       NULL,
+       NULL,
+       cswift_mod_exp_dh,
+       NULL,
+       NULL,
+       0,
+       NULL
+       };
+#endif
+
+static RAND_METHOD cswift_random =
+    {
+    /* "CryptoSwift RAND method", */
+    NULL,
+    cswift_rand_bytes,
+    NULL,
+    NULL,
+    cswift_rand_bytes,
+    cswift_rand_status,
+    };
+
+
+/* Constants used when creating the ENGINE */
+static const char *engine_cswift_id = "cswift";
+static const char *engine_cswift_name = "CryptoSwift hardware engine support";
+
+/* This internal function is used by ENGINE_cswift() 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_cswift_id) ||
+                       !ENGINE_set_name(e, engine_cswift_name) ||
+#ifndef OPENSSL_NO_RSA
+                       !ENGINE_set_RSA(e, &cswift_rsa) ||
+#endif
+#ifndef OPENSSL_NO_DSA
+                       !ENGINE_set_DSA(e, &cswift_dsa) ||
+#endif
+#ifndef OPENSSL_NO_DH
+                       !ENGINE_set_DH(e, &cswift_dh) ||
+#endif
+                       !ENGINE_set_RAND(e, &cswift_random) ||
+                       !ENGINE_set_destroy_function(e, cswift_destroy) ||
+                       !ENGINE_set_init_function(e, cswift_init) ||
+                       !ENGINE_set_finish_function(e, cswift_finish) ||
+                       !ENGINE_set_ctrl_function(e, cswift_ctrl) ||
+                       !ENGINE_set_cmd_defns(e, cswift_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();
+       cswift_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
+       cswift_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
+       cswift_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
+       cswift_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
+#endif
+
+#ifndef OPENSSL_NO_DH
+       /* Much the same for Diffie-Hellman */
+       meth2 = DH_OpenSSL();
+       cswift_dh.generate_key = meth2->generate_key;
+       cswift_dh.compute_key = meth2->compute_key;
+#endif
+
+       /* Ensure the cswift error handling is set up */
+       ERR_load_CSWIFT_strings();
+       return 1;
+       }
+
+static ENGINE *engine_cswift(void)
+       {
+       ENGINE *ret = ENGINE_new();
+       if(!ret)
+               return NULL;
+       if(!bind_helper(ret))
+               {
+               ENGINE_free(ret);
+               return NULL;
+               }
+       return ret;
+       }
+
+void ENGINE_load_cswift(void)
+       {
+       /* Copied from eng_[openssl|dyn].c */
+       ENGINE *toadd = engine_cswift();
+       if(!toadd) return;
+       ENGINE_add(toadd);
+       ENGINE_free(toadd);
+       ERR_clear_error();
+       }
+
+/* This is a process-global DSO handle used for loading and unloading
+ * the CryptoSwift 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 *cswift_dso = NULL;
+
+/* These are the function pointers that are (un)set when the library has
+ * successfully (un)loaded. */
+t_swAcquireAccContext *p_CSwift_AcquireAccContext = NULL;
+t_swAttachKeyParam *p_CSwift_AttachKeyParam = NULL;
+t_swSimpleRequest *p_CSwift_SimpleRequest = NULL;
+t_swReleaseAccContext *p_CSwift_ReleaseAccContext = NULL;
+
+/* Used in the DSO operations. */
+static const char *CSWIFT_LIBNAME = NULL;
+static const char *get_CSWIFT_LIBNAME(void)
+       {
+       if(CSWIFT_LIBNAME)
+               return CSWIFT_LIBNAME;
+       return "swift";
+       }
+static void free_CSWIFT_LIBNAME(void)
+       {
+       if(CSWIFT_LIBNAME)
+               OPENSSL_free((void*)CSWIFT_LIBNAME);
+       CSWIFT_LIBNAME = NULL;
+       }
+static long set_CSWIFT_LIBNAME(const char *name)
+       {
+       free_CSWIFT_LIBNAME();
+       return (((CSWIFT_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
+       }
+static const char *CSWIFT_F1 = "swAcquireAccContext";
+static const char *CSWIFT_F2 = "swAttachKeyParam";
+static const char *CSWIFT_F3 = "swSimpleRequest";
+static const char *CSWIFT_F4 = "swReleaseAccContext";
+
+
+/* CryptoSwift 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(SW_CONTEXT_HANDLE *hac)
+       {
+        SW_STATUS status;
+        status = p_CSwift_AcquireAccContext(hac);
+        if(status != SW_OK)
+                return 0;
+        return 1;
+       }
+/* similarly to release one. */
+static void release_context(SW_CONTEXT_HANDLE hac)
+       {
+        p_CSwift_ReleaseAccContext(hac);
+       }
+
+/* Destructor (complements the "ENGINE_cswift()" constructor) */
+static int cswift_destroy(ENGINE *e)
+       {
+       free_CSWIFT_LIBNAME();
+       ERR_unload_CSWIFT_strings();
+       return 1;
+       }
+
+/* (de)initialisation functions. */
+static int cswift_init(ENGINE *e)
+       {
+        SW_CONTEXT_HANDLE hac;
+        t_swAcquireAccContext *p1;
+        t_swAttachKeyParam *p2;
+        t_swSimpleRequest *p3;
+        t_swReleaseAccContext *p4;
+
+       if(cswift_dso != NULL)
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_INIT,CSWIFT_R_ALREADY_LOADED);
+               goto err;
+               }
+       /* Attempt to load libswift.so/swift.dll/whatever. */
+       cswift_dso = DSO_load(NULL, get_CSWIFT_LIBNAME(), NULL, 0);
+       if(cswift_dso == NULL)
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_INIT,CSWIFT_R_NOT_LOADED);
+               goto err;
+               }
+       if(!(p1 = (t_swAcquireAccContext *)
+                               DSO_bind_func(cswift_dso, CSWIFT_F1)) ||
+                       !(p2 = (t_swAttachKeyParam *)
+                               DSO_bind_func(cswift_dso, CSWIFT_F2)) ||
+                       !(p3 = (t_swSimpleRequest *)
+                               DSO_bind_func(cswift_dso, CSWIFT_F3)) ||
+                       !(p4 = (t_swReleaseAccContext *)
+                               DSO_bind_func(cswift_dso, CSWIFT_F4)))
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_INIT,CSWIFT_R_NOT_LOADED);
+               goto err;
+               }
+       /* Copy the pointers */
+       p_CSwift_AcquireAccContext = p1;
+       p_CSwift_AttachKeyParam = p2;
+       p_CSwift_SimpleRequest = p3;
+       p_CSwift_ReleaseAccContext = p4;
+       /* Try and get a context - if not, we may have a DSO but no
+        * accelerator! */
+       if(!get_context(&hac))
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_INIT,CSWIFT_R_UNIT_FAILURE);
+               goto err;
+               }
+       release_context(hac);
+       /* Everything's fine. */
+       return 1;
+err:
+       if(cswift_dso)
+               DSO_free(cswift_dso);
+       p_CSwift_AcquireAccContext = NULL;
+       p_CSwift_AttachKeyParam = NULL;
+       p_CSwift_SimpleRequest = NULL;
+       p_CSwift_ReleaseAccContext = NULL;
+       return 0;
+       }
+
+static int cswift_finish(ENGINE *e)
+       {
+       free_CSWIFT_LIBNAME();
+       if(cswift_dso == NULL)
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_FINISH,CSWIFT_R_NOT_LOADED);
+               return 0;
+               }
+       if(!DSO_free(cswift_dso))
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_FINISH,CSWIFT_R_UNIT_FAILURE);
+               return 0;
+               }
+       cswift_dso = NULL;
+       p_CSwift_AcquireAccContext = NULL;
+       p_CSwift_AttachKeyParam = NULL;
+       p_CSwift_SimpleRequest = NULL;
+       p_CSwift_ReleaseAccContext = NULL;
+       return 1;
+       }
+
+static int cswift_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+       {
+       int initialised = ((cswift_dso == NULL) ? 0 : 1);
+       switch(cmd)
+               {
+       case CSWIFT_CMD_SO_PATH:
+               if(p == NULL)
+                       {
+                       CSWIFTerr(CSWIFT_F_CSWIFT_CTRL,ERR_R_PASSED_NULL_PARAMETER);
+                       return 0;
+                       }
+               if(initialised)
+                       {
+                       CSWIFTerr(CSWIFT_F_CSWIFT_CTRL,CSWIFT_R_ALREADY_LOADED);
+                       return 0;
+                       }
+               return set_CSWIFT_LIBNAME((const char *)p);
+       default:
+               break;
+               }
+       CSWIFTerr(CSWIFT_F_CSWIFT_CTRL,CSWIFT_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+       return 0;
+       }
+
+/* Un petit mod_exp */
+static int cswift_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                       const BIGNUM *m, BN_CTX *ctx)
+       {
+       /* I need somewhere to store temporary serialised values for
+        * use with the CryptoSwift API calls. A neat cheat - I'll use
+        * BIGNUMs from the BN_CTX but access their arrays directly as
+        * byte arrays <grin>. This way I don't have to clean anything
+        * up. */
+       BIGNUM *modulus;
+       BIGNUM *exponent;
+       BIGNUM *argument;
+       BIGNUM *result;
+       SW_STATUS sw_status;
+       SW_LARGENUMBER arg, res;
+       SW_PARAM sw_param;
+       SW_CONTEXT_HANDLE hac;
+       int to_return, acquired;
+       modulus = exponent = argument = result = NULL;
+       to_return = 0; /* expect failure */
+       acquired = 0;
+       if(!get_context(&hac))
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_MOD_EXP,CSWIFT_R_UNIT_FAILURE);
+               goto err;
+               }
+       acquired = 1;
+       /* Prepare the params */
+       BN_CTX_start(ctx);
+       modulus = BN_CTX_get(ctx);
+       exponent = BN_CTX_get(ctx);
+       argument = BN_CTX_get(ctx);
+       result = BN_CTX_get(ctx);
+       if(!result)
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_MOD_EXP,CSWIFT_R_BN_CTX_FULL);
+               goto err;
+               }
+       if(!bn_wexpand(modulus, m->top) || !bn_wexpand(exponent, p->top) ||
+               !bn_wexpand(argument, a->top) || !bn_wexpand(result, m->top))
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_MOD_EXP,CSWIFT_R_BN_EXPAND_FAIL);
+               goto err;
+               }
+       sw_param.type = SW_ALG_EXP;
+       sw_param.up.exp.modulus.nbytes = BN_bn2bin(m,
+               (unsigned char *)modulus->d);
+       sw_param.up.exp.modulus.value = (unsigned char *)modulus->d;
+       sw_param.up.exp.exponent.nbytes = BN_bn2bin(p,
+               (unsigned char *)exponent->d);
+       sw_param.up.exp.exponent.value = (unsigned char *)exponent->d;
+       /* Attach the key params */
+       sw_status = p_CSwift_AttachKeyParam(hac, &sw_param);
+       switch(sw_status)
+               {
+       case SW_OK:
+               break;
+       case SW_ERR_INPUT_SIZE:
+               CSWIFTerr(CSWIFT_F_CSWIFT_MOD_EXP,CSWIFT_R_BAD_KEY_SIZE);
+               goto err;
+       default:
+               {
+               char tmpbuf[DECIMAL_SIZE(sw_status)+1];
+               CSWIFTerr(CSWIFT_F_CSWIFT_MOD_EXP,CSWIFT_R_REQUEST_FAILED);
+               sprintf(tmpbuf, "%ld", sw_status);
+               ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
+               }
+               goto err;
+               }
+       /* Prepare the argument and response */
+       arg.nbytes = BN_bn2bin(a, (unsigned char *)argument->d);
+       arg.value = (unsigned char *)argument->d;
+       res.nbytes = BN_num_bytes(m);
+       memset(result->d, 0, res.nbytes);
+       res.value = (unsigned char *)result->d;
+       /* Perform the operation */
+       if((sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_MODEXP, &arg, 1,
+               &res, 1)) != SW_OK)
+               {
+               char tmpbuf[DECIMAL_SIZE(sw_status)+1];
+               CSWIFTerr(CSWIFT_F_CSWIFT_MOD_EXP,CSWIFT_R_REQUEST_FAILED);
+               sprintf(tmpbuf, "%ld", sw_status);
+               ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
+               goto err;
+               }
+       /* Convert the response */
+       BN_bin2bn((unsigned char *)result->d, res.nbytes, r);
+       to_return = 1;
+err:
+       if(acquired)
+               release_context(hac);
+       BN_CTX_end(ctx);
+       return to_return;
+       }
+
+/* Un petit mod_exp chinois */
+static int cswift_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                       const BIGNUM *q, const BIGNUM *dmp1,
+                       const BIGNUM *dmq1, const BIGNUM *iqmp, BN_CTX *ctx)
+       {
+       SW_STATUS sw_status;
+       SW_LARGENUMBER arg, res;
+       SW_PARAM sw_param;
+       SW_CONTEXT_HANDLE hac;
+       BIGNUM *rsa_p = NULL;
+       BIGNUM *rsa_q = NULL;
+       BIGNUM *rsa_dmp1 = NULL;
+       BIGNUM *rsa_dmq1 = NULL;
+       BIGNUM *rsa_iqmp = NULL;
+       BIGNUM *argument = NULL;
+       BIGNUM *result = NULL;
+       int to_return = 0; /* expect failure */
+       int acquired = 0;
+       if(!get_context(&hac))
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_MOD_EXP_CRT,CSWIFT_R_UNIT_FAILURE);
+               goto err;
+               }
+       acquired = 1;
+       /* Prepare the params */
+       BN_CTX_start(ctx);
+       rsa_p = BN_CTX_get(ctx);
+       rsa_q = BN_CTX_get(ctx);
+       rsa_dmp1 = BN_CTX_get(ctx);
+       rsa_dmq1 = BN_CTX_get(ctx);
+       rsa_iqmp = BN_CTX_get(ctx);
+       argument = BN_CTX_get(ctx);
+       result = BN_CTX_get(ctx);
+       if(!result)
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_MOD_EXP_CRT,CSWIFT_R_BN_CTX_FULL);
+               goto err;
+               }
+       if(!bn_wexpand(rsa_p, p->top) || !bn_wexpand(rsa_q, q->top) ||
+                       !bn_wexpand(rsa_dmp1, dmp1->top) ||
+                       !bn_wexpand(rsa_dmq1, dmq1->top) ||
+                       !bn_wexpand(rsa_iqmp, iqmp->top) ||
+                       !bn_wexpand(argument, a->top) ||
+                       !bn_wexpand(result, p->top + q->top))
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_MOD_EXP_CRT,CSWIFT_R_BN_EXPAND_FAIL);
+               goto err;
+               }
+       sw_param.type = SW_ALG_CRT;
+       sw_param.up.crt.p.nbytes = BN_bn2bin(p, (unsigned char *)rsa_p->d);
+       sw_param.up.crt.p.value = (unsigned char *)rsa_p->d;
+       sw_param.up.crt.q.nbytes = BN_bn2bin(q, (unsigned char *)rsa_q->d);
+       sw_param.up.crt.q.value = (unsigned char *)rsa_q->d;
+       sw_param.up.crt.dmp1.nbytes = BN_bn2bin(dmp1,
+               (unsigned char *)rsa_dmp1->d);
+       sw_param.up.crt.dmp1.value = (unsigned char *)rsa_dmp1->d;
+       sw_param.up.crt.dmq1.nbytes = BN_bn2bin(dmq1,
+               (unsigned char *)rsa_dmq1->d);
+       sw_param.up.crt.dmq1.value = (unsigned char *)rsa_dmq1->d;
+       sw_param.up.crt.iqmp.nbytes = BN_bn2bin(iqmp,
+               (unsigned char *)rsa_iqmp->d);
+       sw_param.up.crt.iqmp.value = (unsigned char *)rsa_iqmp->d;
+       /* Attach the key params */
+       sw_status = p_CSwift_AttachKeyParam(hac, &sw_param);
+       switch(sw_status)
+               {
+       case SW_OK:
+               break;
+       case SW_ERR_INPUT_SIZE:
+               CSWIFTerr(CSWIFT_F_CSWIFT_MOD_EXP_CRT,CSWIFT_R_BAD_KEY_SIZE);
+               goto err;
+       default:
+               {
+               char tmpbuf[DECIMAL_SIZE(sw_status)+1];
+               CSWIFTerr(CSWIFT_F_CSWIFT_MOD_EXP_CRT,CSWIFT_R_REQUEST_FAILED);
+               sprintf(tmpbuf, "%ld", sw_status);
+               ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
+               }
+               goto err;
+               }
+       /* Prepare the argument and response */
+       arg.nbytes = BN_bn2bin(a, (unsigned char *)argument->d);
+       arg.value = (unsigned char *)argument->d;
+       res.nbytes = 2 * BN_num_bytes(p);
+       memset(result->d, 0, res.nbytes);
+       res.value = (unsigned char *)result->d;
+       /* Perform the operation */
+       if((sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_MODEXP_CRT, &arg, 1,
+               &res, 1)) != SW_OK)
+               {
+               char tmpbuf[DECIMAL_SIZE(sw_status)+1];
+               CSWIFTerr(CSWIFT_F_CSWIFT_MOD_EXP_CRT,CSWIFT_R_REQUEST_FAILED);
+               sprintf(tmpbuf, "%ld", sw_status);
+               ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
+               goto err;
+               }
+       /* Convert the response */
+       BN_bin2bn((unsigned char *)result->d, res.nbytes, r);
+       to_return = 1;
+err:
+       if(acquired)
+               release_context(hac);
+       BN_CTX_end(ctx);
+       return to_return;
+       }
+#ifndef OPENSSL_NO_RSA
+static int cswift_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
+       {
+       BN_CTX *ctx;
+       int to_return = 0;
+
+       if((ctx = BN_CTX_new()) == NULL)
+               goto err;
+       if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_RSA_MOD_EXP,CSWIFT_R_MISSING_KEY_COMPONENTS);
+               goto err;
+               }
+       to_return = cswift_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1,
+               rsa->dmq1, rsa->iqmp, ctx);
+err:
+       if(ctx)
+               BN_CTX_free(ctx);
+       return to_return;
+       }
+#endif
+
+/* This function is aliased to mod_exp (with the mont stuff dropped). */
+static int cswift_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+               const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+       {
+       return cswift_mod_exp(r, a, p, m, ctx);
+       }
+
+#ifndef OPENSSL_NO_DSA
+static DSA_SIG *cswift_dsa_sign(const unsigned char *dgst, int dlen, DSA *dsa)
+       {
+       SW_CONTEXT_HANDLE hac;
+       SW_PARAM sw_param;
+       SW_STATUS sw_status;
+       SW_LARGENUMBER arg, res;
+       unsigned char *ptr;
+       BN_CTX *ctx;
+       BIGNUM *dsa_p = NULL;
+       BIGNUM *dsa_q = NULL;
+       BIGNUM *dsa_g = NULL;
+       BIGNUM *dsa_key = NULL;
+       BIGNUM *result = NULL;
+       DSA_SIG *to_return = NULL;
+       int acquired = 0;
+
+       if((ctx = BN_CTX_new()) == NULL)
+               goto err;
+       if(!get_context(&hac))
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_DSA_SIGN,CSWIFT_R_UNIT_FAILURE);
+               goto err;
+               }
+       acquired = 1;
+       /* Prepare the params */
+       BN_CTX_start(ctx);
+       dsa_p = BN_CTX_get(ctx);
+       dsa_q = BN_CTX_get(ctx);
+       dsa_g = BN_CTX_get(ctx);
+       dsa_key = BN_CTX_get(ctx);
+       result = BN_CTX_get(ctx);
+       if(!result)
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_DSA_SIGN,CSWIFT_R_BN_CTX_FULL);
+               goto err;
+               }
+       if(!bn_wexpand(dsa_p, dsa->p->top) ||
+                       !bn_wexpand(dsa_q, dsa->q->top) ||
+                       !bn_wexpand(dsa_g, dsa->g->top) ||
+                       !bn_wexpand(dsa_key, dsa->priv_key->top) ||
+                       !bn_wexpand(result, dsa->p->top))
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_DSA_SIGN,CSWIFT_R_BN_EXPAND_FAIL);
+               goto err;
+               }
+       sw_param.type = SW_ALG_DSA;
+       sw_param.up.dsa.p.nbytes = BN_bn2bin(dsa->p,
+                               (unsigned char *)dsa_p->d);
+       sw_param.up.dsa.p.value = (unsigned char *)dsa_p->d;
+       sw_param.up.dsa.q.nbytes = BN_bn2bin(dsa->q,
+                               (unsigned char *)dsa_q->d);
+       sw_param.up.dsa.q.value = (unsigned char *)dsa_q->d;
+       sw_param.up.dsa.g.nbytes = BN_bn2bin(dsa->g,
+                               (unsigned char *)dsa_g->d);
+       sw_param.up.dsa.g.value = (unsigned char *)dsa_g->d;
+       sw_param.up.dsa.key.nbytes = BN_bn2bin(dsa->priv_key,
+                               (unsigned char *)dsa_key->d);
+       sw_param.up.dsa.key.value = (unsigned char *)dsa_key->d;
+       /* Attach the key params */
+       sw_status = p_CSwift_AttachKeyParam(hac, &sw_param);
+       switch(sw_status)
+               {
+       case SW_OK:
+               break;
+       case SW_ERR_INPUT_SIZE:
+               CSWIFTerr(CSWIFT_F_CSWIFT_DSA_SIGN,CSWIFT_R_BAD_KEY_SIZE);
+               goto err;
+       default:
+               {
+               char tmpbuf[DECIMAL_SIZE(sw_status)+1];
+               CSWIFTerr(CSWIFT_F_CSWIFT_DSA_SIGN,CSWIFT_R_REQUEST_FAILED);
+               sprintf(tmpbuf, "%ld", sw_status);
+               ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
+               }
+               goto err;
+               }
+       /* Prepare the argument and response */
+       arg.nbytes = dlen;
+       arg.value = (unsigned char *)dgst;
+       res.nbytes = BN_num_bytes(dsa->p);
+       memset(result->d, 0, res.nbytes);
+       res.value = (unsigned char *)result->d;
+       /* Perform the operation */
+       sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_DSS_SIGN, &arg, 1,
+               &res, 1);
+       if(sw_status != SW_OK)
+               {
+               char tmpbuf[DECIMAL_SIZE(sw_status)+1];
+               CSWIFTerr(CSWIFT_F_CSWIFT_DSA_SIGN,CSWIFT_R_REQUEST_FAILED);
+               sprintf(tmpbuf, "%ld", sw_status);
+               ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
+               goto err;
+               }
+       /* Convert the response */
+       ptr = (unsigned char *)result->d;
+       if((to_return = DSA_SIG_new()) == NULL)
+               goto err;
+       to_return->r = BN_bin2bn((unsigned char *)result->d, 20, NULL);
+       to_return->s = BN_bin2bn((unsigned char *)result->d + 20, 20, NULL);
+
+err:
+       if(acquired)
+               release_context(hac);
+       if(ctx)
+               {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+               }
+       return to_return;
+       }
+
+static int cswift_dsa_verify(const unsigned char *dgst, int dgst_len,
+                               DSA_SIG *sig, DSA *dsa)
+       {
+       SW_CONTEXT_HANDLE hac;
+       SW_PARAM sw_param;
+       SW_STATUS sw_status;
+       SW_LARGENUMBER arg[2], res;
+       unsigned long sig_result;
+       BN_CTX *ctx;
+       BIGNUM *dsa_p = NULL;
+       BIGNUM *dsa_q = NULL;
+       BIGNUM *dsa_g = NULL;
+       BIGNUM *dsa_key = NULL;
+       BIGNUM *argument = NULL;
+       int to_return = -1;
+       int acquired = 0;
+
+       if((ctx = BN_CTX_new()) == NULL)
+               goto err;
+       if(!get_context(&hac))
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_DSA_VERIFY,CSWIFT_R_UNIT_FAILURE);
+               goto err;
+               }
+       acquired = 1;
+       /* Prepare the params */
+       BN_CTX_start(ctx);
+       dsa_p = BN_CTX_get(ctx);
+       dsa_q = BN_CTX_get(ctx);
+       dsa_g = BN_CTX_get(ctx);
+       dsa_key = BN_CTX_get(ctx);
+       argument = BN_CTX_get(ctx);
+       if(!argument)
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_DSA_VERIFY,CSWIFT_R_BN_CTX_FULL);
+               goto err;
+               }
+       if(!bn_wexpand(dsa_p, dsa->p->top) ||
+                       !bn_wexpand(dsa_q, dsa->q->top) ||
+                       !bn_wexpand(dsa_g, dsa->g->top) ||
+                       !bn_wexpand(dsa_key, dsa->pub_key->top) ||
+                       !bn_wexpand(argument, 40))
+               {
+               CSWIFTerr(CSWIFT_F_CSWIFT_DSA_VERIFY,CSWIFT_R_BN_EXPAND_FAIL);
+               goto err;
+               }
+       sw_param.type = SW_ALG_DSA;
+       sw_param.up.dsa.p.nbytes = BN_bn2bin(dsa->p,
+                               (unsigned char *)dsa_p->d);
+       sw_param.up.dsa.p.value = (unsigned char *)dsa_p->d;
+       sw_param.up.dsa.q.nbytes = BN_bn2bin(dsa->q,
+                               (unsigned char *)dsa_q->d);
+       sw_param.up.dsa.q.value = (unsigned char *)dsa_q->d;
+       sw_param.up.dsa.g.nbytes = BN_bn2bin(dsa->g,
+                               (unsigned char *)dsa_g->d);
+       sw_param.up.dsa.g.value = (unsigned char *)dsa_g->d;
+       sw_param.up.dsa.key.nbytes = BN_bn2bin(dsa->pub_key,
+                               (unsigned char *)dsa_key->d);
+       sw_param.up.dsa.key.value = (unsigned char *)dsa_key->d;
+       /* Attach the key params */
+       sw_status = p_CSwift_AttachKeyParam(hac, &sw_param);
+       switch(sw_status)
+               {
+       case SW_OK:
+               break;
+       case SW_ERR_INPUT_SIZE:
+               CSWIFTerr(CSWIFT_F_CSWIFT_DSA_VERIFY,CSWIFT_R_BAD_KEY_SIZE);
+               goto err;
+       default:
+               {
+               char tmpbuf[DECIMAL_SIZE(sw_status)+1];
+               CSWIFTerr(CSWIFT_F_CSWIFT_DSA_VERIFY,CSWIFT_R_REQUEST_FAILED);
+               sprintf(tmpbuf, "%ld", sw_status);
+               ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
+               }
+               goto err;
+               }
+       /* Prepare the argument and response */
+       arg[0].nbytes = dgst_len;
+       arg[0].value = (unsigned char *)dgst;
+       arg[1].nbytes = 40;
+       arg[1].value = (unsigned char *)argument->d;
+       memset(arg[1].value, 0, 40);
+       BN_bn2bin(sig->r, arg[1].value + 20 - BN_num_bytes(sig->r));
+       BN_bn2bin(sig->s, arg[1].value + 40 - BN_num_bytes(sig->s));
+       res.nbytes = 4; /* unsigned long */
+       res.value = (unsigned char *)(&sig_result);
+       /* Perform the operation */
+       sw_status = p_CSwift_SimpleRequest(hac, SW_CMD_DSS_VERIFY, arg, 2,
+               &res, 1);
+       if(sw_status != SW_OK)
+               {
+               char tmpbuf[DECIMAL_SIZE(sw_status)+1];
+               CSWIFTerr(CSWIFT_F_CSWIFT_DSA_VERIFY,CSWIFT_R_REQUEST_FAILED);
+               sprintf(tmpbuf, "%ld", sw_status);
+               ERR_add_error_data(2, "CryptoSwift error number is ",tmpbuf);
+               goto err;
+               }
+       /* Convert the response */
+       to_return = ((sig_result == 0) ? 0 : 1);
+
+err:
+       if(acquired)
+               release_context(hac);
+       if(ctx)
+               {
+               BN_CTX_end(ctx);
+               BN_CTX_free(ctx);
+               }
+       return to_return;
+       }
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* This function is aliased to mod_exp (with the dh and mont dropped). */
+static int cswift_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 cswift_mod_exp(r, a, p, m, ctx);
+       }
+#endif
+
+/* Random bytes are good */
+static int cswift_rand_bytes(unsigned char *buf, int num)
+{
+       SW_CONTEXT_HANDLE hac;
+       SW_STATUS swrc;
+       SW_LARGENUMBER largenum;
+       size_t nbytes = 0;
+       int acquired = 0;
+       int to_return = 0; /* assume failure */
+
+       if (!get_context(&hac))
+       {
+               CSWIFTerr(CSWIFT_F_CSWIFT_CTRL, CSWIFT_R_UNIT_FAILURE);
+               goto err;
+       }
+       acquired = 1;
+
+       while (nbytes < (size_t)num)
+       {
+               /* tell CryptoSwift how many bytes we want and where we want it.
+                * Note: - CryptoSwift cannot do more than 4096 bytes at a time.
+                *       - CryptoSwift can only do multiple of 32-bits. */
+               largenum.value = (SW_BYTE *) buf + nbytes;
+               if (4096 > num - nbytes)
+                       largenum.nbytes = num - nbytes;
+               else
+                       largenum.nbytes = 4096;
+
+               swrc = p_CSwift_SimpleRequest(hac, SW_CMD_RAND, NULL, 0, &largenum, 1);
+               if (swrc != SW_OK)
+               {
+                       char tmpbuf[20];
+                       CSWIFTerr(CSWIFT_F_CSWIFT_CTRL, CSWIFT_R_REQUEST_FAILED);
+                       sprintf(tmpbuf, "%ld", swrc);
+                       ERR_add_error_data(2, "CryptoSwift error number is ", tmpbuf);
+                       goto err;
+               }
+
+               nbytes += largenum.nbytes;
+       }
+       to_return = 1;  /* success */
+
+err:
+       if (acquired)
+               release_context(hac);
+       return to_return;
+}
+
+static int cswift_rand_status(void)
+{
+       return 1;
+}
+
+
+/* This stuff is needed if this ENGINE is being compiled into a self-contained
+ * shared-library. */
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_fn(ENGINE *e, const char *id)
+       {
+       if(id && (strcmp(id, engine_cswift_id) != 0))
+               return 0;
+       if(!bind_helper(e))
+               return 0;
+       return 1;
+       }       
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
+#endif /* ENGINE_DYNAMIC_SUPPORT */
+
+#endif /* !OPENSSL_NO_HW_CSWIFT */
+#endif /* !OPENSSL_NO_HW */
diff --git a/engines/e_cswift_err.c b/engines/e_cswift_err.c
new file mode 100644 (file)
index 0000000..684f53b
--- /dev/null
@@ -0,0 +1,149 @@
+/* hw_cswift_err.c */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "hw_cswift_err.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA CSWIFT_str_functs[]=
+       {
+{ERR_PACK(0,CSWIFT_F_CSWIFT_CTRL,0),   "CSWIFT_CTRL"},
+{ERR_PACK(0,CSWIFT_F_CSWIFT_DSA_SIGN,0),       "CSWIFT_DSA_SIGN"},
+{ERR_PACK(0,CSWIFT_F_CSWIFT_DSA_VERIFY,0),     "CSWIFT_DSA_VERIFY"},
+{ERR_PACK(0,CSWIFT_F_CSWIFT_FINISH,0), "CSWIFT_FINISH"},
+{ERR_PACK(0,CSWIFT_F_CSWIFT_INIT,0),   "CSWIFT_INIT"},
+{ERR_PACK(0,CSWIFT_F_CSWIFT_MOD_EXP,0),        "CSWIFT_MOD_EXP"},
+{ERR_PACK(0,CSWIFT_F_CSWIFT_MOD_EXP_CRT,0),    "CSWIFT_MOD_EXP_CRT"},
+{ERR_PACK(0,CSWIFT_F_CSWIFT_RSA_MOD_EXP,0),    "CSWIFT_RSA_MOD_EXP"},
+{0,NULL}
+       };
+
+static ERR_STRING_DATA CSWIFT_str_reasons[]=
+       {
+{CSWIFT_R_ALREADY_LOADED                 ,"already loaded"},
+{CSWIFT_R_BAD_KEY_SIZE                   ,"bad key size"},
+{CSWIFT_R_BN_CTX_FULL                    ,"bn ctx full"},
+{CSWIFT_R_BN_EXPAND_FAIL                 ,"bn expand fail"},
+{CSWIFT_R_CTRL_COMMAND_NOT_IMPLEMENTED   ,"ctrl command not implemented"},
+{CSWIFT_R_MISSING_KEY_COMPONENTS         ,"missing key components"},
+{CSWIFT_R_NOT_LOADED                     ,"not loaded"},
+{CSWIFT_R_REQUEST_FAILED                 ,"request failed"},
+{CSWIFT_R_UNIT_FAILURE                   ,"unit failure"},
+{0,NULL}
+       };
+
+#endif
+
+#ifdef CSWIFT_LIB_NAME
+static ERR_STRING_DATA CSWIFT_lib_name[]=
+        {
+{0     ,CSWIFT_LIB_NAME},
+{0,NULL}
+       };
+#endif
+
+
+static int CSWIFT_lib_error_code=0;
+static int CSWIFT_error_init=1;
+
+static void ERR_load_CSWIFT_strings(void)
+       {
+       if (CSWIFT_lib_error_code == 0)
+               CSWIFT_lib_error_code=ERR_get_next_error_library();
+
+       if (CSWIFT_error_init)
+               {
+               CSWIFT_error_init=0;
+#ifndef OPENSSL_NO_ERR
+               ERR_load_strings(CSWIFT_lib_error_code,CSWIFT_str_functs);
+               ERR_load_strings(CSWIFT_lib_error_code,CSWIFT_str_reasons);
+#endif
+
+#ifdef CSWIFT_LIB_NAME
+               CSWIFT_lib_name->error = ERR_PACK(CSWIFT_lib_error_code,0,0);
+               ERR_load_strings(0,CSWIFT_lib_name);
+#endif
+               }
+       }
+
+static void ERR_unload_CSWIFT_strings(void)
+       {
+       if (CSWIFT_error_init == 0)
+               {
+#ifndef OPENSSL_NO_ERR
+               ERR_unload_strings(CSWIFT_lib_error_code,CSWIFT_str_functs);
+               ERR_unload_strings(CSWIFT_lib_error_code,CSWIFT_str_reasons);
+#endif
+
+#ifdef CSWIFT_LIB_NAME
+               ERR_unload_strings(0,CSWIFT_lib_name);
+#endif
+               CSWIFT_error_init=1;
+               }
+       }
+
+static void ERR_CSWIFT_error(int function, int reason, char *file, int line)
+       {
+       if (CSWIFT_lib_error_code == 0)
+               CSWIFT_lib_error_code=ERR_get_next_error_library();
+       ERR_PUT_error(CSWIFT_lib_error_code,function,reason,file,line);
+       }
diff --git a/engines/e_cswift_err.h b/engines/e_cswift_err.h
new file mode 100644 (file)
index 0000000..7120c32
--- /dev/null
@@ -0,0 +1,93 @@
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_CSWIFT_ERR_H
+#define HEADER_CSWIFT_ERR_H
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+static void ERR_load_CSWIFT_strings(void);
+static void ERR_unload_CSWIFT_strings(void);
+static void ERR_CSWIFT_error(int function, int reason, char *file, int line);
+#define CSWIFTerr(f,r) ERR_CSWIFT_error((f),(r),__FILE__,__LINE__)
+
+/* Error codes for the CSWIFT functions. */
+
+/* Function codes. */
+#define CSWIFT_F_CSWIFT_CTRL                            100
+#define CSWIFT_F_CSWIFT_DSA_SIGN                        101
+#define CSWIFT_F_CSWIFT_DSA_VERIFY                      102
+#define CSWIFT_F_CSWIFT_FINISH                          103
+#define CSWIFT_F_CSWIFT_INIT                            104
+#define CSWIFT_F_CSWIFT_MOD_EXP                                 105
+#define CSWIFT_F_CSWIFT_MOD_EXP_CRT                     106
+#define CSWIFT_F_CSWIFT_RSA_MOD_EXP                     107
+
+/* Reason codes. */
+#define CSWIFT_R_ALREADY_LOADED                                 100
+#define CSWIFT_R_BAD_KEY_SIZE                           101
+#define CSWIFT_R_BN_CTX_FULL                            102
+#define CSWIFT_R_BN_EXPAND_FAIL                                 103
+#define CSWIFT_R_CTRL_COMMAND_NOT_IMPLEMENTED           104
+#define CSWIFT_R_MISSING_KEY_COMPONENTS                         105
+#define CSWIFT_R_NOT_LOADED                             106
+#define CSWIFT_R_REQUEST_FAILED                                 107
+#define CSWIFT_R_UNIT_FAILURE                           108
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/engines/e_ncipher.c b/engines/e_ncipher.c
new file mode 100644 (file)
index 0000000..a43d436
--- /dev/null
@@ -0,0 +1,1342 @@
+/* crypto/engine/hw_ncipher.c -*- mode: C; c-file-style: "eay" -*- */
+/* Written by Richard Levitte (richard@levitte.org), Geoff Thorpe
+ * (geoff@geoffthorpe.net) and Dr Stephen N Henson (shenson@bigfoot.com)
+ * for the OpenSSL project 2000.
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "cryptlib.h"
+#include <openssl/crypto.h>
+#include <openssl/pem.h>
+#include <openssl/dso.h>
+#include <openssl/engine.h>
+#include <openssl/ui.h>
+
+#ifndef OPENSSL_NO_HW
+#ifndef OPENSSL_NO_HW_NCIPHER
+
+/* 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
+
+#define HWCRHK_LIB_NAME "hwcrhk engine"
+#include "hw_ncipher_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)()); 
+
+/* 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*);
+
+/* BIGNUM stuff */
+static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+               const BIGNUM *m, BN_CTX *ctx);
+
+#ifndef OPENSSL_NO_RSA
+/* RSA stuff */
+static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa);
+#endif
+/* 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);
+
+#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
+
+/* RAND stuff */
+static int hwcrhk_rand_bytes(unsigned char *buf, int num);
+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);
+static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
+       UI_METHOD *ui_method, void *callback_data);
+static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
+       int ind,long argl, void *argp);
+
+/* Interaction stuff */
+static int hwcrhk_insert_card(const char *prompt_info,
+       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);
+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)
+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 or off (boolean)",
+               ENGINE_CMD_FLAG_NUMERIC},
+       {HWCRHK_CMD_THREAD_LOCKING,
+               "THREAD_LOCKING",
+               "Turns thread-safe locking on or off (boolean)",
+               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
+/* Our internal RSA_METHOD that we provide pointers to */
+static RSA_METHOD hwcrhk_rsa =
+       {
+       "nCipher RSA method",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       hwcrhk_rsa_mod_exp,
+       hwcrhk_mod_exp_mont,
+       NULL,
+       NULL,
+       0,
+       NULL,
+       NULL,
+       NULL
+       };
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* Our internal DH_METHOD that we provide pointers to */
+static DH_METHOD hwcrhk_dh =
+       {
+       "nCipher DH method",
+       NULL,
+       NULL,
+       hwcrhk_mod_exp_dh,
+       NULL,
+       NULL,
+       0,
+       NULL
+       };
+#endif
+
+static RAND_METHOD hwcrhk_rand =
+       {
+       /* "nCipher 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 = "nCipher hardware engine support";
+
+/* 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) \
+    {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
+#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. */
+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 */
+};
+
+
+/* Now, to our own code */
+
+/* This internal function is used by ENGINE_ncipher() 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;
+       }
+
+static ENGINE *engine_ncipher(void)
+       {
+       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_ncipher();
+       if(!toadd) return;
+       ENGINE_add(toadd);
+       ENGINE_free(toadd);
+       ERR_clear_error();
+       }
+
+/* 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. */
+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
+static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
+#endif
+static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
+#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
+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;
+       }
+static const char *get_HWCRHK_LIBNAME(void)
+       {
+       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);
+       }
+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
+static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
+#endif
+static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
+#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
+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. */
+
+/* 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;
+       }
+/* similarly to release one. */
+static void release_context(HWCryptoHook_ContextHandle hac)
+       {
+       p_hwcrhk_Finish(hac);
+       }
+
+/* Destructor (complements the "ENGINE_ncipher()" constructor) */
+static int hwcrhk_destroy(ENGINE *e)
+       {
+       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 &&
+               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;
+       }
+
+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;
+               }
+ 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)())
+       {
+       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;
+#endif
+       HWCryptoHook_PassphraseContext ppctx;
+
+#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_PUBKEY,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_PUBKEY,
+                       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 (!res)
+                HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
+                        HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
+
+       return res;
+ err:
+       if (res)
+               EVP_PKEY_free(res);
+#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;
+ err:
+       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)
+       {
+       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_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, NULL);
+
+               /* 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
+
+/* 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);
+       }
+
+#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
+
+/* 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;
+ err:
+       return to_return;
+       }
+
+static int hwcrhk_rand_status(void)
+       {
+       return 1;
+       }
+
+/* This cleans up an RSA KM key, called when ex_data is freed */
+
+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
+}
+
+/* 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 void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
+       {
+       CRYPTO_w_unlock(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;
+
+        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);
+                }
+       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];
+
+               if (wrong_info)
+                       BIO_snprintf(buf, sizeof(buf)-1,
+                               "Current card: \"%s\"\n", wrong_info);
+               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_write(lstream, message, strlen(message));
+               }
+       CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
+       }
+
+/* This stuff is needed if this ENGINE is being compiled into a self-contained
+ * shared-library. */     
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_fn(ENGINE *e, const char *id)
+       {
+       if(id && (strcmp(id, engine_hwcrhk_id) != 0))
+               return 0;
+       if(!bind_helper(e))
+               return 0;
+       return 1;
+       }       
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
+#endif /* ENGINE_DYNAMIC_SUPPORT */
+
+#endif /* !OPENSSL_NO_HW_NCIPHER */
+#endif /* !OPENSSL_NO_HW */
diff --git a/engines/e_ncipher_err.c b/engines/e_ncipher_err.c
new file mode 100644 (file)
index 0000000..24024cf
--- /dev/null
@@ -0,0 +1,156 @@
+/* hw_ncipher_err.c */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "hw_ncipher_err.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA HWCRHK_str_functs[]=
+       {
+{ERR_PACK(0,HWCRHK_F_HWCRHK_CTRL,0),   "HWCRHK_CTRL"},
+{ERR_PACK(0,HWCRHK_F_HWCRHK_FINISH,0), "HWCRHK_FINISH"},
+{ERR_PACK(0,HWCRHK_F_HWCRHK_GET_PASS,0),       "HWCRHK_GET_PASS"},
+{ERR_PACK(0,HWCRHK_F_HWCRHK_INIT,0),   "HWCRHK_INIT"},
+{ERR_PACK(0,HWCRHK_F_HWCRHK_INSERT_CARD,0),    "HWCRHK_INSERT_CARD"},
+{ERR_PACK(0,HWCRHK_F_HWCRHK_LOAD_PRIVKEY,0),   "HWCRHK_LOAD_PRIVKEY"},
+{ERR_PACK(0,HWCRHK_F_HWCRHK_LOAD_PUBKEY,0),    "HWCRHK_LOAD_PUBKEY"},
+{ERR_PACK(0,HWCRHK_F_HWCRHK_MOD_EXP,0),        "HWCRHK_MOD_EXP"},
+{ERR_PACK(0,HWCRHK_F_HWCRHK_RAND_BYTES,0),     "HWCRHK_RAND_BYTES"},
+{ERR_PACK(0,HWCRHK_F_HWCRHK_RSA_MOD_EXP,0),    "HWCRHK_RSA_MOD_EXP"},
+{0,NULL}
+       };
+
+static ERR_STRING_DATA HWCRHK_str_reasons[]=
+       {
+{HWCRHK_R_ALREADY_LOADED                 ,"already loaded"},
+{HWCRHK_R_BIO_WAS_FREED                  ,"bio was freed"},
+{HWCRHK_R_CHIL_ERROR                     ,"chil error"},
+{HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED   ,"ctrl command not implemented"},
+{HWCRHK_R_DSO_FAILURE                    ,"dso failure"},
+{HWCRHK_R_MISSING_KEY_COMPONENTS         ,"missing key components"},
+{HWCRHK_R_NOT_INITIALISED                ,"not initialised"},
+{HWCRHK_R_NOT_LOADED                     ,"not loaded"},
+{HWCRHK_R_NO_CALLBACK                    ,"no callback"},
+{HWCRHK_R_NO_KEY                         ,"no key"},
+{HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED,"private key algorithms disabled"},
+{HWCRHK_R_REQUEST_FAILED                 ,"request failed"},
+{HWCRHK_R_REQUEST_FALLBACK               ,"request fallback"},
+{HWCRHK_R_UNIT_FAILURE                   ,"unit failure"},
+{0,NULL}
+       };
+
+#endif
+
+#ifdef HWCRHK_LIB_NAME
+static ERR_STRING_DATA HWCRHK_lib_name[]=
+        {
+{0     ,HWCRHK_LIB_NAME},
+{0,NULL}
+       };
+#endif
+
+
+static int HWCRHK_lib_error_code=0;
+static int HWCRHK_error_init=1;
+
+static void ERR_load_HWCRHK_strings(void)
+       {
+       if (HWCRHK_lib_error_code == 0)
+               HWCRHK_lib_error_code=ERR_get_next_error_library();
+
+       if (HWCRHK_error_init)
+               {
+               HWCRHK_error_init=0;
+#ifndef OPENSSL_NO_ERR
+               ERR_load_strings(HWCRHK_lib_error_code,HWCRHK_str_functs);
+               ERR_load_strings(HWCRHK_lib_error_code,HWCRHK_str_reasons);
+#endif
+
+#ifdef HWCRHK_LIB_NAME
+               HWCRHK_lib_name->error = ERR_PACK(HWCRHK_lib_error_code,0,0);
+               ERR_load_strings(0,HWCRHK_lib_name);
+#endif
+               }
+       }
+
+static void ERR_unload_HWCRHK_strings(void)
+       {
+       if (HWCRHK_error_init == 0)
+               {
+#ifndef OPENSSL_NO_ERR
+               ERR_unload_strings(HWCRHK_lib_error_code,HWCRHK_str_functs);
+               ERR_unload_strings(HWCRHK_lib_error_code,HWCRHK_str_reasons);
+#endif
+
+#ifdef HWCRHK_LIB_NAME
+               ERR_unload_strings(0,HWCRHK_lib_name);
+#endif
+               HWCRHK_error_init=1;
+               }
+       }
+
+static void ERR_HWCRHK_error(int function, int reason, char *file, int line)
+       {
+       if (HWCRHK_lib_error_code == 0)
+               HWCRHK_lib_error_code=ERR_get_next_error_library();
+       ERR_PUT_error(HWCRHK_lib_error_code,function,reason,file,line);
+       }
diff --git a/engines/e_ncipher_err.h b/engines/e_ncipher_err.h
new file mode 100644 (file)
index 0000000..4d65b1d
--- /dev/null
@@ -0,0 +1,100 @@
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_HWCRHK_ERR_H
+#define HEADER_HWCRHK_ERR_H
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+static void ERR_load_HWCRHK_strings(void);
+static void ERR_unload_HWCRHK_strings(void);
+static void ERR_HWCRHK_error(int function, int reason, char *file, int line);
+#define HWCRHKerr(f,r) ERR_HWCRHK_error((f),(r),__FILE__,__LINE__)
+
+/* Error codes for the HWCRHK functions. */
+
+/* Function codes. */
+#define HWCRHK_F_HWCRHK_CTRL                            100
+#define HWCRHK_F_HWCRHK_FINISH                          101
+#define HWCRHK_F_HWCRHK_GET_PASS                        102
+#define HWCRHK_F_HWCRHK_INIT                            103
+#define HWCRHK_F_HWCRHK_INSERT_CARD                     104
+#define HWCRHK_F_HWCRHK_LOAD_PRIVKEY                    105
+#define HWCRHK_F_HWCRHK_LOAD_PUBKEY                     106
+#define HWCRHK_F_HWCRHK_MOD_EXP                                 107
+#define HWCRHK_F_HWCRHK_RAND_BYTES                      108
+#define HWCRHK_F_HWCRHK_RSA_MOD_EXP                     109
+
+/* Reason codes. */
+#define HWCRHK_R_ALREADY_LOADED                                 100
+#define HWCRHK_R_BIO_WAS_FREED                          101
+#define HWCRHK_R_CHIL_ERROR                             102
+#define HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED           103
+#define HWCRHK_R_DSO_FAILURE                            104
+#define HWCRHK_R_MISSING_KEY_COMPONENTS                         105
+#define HWCRHK_R_NOT_INITIALISED                        106
+#define HWCRHK_R_NOT_LOADED                             107
+#define HWCRHK_R_NO_CALLBACK                            108
+#define HWCRHK_R_NO_KEY                                         109
+#define HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED        110
+#define HWCRHK_R_REQUEST_FAILED                                 111
+#define HWCRHK_R_REQUEST_FALLBACK                       112
+#define HWCRHK_R_UNIT_FAILURE                           113
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/engines/e_nuron.c b/engines/e_nuron.c
new file mode 100644 (file)
index 0000000..130b6d8
--- /dev/null
@@ -0,0 +1,416 @@
+/* crypto/engine/hw_nuron.c */
+/* Written by Ben Laurie for the OpenSSL Project, leaning heavily on Geoff
+ * Thorpe's Atalla implementation.
+ */
+/* ====================================================================
+ * Copyright (c) 2000-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include "cryptlib.h"
+#include <openssl/dso.h>
+#include <openssl/engine.h>
+
+
+#ifndef OPENSSL_NO_HW
+#ifndef OPENSSL_NO_HW_NURON
+
+#define NURON_LIB_NAME "nuron engine"
+#include "hw_nuron_err.c"
+
+static const char *NURON_LIBNAME = NULL;
+static const char *get_NURON_LIBNAME(void)
+       {
+       if(NURON_LIBNAME)
+               return NURON_LIBNAME;
+       return "nuronssl";
+       }
+static void free_NURON_LIBNAME(void)
+       {
+       if(NURON_LIBNAME)
+               OPENSSL_free((void*)NURON_LIBNAME);
+       NURON_LIBNAME = NULL;
+       }
+static long set_NURON_LIBNAME(const char *name)
+       {
+       free_NURON_LIBNAME();
+       return (((NURON_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
+       }
+static const char *NURON_F1 = "nuron_mod_exp";
+
+/* The definitions for control commands specific to this engine */
+#define NURON_CMD_SO_PATH              ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN nuron_cmd_defns[] = {
+       {NURON_CMD_SO_PATH,
+               "SO_PATH",
+               "Specifies the path to the 'nuronssl' shared library",
+               ENGINE_CMD_FLAG_STRING},
+       {0, NULL, NULL, 0}
+       };
+
+typedef int tfnModExp(BIGNUM *r,const BIGNUM *a,const BIGNUM *p,const BIGNUM *m);
+static tfnModExp *pfnModExp = NULL;
+
+static DSO *pvDSOHandle = NULL;
+
+static int nuron_destroy(ENGINE *e)
+       {
+       free_NURON_LIBNAME();
+       ERR_unload_NURON_strings();
+       return 1;
+       }
+
+static int nuron_init(ENGINE *e)
+       {
+       if(pvDSOHandle != NULL)
+               {
+               NURONerr(NURON_F_NURON_INIT,NURON_R_ALREADY_LOADED);
+               return 0;
+               }
+
+       pvDSOHandle = DSO_load(NULL, get_NURON_LIBNAME(), NULL,
+               DSO_FLAG_NAME_TRANSLATION_EXT_ONLY);
+       if(!pvDSOHandle)
+               {
+               NURONerr(NURON_F_NURON_INIT,NURON_R_DSO_NOT_FOUND);
+               return 0;
+               }
+
+       pfnModExp = (tfnModExp *)DSO_bind_func(pvDSOHandle, NURON_F1);
+       if(!pfnModExp)
+               {
+               NURONerr(NURON_F_NURON_INIT,NURON_R_DSO_FUNCTION_NOT_FOUND);
+               return 0;
+               }
+
+       return 1;
+       }
+
+static int nuron_finish(ENGINE *e)
+       {
+       free_NURON_LIBNAME();
+       if(pvDSOHandle == NULL)
+               {
+               NURONerr(NURON_F_NURON_FINISH,NURON_R_NOT_LOADED);
+               return 0;
+               }
+       if(!DSO_free(pvDSOHandle))
+               {
+               NURONerr(NURON_F_NURON_FINISH,NURON_R_DSO_FAILURE);
+               return 0;
+               }
+       pvDSOHandle=NULL;
+       pfnModExp=NULL;
+       return 1;
+       }
+
+static int nuron_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+       {
+       int initialised = ((pvDSOHandle == NULL) ? 0 : 1);
+       switch(cmd)
+               {
+       case NURON_CMD_SO_PATH:
+               if(p == NULL)
+                       {
+                       NURONerr(NURON_F_NURON_CTRL,ERR_R_PASSED_NULL_PARAMETER);
+                       return 0;
+                       }
+               if(initialised)
+                       {
+                       NURONerr(NURON_F_NURON_CTRL,NURON_R_ALREADY_LOADED);
+                       return 0;
+                       }
+               return set_NURON_LIBNAME((const char *)p);
+       default:
+               break;
+               }
+       NURONerr(NURON_F_NURON_CTRL,NURON_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+       return 0;
+}
+
+static int nuron_mod_exp(BIGNUM *r,const BIGNUM *a,const BIGNUM *p,
+                        const BIGNUM *m,BN_CTX *ctx)
+       {
+       if(!pvDSOHandle)
+               {
+               NURONerr(NURON_F_NURON_MOD_EXP,NURON_R_NOT_LOADED);
+               return 0;
+               }
+       return pfnModExp(r,a,p,m);
+       }
+
+#ifndef OPENSSL_NO_RSA
+static int nuron_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
+       {
+       return nuron_mod_exp(r0,I,rsa->d,rsa->n,NULL);
+       }
+#endif
+
+#ifndef OPENSSL_NO_DSA
+/* This code was liberated and adapted from the commented-out code in
+ * dsa_ossl.c. Because of the unoptimised form of the Atalla acceleration
+ * (it doesn't have a CRT form for RSA), this function means that an
+ * Atalla system running with a DSA server certificate can handshake
+ * around 5 or 6 times faster/more than an equivalent system running with
+ * RSA. Just check out the "signs" statistics from the RSA and DSA parts
+ * of "openssl speed -engine atalla dsa1024 rsa1024". */
+static int nuron_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
+                            BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
+                            BN_CTX *ctx, BN_MONT_CTX *in_mont)
+       {
+       BIGNUM t;
+       int to_return = 0;
+       BN_init(&t);
+       /* let rr = a1 ^ p1 mod m */
+       if (!nuron_mod_exp(rr,a1,p1,m,ctx))
+               goto end;
+       /* let t = a2 ^ p2 mod m */
+       if (!nuron_mod_exp(&t,a2,p2,m,ctx))
+               goto end;
+       /* let rr = rr * t mod m */
+       if (!BN_mod_mul(rr,rr,&t,m,ctx))
+               goto end;
+       to_return = 1;
+end:
+       BN_free(&t);
+       return to_return;
+       }
+
+
+static int nuron_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
+                            const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+                            BN_MONT_CTX *m_ctx)
+       {
+       return nuron_mod_exp(r, a, p, m, ctx);
+       }
+#endif
+
+/* This function is aliased to mod_exp (with the mont stuff dropped). */
+static int nuron_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                             const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+       {
+       return nuron_mod_exp(r, a, p, m, ctx);
+       }
+
+#ifndef OPENSSL_NO_DH
+/* This function is aliased to mod_exp (with the dh and mont dropped). */
+static int nuron_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 nuron_mod_exp(r, a, p, m, ctx);
+       }
+#endif
+
+#ifndef OPENSSL_NO_RSA
+static RSA_METHOD nuron_rsa =
+       {
+       "Nuron RSA method",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       nuron_rsa_mod_exp,
+       nuron_mod_exp_mont,
+       NULL,
+       NULL,
+       0,
+       NULL,
+       NULL,
+       NULL
+       };
+#endif
+
+#ifndef OPENSSL_NO_DSA
+static DSA_METHOD nuron_dsa =
+       {
+       "Nuron DSA method",
+       NULL, /* dsa_do_sign */
+       NULL, /* dsa_sign_setup */
+       NULL, /* dsa_do_verify */
+       nuron_dsa_mod_exp, /* dsa_mod_exp */
+       nuron_mod_exp_dsa, /* bn_mod_exp */
+       NULL, /* init */
+       NULL, /* finish */
+       0, /* flags */
+       NULL /* app_data */
+       };
+#endif
+
+#ifndef OPENSSL_NO_DH
+static DH_METHOD nuron_dh =
+       {
+       "Nuron DH method",
+       NULL,
+       NULL,
+       nuron_mod_exp_dh,
+       NULL,
+       NULL,
+       0,
+       NULL
+       };
+#endif
+
+/* Constants used when creating the ENGINE */
+static const char *engine_nuron_id = "nuron";
+static const char *engine_nuron_name = "Nuron hardware engine support";
+
+/* This internal function is used by ENGINE_nuron() 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_DSA
+       const DSA_METHOD *meth2;
+#endif
+#ifndef OPENSSL_NO_DH
+       const DH_METHOD *meth3;
+#endif
+       if(!ENGINE_set_id(e, engine_nuron_id) ||
+                       !ENGINE_set_name(e, engine_nuron_name) ||
+#ifndef OPENSSL_NO_RSA
+                       !ENGINE_set_RSA(e, &nuron_rsa) ||
+#endif
+#ifndef OPENSSL_NO_DSA
+                       !ENGINE_set_DSA(e, &nuron_dsa) ||
+#endif
+#ifndef OPENSSL_NO_DH
+                       !ENGINE_set_DH(e, &nuron_dh) ||
+#endif
+                       !ENGINE_set_destroy_function(e, nuron_destroy) ||
+                       !ENGINE_set_init_function(e, nuron_init) ||
+                       !ENGINE_set_finish_function(e, nuron_finish) ||
+                       !ENGINE_set_ctrl_function(e, nuron_ctrl) ||
+                       !ENGINE_set_cmd_defns(e, nuron_cmd_defns))
+               return 0;
+
+#ifndef OPENSSL_NO_RSA
+       /* We know that the "PKCS1_SSLeay()" functions hook properly
+        * to the nuron-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();
+       nuron_rsa.rsa_pub_enc=meth1->rsa_pub_enc;
+       nuron_rsa.rsa_pub_dec=meth1->rsa_pub_dec;
+       nuron_rsa.rsa_priv_enc=meth1->rsa_priv_enc;
+       nuron_rsa.rsa_priv_dec=meth1->rsa_priv_dec;
+#endif
+
+#ifndef OPENSSL_NO_DSA
+       /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish
+        * bits. */
+       meth2=DSA_OpenSSL();
+       nuron_dsa.dsa_do_sign=meth2->dsa_do_sign;
+       nuron_dsa.dsa_sign_setup=meth2->dsa_sign_setup;
+       nuron_dsa.dsa_do_verify=meth2->dsa_do_verify;
+#endif
+
+#ifndef OPENSSL_NO_DH
+       /* Much the same for Diffie-Hellman */
+       meth3=DH_OpenSSL();
+       nuron_dh.generate_key=meth3->generate_key;
+       nuron_dh.compute_key=meth3->compute_key;
+#endif
+
+       /* Ensure the nuron error handling is set up */
+       ERR_load_NURON_strings();
+       return 1;
+       }
+
+static ENGINE *engine_nuron(void)
+       {
+       ENGINE *ret = ENGINE_new();
+       if(!ret)
+               return NULL;
+       if(!bind_helper(ret))
+               {
+               ENGINE_free(ret);
+               return NULL;
+               }
+       return ret;
+       }
+
+void ENGINE_load_nuron(void)
+       {
+       /* Copied from eng_[openssl|dyn].c */
+       ENGINE *toadd = engine_nuron();
+       if(!toadd) return;
+       ENGINE_add(toadd);
+       ENGINE_free(toadd);
+       ERR_clear_error();
+       }
+
+/* This stuff is needed if this ENGINE is being compiled into a self-contained
+ * shared-library. */     
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_fn(ENGINE *e, const char *id)
+       {
+       if(id && (strcmp(id, engine_nuron_id) != 0))
+               return 0;
+       if(!bind_helper(e))
+               return 0;
+       return 1;
+       }       
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
+#endif /* ENGINE_DYNAMIC_SUPPORT */
+
+#endif /* !OPENSSL_NO_HW_NURON */
+#endif /* !OPENSSL_NO_HW */
diff --git a/engines/e_nuron_err.c b/engines/e_nuron_err.c
new file mode 100644 (file)
index 0000000..df9d7bd
--- /dev/null
@@ -0,0 +1,142 @@
+/* hw_nuron_err.c */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "hw_nuron_err.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA NURON_str_functs[]=
+       {
+{ERR_PACK(0,NURON_F_NURON_CTRL,0),     "NURON_CTRL"},
+{ERR_PACK(0,NURON_F_NURON_FINISH,0),   "NURON_FINISH"},
+{ERR_PACK(0,NURON_F_NURON_INIT,0),     "NURON_INIT"},
+{ERR_PACK(0,NURON_F_NURON_MOD_EXP,0),  "NURON_MOD_EXP"},
+{0,NULL}
+       };
+
+static ERR_STRING_DATA NURON_str_reasons[]=
+       {
+{NURON_R_ALREADY_LOADED                  ,"already loaded"},
+{NURON_R_CTRL_COMMAND_NOT_IMPLEMENTED    ,"ctrl command not implemented"},
+{NURON_R_DSO_FAILURE                     ,"dso failure"},
+{NURON_R_DSO_FUNCTION_NOT_FOUND          ,"dso function not found"},
+{NURON_R_DSO_NOT_FOUND                   ,"dso not found"},
+{NURON_R_NOT_LOADED                      ,"not loaded"},
+{0,NULL}
+       };
+
+#endif
+
+#ifdef NURON_LIB_NAME
+static ERR_STRING_DATA NURON_lib_name[]=
+        {
+{0     ,NURON_LIB_NAME},
+{0,NULL}
+       };
+#endif
+
+
+static int NURON_lib_error_code=0;
+static int NURON_error_init=1;
+
+static void ERR_load_NURON_strings(void)
+       {
+       if (NURON_lib_error_code == 0)
+               NURON_lib_error_code=ERR_get_next_error_library();
+
+       if (NURON_error_init)
+               {
+               NURON_error_init=0;
+#ifndef OPENSSL_NO_ERR
+               ERR_load_strings(NURON_lib_error_code,NURON_str_functs);
+               ERR_load_strings(NURON_lib_error_code,NURON_str_reasons);
+#endif
+
+#ifdef NURON_LIB_NAME
+               NURON_lib_name->error = ERR_PACK(NURON_lib_error_code,0,0);
+               ERR_load_strings(0,NURON_lib_name);
+#endif
+               }
+       }
+
+static void ERR_unload_NURON_strings(void)
+       {
+       if (NURON_error_init == 0)
+               {
+#ifndef OPENSSL_NO_ERR
+               ERR_unload_strings(NURON_lib_error_code,NURON_str_functs);
+               ERR_unload_strings(NURON_lib_error_code,NURON_str_reasons);
+#endif
+
+#ifdef NURON_LIB_NAME
+               ERR_unload_strings(0,NURON_lib_name);
+#endif
+               NURON_error_init=1;
+               }
+       }
+
+static void ERR_NURON_error(int function, int reason, char *file, int line)
+       {
+       if (NURON_lib_error_code == 0)
+               NURON_lib_error_code=ERR_get_next_error_library();
+       ERR_PUT_error(NURON_lib_error_code,function,reason,file,line);
+       }
diff --git a/engines/e_nuron_err.h b/engines/e_nuron_err.h
new file mode 100644 (file)
index 0000000..a56bfdf
--- /dev/null
@@ -0,0 +1,86 @@
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_NURON_ERR_H
+#define HEADER_NURON_ERR_H
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+static void ERR_load_NURON_strings(void);
+static void ERR_unload_NURON_strings(void);
+static void ERR_NURON_error(int function, int reason, char *file, int line);
+#define NURONerr(f,r) ERR_NURON_error((f),(r),__FILE__,__LINE__)
+
+/* Error codes for the NURON functions. */
+
+/* Function codes. */
+#define NURON_F_NURON_CTRL                              100
+#define NURON_F_NURON_FINISH                            101
+#define NURON_F_NURON_INIT                              102
+#define NURON_F_NURON_MOD_EXP                           103
+
+/* Reason codes. */
+#define NURON_R_ALREADY_LOADED                          100
+#define NURON_R_CTRL_COMMAND_NOT_IMPLEMENTED            101
+#define NURON_R_DSO_FAILURE                             102
+#define NURON_R_DSO_FUNCTION_NOT_FOUND                  103
+#define NURON_R_DSO_NOT_FOUND                           104
+#define NURON_R_NOT_LOADED                              105
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/engines/e_sureware.c b/engines/e_sureware.c
new file mode 100644 (file)
index 0000000..89f7086
--- /dev/null
@@ -0,0 +1,1040 @@
+/* Written by Corinne Dive-Reclus(cdive@baltimore.com)
+* 
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+*    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
+*    the documentation and/or other materials provided with the
+*    distribution.
+*
+* 3. All advertising materials mentioning features or use of this
+*    software must display the following acknowledgment:
+*    "This product includes software developed by the OpenSSL Project
+*    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+*
+* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+*    endorse or promote products derived from this software without
+*    prior written permission. For written permission, please contact
+*    licensing@OpenSSL.org.
+*
+* 5. Products derived from this software may not be called "OpenSSL"
+*    nor may "OpenSSL" appear in their names without prior written
+*    permission of the OpenSSL Project.
+*
+* 6. Redistributions of any form whatsoever must retain the following
+*    acknowledgment:
+*    "This product includes software developed by the OpenSSL Project
+*    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+*
+* Written by Corinne Dive-Reclus(cdive@baltimore.com)
+*
+* Copyright@2001 Baltimore Technologies Ltd.
+* All right Reserved.
+*                                                                                                                                                                                              *       
+*              THIS FILE IS PROVIDED BY BALTIMORE TECHNOLOGIES ``AS IS'' AND                                                                                                                                                   *
+*              ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE                                   * 
+*              IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE                              *
+*              ARE DISCLAIMED.  IN NO EVENT SHALL BALTIMORE TECHNOLOGIES BE LIABLE                                             *
+*              FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL                              *
+*              DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS                                 *
+*              OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)                                   *
+*              HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT                              *
+*              LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY                               *
+*              OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF                                  *
+*              SUCH DAMAGE.                                                                                                                                                    *
+====================================================================*/
+
+#include <stdio.h>
+#include "cryptlib.h"
+#include <openssl/crypto.h>
+#include <openssl/pem.h>
+#include <openssl/dso.h>
+#include "eng_int.h"
+#include "engine.h"
+#include <openssl/engine.h>
+
+#ifndef OPENSSL_NO_HW
+#ifndef OPENSSL_NO_HW_SUREWARE
+
+#ifdef FLAT_INC
+#include "sureware.h"
+#else
+#include "vendor_defns/sureware.h"
+#endif
+
+#define SUREWARE_LIB_NAME "sureware engine"
+#include "hw_sureware_err.c"
+
+static int surewarehk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
+static int surewarehk_destroy(ENGINE *e);
+static int surewarehk_init(ENGINE *e);
+static int surewarehk_finish(ENGINE *e);
+static int surewarehk_modexp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+       const BIGNUM *m, BN_CTX *ctx);
+
+/* RSA stuff */
+static int surewarehk_rsa_priv_dec(int flen,const unsigned char *from,unsigned char *to,
+                       RSA *rsa,int padding);
+static int surewarehk_rsa_sign(int flen,const unsigned char *from,unsigned char *to,
+                           RSA *rsa,int padding);
+
+/* RAND stuff */
+static int surewarehk_rand_bytes(unsigned char *buf, int num);
+static void surewarehk_rand_seed(const void *buf, int num);
+static void surewarehk_rand_add(const void *buf, int num, double entropy);
+
+/* KM stuff */
+static EVP_PKEY *surewarehk_load_privkey(ENGINE *e, const char *key_id,
+       UI_METHOD *ui_method, void *callback_data);
+static EVP_PKEY *surewarehk_load_pubkey(ENGINE *e, const char *key_id,
+       UI_METHOD *ui_method, void *callback_data);
+static void surewarehk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
+       int idx,long argl, void *argp);
+#if 0
+static void surewarehk_dh_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
+       int idx,long argl, void *argp);
+#endif
+
+#ifndef OPENSSL_NO_RSA
+/* This function is aliased to mod_exp (with the mont stuff dropped). */
+static int surewarehk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+               const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+{
+       return surewarehk_modexp(r, a, p, m, ctx);
+}
+
+/* Our internal RSA_METHOD that we provide pointers to */
+static RSA_METHOD surewarehk_rsa =
+       {
+       "SureWare RSA method",
+       NULL, /* pub_enc*/
+       NULL, /* pub_dec*/
+       surewarehk_rsa_sign, /* our rsa_sign is OpenSSL priv_enc*/
+       surewarehk_rsa_priv_dec, /* priv_dec*/
+       NULL, /*mod_exp*/
+       surewarehk_mod_exp_mont, /*mod_exp_mongomery*/
+       NULL, /* init*/
+       NULL, /* finish*/
+       0,      /* RSA flag*/
+       NULL, 
+       NULL, /* OpenSSL sign*/
+       NULL  /* OpenSSL verify*/
+       };
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* Our internal DH_METHOD that we provide pointers to */
+/* This function is aliased to mod_exp (with the dh and mont dropped). */
+static int surewarehk_modexp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
+       const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
+{
+       return surewarehk_modexp(r, a, p, m, ctx);
+}
+
+static DH_METHOD surewarehk_dh =
+       {
+       "SureWare DH method",
+       NULL,/*gen_key*/
+       NULL,/*agree,*/
+       surewarehk_modexp_dh, /*dh mod exp*/
+       NULL, /* init*/
+       NULL, /* finish*/
+       0,    /* flags*/
+       NULL 
+       };
+#endif
+
+static RAND_METHOD surewarehk_rand =
+       {
+       /* "SureWare RAND method", */
+       surewarehk_rand_seed,
+       surewarehk_rand_bytes,
+       NULL,/*cleanup*/
+       surewarehk_rand_add,
+       surewarehk_rand_bytes,
+       NULL,/*rand_status*/
+       };
+
+#ifndef OPENSSL_NO_DSA
+/* DSA stuff */
+static DSA_SIG * surewarehk_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
+static int surewarehk_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
+               BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
+               BN_CTX *ctx, BN_MONT_CTX *in_mont)
+{
+       BIGNUM t;
+       int to_return = 0;
+       BN_init(&t);
+       /* let rr = a1 ^ p1 mod m */
+       if (!surewarehk_modexp(rr,a1,p1,m,ctx)) goto end;
+       /* let t = a2 ^ p2 mod m */
+       if (!surewarehk_modexp(&t,a2,p2,m,ctx)) goto end;
+       /* let rr = rr * t mod m */
+       if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end;
+       to_return = 1;
+end:
+       BN_free(&t);
+       return to_return;
+}
+
+static DSA_METHOD surewarehk_dsa =
+       {
+        "SureWare DSA method", 
+       surewarehk_dsa_do_sign,
+       NULL,/*sign setup*/
+       NULL,/*verify,*/
+       surewarehk_dsa_mod_exp,/*mod exp*/
+       NULL,/*bn mod exp*/
+       NULL, /*init*/
+       NULL,/*finish*/
+       0,
+       NULL,
+       };
+#endif
+
+static const char *engine_sureware_id = "sureware";
+static const char *engine_sureware_name = "SureWare hardware engine support";
+
+/* Now, to our own code */
+
+/* As this is only ever called once, there's no need for locking
+ * (indeed - the lock will already be held by our caller!!!) */
+static int bind_sureware(ENGINE *e)
+{
+#ifndef OPENSSL_NO_RSA
+       const RSA_METHOD *meth1;
+#endif
+#ifndef OPENSSL_NO_DSA
+       const DSA_METHOD *meth2;
+#endif
+#ifndef OPENSSL_NO_DH
+       const DH_METHOD *meth3;
+#endif
+
+       if(!ENGINE_set_id(e, engine_sureware_id) ||
+          !ENGINE_set_name(e, engine_sureware_name) ||
+#ifndef OPENSSL_NO_RSA
+          !ENGINE_set_RSA(e, &surewarehk_rsa) ||
+#endif
+#ifndef OPENSSL_NO_DSA
+          !ENGINE_set_DSA(e, &surewarehk_dsa) ||
+#endif
+#ifndef OPENSSL_NO_DH
+          !ENGINE_set_DH(e, &surewarehk_dh) ||
+#endif
+          !ENGINE_set_RAND(e, &surewarehk_rand) ||
+          !ENGINE_set_destroy_function(e, surewarehk_destroy) ||
+          !ENGINE_set_init_function(e, surewarehk_init) ||
+          !ENGINE_set_finish_function(e, surewarehk_finish) ||
+          !ENGINE_set_ctrl_function(e, surewarehk_ctrl) ||
+          !ENGINE_set_load_privkey_function(e, surewarehk_load_privkey) ||
+          !ENGINE_set_load_pubkey_function(e, surewarehk_load_pubkey))
+         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();
+       if (meth1)
+       {
+               surewarehk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
+               surewarehk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
+       }
+#endif
+
+#ifndef OPENSSL_NO_DSA
+       /* Use the DSA_OpenSSL() method and just hook the mod_exp-ish
+        * bits. */
+       meth2 = DSA_OpenSSL();
+       if (meth2)
+       {
+               surewarehk_dsa.dsa_do_verify = meth2->dsa_do_verify;
+       }
+#endif
+
+#ifndef OPENSSL_NO_DH
+       /* Much the same for Diffie-Hellman */
+       meth3 = DH_OpenSSL();
+       if (meth3)
+       {
+               surewarehk_dh.generate_key = meth3->generate_key;
+               surewarehk_dh.compute_key = meth3->compute_key;
+       }
+#endif
+
+       /* Ensure the sureware error handling is set up */
+       ERR_load_SUREWARE_strings();
+       return 1;
+}
+
+#ifdef ENGINE_DYNAMIC_SUPPORT
+static int bind_helper(ENGINE *e, const char *id)
+       {
+       if(id && (strcmp(id, engine_sureware_id) != 0))
+               return 0;
+       if(!bind_sureware(e))
+               return 0;
+       return 1;
+       }       
+IMPLEMENT_DYNAMIC_CHECK_FN()
+IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
+#else
+static ENGINE *engine_sureware(void)
+       {
+       ENGINE *ret = ENGINE_new();
+       if(!ret)
+               return NULL;
+       if(!bind_sureware(ret))
+               {
+               ENGINE_free(ret);
+               return NULL;
+               }
+       return ret;
+       }
+
+void ENGINE_load_sureware(void)
+       {
+       /* Copied from eng_[openssl|dyn].c */
+       ENGINE *toadd = engine_sureware();
+       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 SureWareHook 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 *surewarehk_dso = NULL;
+#ifndef OPENSSL_NO_RSA
+static int rsaHndidx = -1;     /* Index for KM handle.  Not really used yet. */
+#endif
+#ifndef OPENSSL_NO_DSA
+static int dsaHndidx = -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. */
+static SureWareHook_Init_t *p_surewarehk_Init = NULL;
+static SureWareHook_Finish_t *p_surewarehk_Finish = NULL;
+static SureWareHook_Rand_Bytes_t *p_surewarehk_Rand_Bytes = NULL;
+static SureWareHook_Rand_Seed_t *p_surewarehk_Rand_Seed = NULL;
+static SureWareHook_Load_Privkey_t *p_surewarehk_Load_Privkey = NULL;
+static SureWareHook_Info_Pubkey_t *p_surewarehk_Info_Pubkey = NULL;
+static SureWareHook_Load_Rsa_Pubkey_t *p_surewarehk_Load_Rsa_Pubkey = NULL;
+static SureWareHook_Load_Dsa_Pubkey_t *p_surewarehk_Load_Dsa_Pubkey = NULL;
+static SureWareHook_Free_t *p_surewarehk_Free=NULL;
+static SureWareHook_Rsa_Priv_Dec_t *p_surewarehk_Rsa_Priv_Dec=NULL;
+static SureWareHook_Rsa_Sign_t *p_surewarehk_Rsa_Sign=NULL;
+static SureWareHook_Dsa_Sign_t *p_surewarehk_Dsa_Sign=NULL;
+static SureWareHook_Mod_Exp_t *p_surewarehk_Mod_Exp=NULL;
+
+/* Used in the DSO operations. */
+static const char *surewarehk_LIBNAME = "SureWareHook";
+static const char *n_surewarehk_Init = "SureWareHook_Init";
+static const char *n_surewarehk_Finish = "SureWareHook_Finish";
+static const char *n_surewarehk_Rand_Bytes="SureWareHook_Rand_Bytes";
+static const char *n_surewarehk_Rand_Seed="SureWareHook_Rand_Seed";
+static const char *n_surewarehk_Load_Privkey="SureWareHook_Load_Privkey";
+static const char *n_surewarehk_Info_Pubkey="SureWareHook_Info_Pubkey";
+static const char *n_surewarehk_Load_Rsa_Pubkey="SureWareHook_Load_Rsa_Pubkey";
+static const char *n_surewarehk_Load_Dsa_Pubkey="SureWareHook_Load_Dsa_Pubkey";
+static const char *n_surewarehk_Free="SureWareHook_Free";
+static const char *n_surewarehk_Rsa_Priv_Dec="SureWareHook_Rsa_Priv_Dec";
+static const char *n_surewarehk_Rsa_Sign="SureWareHook_Rsa_Sign";
+static const char *n_surewarehk_Dsa_Sign="SureWareHook_Dsa_Sign";
+static const char *n_surewarehk_Mod_Exp="SureWareHook_Mod_Exp";
+static BIO *logstream = NULL;
+
+/* SureWareHook 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. 
+*/
+static int threadsafe=1;
+static int surewarehk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
+{
+       int to_return = 1;
+
+       switch(cmd)
+       {
+               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
+                               SUREWAREerr(SUREWARE_F_SUREWAREHK_CTRL,SUREWARE_R_BIO_WAS_FREED);
+               }
+               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);
+               threadsafe = 0;
+               CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
+               break;
+
+       /* The command isn't understood by this engine */
+       default:
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_CTRL,
+                       ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
+               to_return = 0;
+               break;
+               }
+
+       return to_return;
+}
+
+/* Destructor (complements the "ENGINE_surewarehk()" constructor) */
+static int surewarehk_destroy(ENGINE *e)
+{
+       ERR_unload_SUREWARE_strings();
+       return 1;
+}
+
+/* (de)initialisation functions. */
+static int surewarehk_init(ENGINE *e)
+{
+       char msg[64]="ENGINE_init";
+       SureWareHook_Init_t *p1=NULL;
+       SureWareHook_Finish_t *p2=NULL;
+       SureWareHook_Rand_Bytes_t *p3=NULL;
+       SureWareHook_Rand_Seed_t *p4=NULL;
+       SureWareHook_Load_Privkey_t *p5=NULL;
+       SureWareHook_Load_Rsa_Pubkey_t *p6=NULL;
+       SureWareHook_Free_t *p7=NULL;
+       SureWareHook_Rsa_Priv_Dec_t *p8=NULL;
+       SureWareHook_Rsa_Sign_t *p9=NULL;
+       SureWareHook_Dsa_Sign_t *p12=NULL;
+       SureWareHook_Info_Pubkey_t *p13=NULL;
+       SureWareHook_Load_Dsa_Pubkey_t *p14=NULL;
+       SureWareHook_Mod_Exp_t *p15=NULL;
+
+       if(surewarehk_dso != NULL)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_INIT,ENGINE_R_ALREADY_LOADED);
+               goto err;
+       }
+       /* Attempt to load libsurewarehk.so/surewarehk.dll/whatever. */
+       surewarehk_dso = DSO_load(NULL, surewarehk_LIBNAME, NULL, 0);
+       if(surewarehk_dso == NULL)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_INIT,ENGINE_R_DSO_FAILURE);
+               goto err;
+       }
+       if(!(p1=(SureWareHook_Init_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Init)) ||
+          !(p2=(SureWareHook_Finish_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Finish)) ||
+          !(p3=(SureWareHook_Rand_Bytes_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Rand_Bytes)) ||
+          !(p4=(SureWareHook_Rand_Seed_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Rand_Seed)) ||
+          !(p5=(SureWareHook_Load_Privkey_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Load_Privkey)) ||
+          !(p6=(SureWareHook_Load_Rsa_Pubkey_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Load_Rsa_Pubkey)) ||
+          !(p7=(SureWareHook_Free_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Free)) ||
+          !(p8=(SureWareHook_Rsa_Priv_Dec_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Rsa_Priv_Dec)) ||
+          !(p9=(SureWareHook_Rsa_Sign_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Rsa_Sign)) ||
+          !(p12=(SureWareHook_Dsa_Sign_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Dsa_Sign)) ||
+          !(p13=(SureWareHook_Info_Pubkey_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Info_Pubkey)) ||
+          !(p14=(SureWareHook_Load_Dsa_Pubkey_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Load_Dsa_Pubkey)) ||
+          !(p15=(SureWareHook_Mod_Exp_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Mod_Exp)))
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_INIT,ENGINE_R_DSO_FAILURE);
+               goto err;
+       }
+       /* Copy the pointers */
+       p_surewarehk_Init = p1;
+       p_surewarehk_Finish = p2;
+       p_surewarehk_Rand_Bytes = p3;
+       p_surewarehk_Rand_Seed = p4;
+       p_surewarehk_Load_Privkey = p5;
+       p_surewarehk_Load_Rsa_Pubkey = p6;
+       p_surewarehk_Free = p7;
+       p_surewarehk_Rsa_Priv_Dec = p8;
+       p_surewarehk_Rsa_Sign = p9;
+       p_surewarehk_Dsa_Sign = p12;
+       p_surewarehk_Info_Pubkey = p13;
+       p_surewarehk_Load_Dsa_Pubkey = p14;
+       p_surewarehk_Mod_Exp = p15;
+       /* Contact the hardware and initialises it. */
+       if(p_surewarehk_Init(msg,threadsafe)==SUREWAREHOOK_ERROR_UNIT_FAILURE)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_INIT,SUREWARE_R_UNIT_FAILURE);
+               goto err;
+       }
+       if(p_surewarehk_Init(msg,threadsafe)==SUREWAREHOOK_ERROR_UNIT_FAILURE)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_INIT,SUREWARE_R_UNIT_FAILURE);
+               goto err;
+       }
+       /* try to load the default private key, if failed does not return a failure but
+           wait for an explicit ENGINE_load_privakey */
+       surewarehk_load_privkey(e,NULL,NULL,NULL);
+
+       /* Everything's fine. */
+#ifndef OPENSSL_NO_RSA
+       if (rsaHndidx == -1)
+               rsaHndidx = RSA_get_ex_new_index(0,
+                                               "SureWareHook RSA key handle",
+                                               NULL, NULL, surewarehk_ex_free);
+#endif
+#ifndef OPENSSL_NO_DSA
+       if (dsaHndidx == -1)
+               dsaHndidx = DSA_get_ex_new_index(0,
+                                               "SureWareHook DSA key handle",
+                                               NULL, NULL, surewarehk_ex_free);
+#endif
+
+       return 1;
+err:
+       if(surewarehk_dso)
+               DSO_free(surewarehk_dso);
+       surewarehk_dso = NULL;
+       p_surewarehk_Init = NULL;
+       p_surewarehk_Finish = NULL;
+       p_surewarehk_Rand_Bytes = NULL;
+       p_surewarehk_Rand_Seed = NULL;
+       p_surewarehk_Load_Privkey = NULL;
+       p_surewarehk_Load_Rsa_Pubkey = NULL;
+       p_surewarehk_Free = NULL;
+       p_surewarehk_Rsa_Priv_Dec = NULL;
+       p_surewarehk_Rsa_Sign = NULL;
+       p_surewarehk_Dsa_Sign = NULL;
+       p_surewarehk_Info_Pubkey = NULL;
+       p_surewarehk_Load_Dsa_Pubkey = NULL;
+       p_surewarehk_Mod_Exp = NULL;
+       return 0;
+}
+
+static int surewarehk_finish(ENGINE *e)
+{
+       int to_return = 1;
+       if(surewarehk_dso == NULL)
+               {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_FINISH,ENGINE_R_NOT_LOADED);
+               to_return = 0;
+               goto err;
+               }
+       p_surewarehk_Finish();
+       if(!DSO_free(surewarehk_dso))
+               {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_FINISH,ENGINE_R_DSO_FAILURE);
+               to_return = 0;
+               goto err;
+               }
+ err:
+       if (logstream)
+               BIO_free(logstream);
+       surewarehk_dso = NULL;
+       p_surewarehk_Init = NULL;
+       p_surewarehk_Finish = NULL;
+       p_surewarehk_Rand_Bytes = NULL;
+       p_surewarehk_Rand_Seed = NULL;
+       p_surewarehk_Load_Privkey = NULL;
+       p_surewarehk_Load_Rsa_Pubkey = NULL;
+       p_surewarehk_Free = NULL;
+       p_surewarehk_Rsa_Priv_Dec = NULL;
+       p_surewarehk_Rsa_Sign = NULL;
+       p_surewarehk_Dsa_Sign = NULL;
+       p_surewarehk_Info_Pubkey = NULL;
+       p_surewarehk_Load_Dsa_Pubkey = NULL;
+       p_surewarehk_Mod_Exp = NULL;
+       return to_return;
+}
+
+static void surewarehk_error_handling(char *const msg,int func,int ret)
+{
+       switch (ret)
+       {
+               case SUREWAREHOOK_ERROR_UNIT_FAILURE:
+                       ENGINEerr(func,SUREWARE_R_UNIT_FAILURE);
+                       break;
+               case SUREWAREHOOK_ERROR_FALLBACK:
+                       ENGINEerr(func,SUREWARE_R_REQUEST_FALLBACK);
+                       break;
+               case SUREWAREHOOK_ERROR_DATA_SIZE:
+                       ENGINEerr(func,SUREWARE_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
+                       break;
+               case SUREWAREHOOK_ERROR_INVALID_PAD:
+                       ENGINEerr(func,RSA_R_PADDING_CHECK_FAILED);
+                       break;
+               default:
+                       ENGINEerr(func,SUREWARE_R_REQUEST_FAILED);
+                       break;
+               case 1:/*nothing*/
+                       msg[0]='\0';
+       }
+       if (*msg)
+       {
+               ERR_add_error_data(1,msg);
+               if (logstream)
+               {
+                       CRYPTO_w_lock(CRYPTO_LOCK_BIO);
+                       BIO_write(logstream, msg, strlen(msg));
+                       CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
+               }
+       }
+}
+
+static int surewarehk_rand_bytes(unsigned char *buf, int num)
+{
+       int ret=0;
+       char msg[64]="ENGINE_rand_bytes";
+       if(!p_surewarehk_Rand_Bytes)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_RAND_BYTES,ENGINE_R_NOT_INITIALISED);
+       }
+       else
+       {
+               ret = p_surewarehk_Rand_Bytes(msg,buf, num);
+               surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_RAND_BYTES,ret);
+       }
+       return ret==1 ? 1 : 0;
+}
+
+static void surewarehk_rand_seed(const void *buf, int num)
+{
+       int ret=0;
+       char msg[64]="ENGINE_rand_seed";
+       if(!p_surewarehk_Rand_Seed)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_RAND_SEED,ENGINE_R_NOT_INITIALISED);
+       }
+       else
+       {
+               ret = p_surewarehk_Rand_Seed(msg,buf, num);
+               surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_RAND_SEED,ret);
+       }
+}
+
+static void surewarehk_rand_add(const void *buf, int num, double entropy)
+{
+       surewarehk_rand_seed(buf,num);
+}
+
+static EVP_PKEY* sureware_load_public(ENGINE *e,const char *key_id,char *hptr,unsigned long el,char keytype)
+{
+       EVP_PKEY *res = NULL;
+#ifndef OPENSSL_NO_RSA
+       RSA *rsatmp = NULL;
+#endif
+#ifndef OPENSSL_NO_DSA
+       DSA *dsatmp=NULL;
+#endif
+       char msg[64]="sureware_load_public";
+       int ret=0;
+       if(!p_surewarehk_Load_Rsa_Pubkey || !p_surewarehk_Load_Dsa_Pubkey)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_LOAD_PUBLIC_KEY,ENGINE_R_NOT_INITIALISED);
+               goto err;
+       }
+       switch (keytype)
+       {
+#ifndef OPENSSL_NO_RSA
+       case 1: /*RSA*/
+               /* set private external reference */
+               rsatmp = RSA_new_method(e);
+               RSA_set_ex_data(rsatmp,rsaHndidx,hptr);
+               rsatmp->flags |= RSA_FLAG_EXT_PKEY;
+
+               /* set public big nums*/
+               rsatmp->e = BN_new();
+               rsatmp->n = BN_new();
+               bn_expand2(rsatmp->e, el/sizeof(BN_ULONG));
+               bn_expand2(rsatmp->n, el/sizeof(BN_ULONG));
+               if (!rsatmp->e || rsatmp->e->dmax!=(int)(el/sizeof(BN_ULONG))|| 
+                       !rsatmp->n || rsatmp->n->dmax!=(int)(el/sizeof(BN_ULONG)))
+                       goto err;
+               ret=p_surewarehk_Load_Rsa_Pubkey(msg,key_id,el,
+                                                (unsigned long *)rsatmp->n->d,
+                                                (unsigned long *)rsatmp->e->d);
+               surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_LOAD_PUBLIC_KEY,ret);
+               if (ret!=1)
+               {
+                       SUREWAREerr(SUREWARE_F_SUREWAREHK_LOAD_PRIVATE_KEY,ENGINE_R_FAILED_LOADING_PUBLIC_KEY);
+                       goto err;
+               }
+               /* normalise pub e and pub n */
+               rsatmp->e->top=el/sizeof(BN_ULONG);
+               bn_fix_top(rsatmp->e);
+               rsatmp->n->top=el/sizeof(BN_ULONG);
+               bn_fix_top(rsatmp->n);
+               /* create an EVP object: engine + rsa key */
+               res = EVP_PKEY_new();
+               EVP_PKEY_assign_RSA(res, rsatmp);
+               break;
+#endif
+
+#ifndef OPENSSL_NO_DSA
+       case 2:/*DSA*/
+               /* set private/public external reference */
+               dsatmp = DSA_new_method(e);
+               DSA_set_ex_data(dsatmp,dsaHndidx,hptr);
+               /*dsatmp->flags |= DSA_FLAG_EXT_PKEY;*/
+
+               /* set public key*/
+               dsatmp->pub_key = BN_new();
+               dsatmp->p = BN_new();
+               dsatmp->q = BN_new();
+               dsatmp->g = BN_new();
+               bn_expand2(dsatmp->pub_key, el/sizeof(BN_ULONG));
+               bn_expand2(dsatmp->p, el/sizeof(BN_ULONG));
+               bn_expand2(dsatmp->q, 20/sizeof(BN_ULONG));
+               bn_expand2(dsatmp->g, el/sizeof(BN_ULONG));
+               if (!dsatmp->pub_key || dsatmp->pub_key->dmax!=(int)(el/sizeof(BN_ULONG))|| 
+                       !dsatmp->p || dsatmp->p->dmax!=(int)(el/sizeof(BN_ULONG)) ||
+                       !dsatmp->q || dsatmp->q->dmax!=20/sizeof(BN_ULONG) ||
+                       !dsatmp->g || dsatmp->g->dmax!=(int)(el/sizeof(BN_ULONG)))
+                       goto err;
+
+               ret=p_surewarehk_Load_Dsa_Pubkey(msg,key_id,el,
+                                                (unsigned long *)dsatmp->pub_key->d, 
+                                                (unsigned long *)dsatmp->p->d,
+                                                (unsigned long *)dsatmp->q->d,
+                                                (unsigned long *)dsatmp->g->d);
+               surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_LOAD_PUBLIC_KEY,ret);
+               if (ret!=1)
+               {
+                       SUREWAREerr(SUREWARE_F_SUREWAREHK_LOAD_PRIVATE_KEY,ENGINE_R_FAILED_LOADING_PUBLIC_KEY);
+                       goto err;
+               }
+               /* set parameters */
+               /* normalise pubkey and parameters in case of */
+               dsatmp->pub_key->top=el/sizeof(BN_ULONG);
+               bn_fix_top(dsatmp->pub_key);
+               dsatmp->p->top=el/sizeof(BN_ULONG);
+               bn_fix_top(dsatmp->p);
+               dsatmp->q->top=20/sizeof(BN_ULONG);
+               bn_fix_top(dsatmp->q);
+               dsatmp->g->top=el/sizeof(BN_ULONG);
+               bn_fix_top(dsatmp->g);
+
+               /* create an EVP object: engine + rsa key */
+               res = EVP_PKEY_new();
+               EVP_PKEY_assign_DSA(res, dsatmp);
+               break;
+#endif
+
+       default:
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_LOAD_PRIVATE_KEY,ENGINE_R_FAILED_LOADING_PRIVATE_KEY);
+               goto err;
+       }
+       return res;
+ err:
+       if (res)
+               EVP_PKEY_free(res);
+#ifndef OPENSSL_NO_RSA
+       if (rsatmp)
+               RSA_free(rsatmp);
+#endif
+#ifndef OPENSSL_NO_DSA
+       if (dsatmp)
+               DSA_free(dsatmp);
+#endif
+       return NULL;
+}
+
+static EVP_PKEY *surewarehk_load_privkey(ENGINE *e, const char *key_id,
+                                        UI_METHOD *ui_method, void *callback_data)
+{
+       EVP_PKEY *res = NULL;
+       int ret=0;
+       unsigned long el=0;
+       char *hptr=NULL;
+       char keytype=0;
+       char msg[64]="ENGINE_load_privkey";
+
+       if(!p_surewarehk_Load_Privkey)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_LOAD_PRIVATE_KEY,ENGINE_R_NOT_INITIALISED);
+       }
+       else
+       {
+               ret=p_surewarehk_Load_Privkey(msg,key_id,&hptr,&el,&keytype);
+               if (ret!=1)
+               {
+                       SUREWAREerr(SUREWARE_F_SUREWAREHK_LOAD_PRIVATE_KEY,ENGINE_R_FAILED_LOADING_PRIVATE_KEY);
+                       ERR_add_error_data(1,msg);              
+               }
+               else
+                       res=sureware_load_public(e,key_id,hptr,el,keytype);
+       }
+       return res;
+}
+
+static EVP_PKEY *surewarehk_load_pubkey(ENGINE *e, const char *key_id,
+                                        UI_METHOD *ui_method, void *callback_data)
+{
+       EVP_PKEY *res = NULL;
+       int ret=0;
+       unsigned long el=0;
+       char *hptr=NULL;
+       char keytype=0;
+       char msg[64]="ENGINE_load_pubkey";
+
+       if(!p_surewarehk_Info_Pubkey)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_LOAD_PUBLIC_KEY,ENGINE_R_NOT_INITIALISED);
+       }
+       else
+       {
+               /* call once to identify if DSA or RSA */
+               ret=p_surewarehk_Info_Pubkey(msg,key_id,&el,&keytype);
+               if (ret!=1)
+               {
+                       SUREWAREerr(SUREWARE_F_SUREWAREHK_LOAD_PUBLIC_KEY,ENGINE_R_FAILED_LOADING_PUBLIC_KEY);
+                       ERR_add_error_data(1,msg);
+               }
+               else
+                       res=sureware_load_public(e,key_id,hptr,el,keytype);
+       }
+       return res;
+}
+
+/* This cleans up an RSA/DSA KM key(do not destroy the key into the hardware)
+, called when ex_data is freed */
+static void surewarehk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
+       int idx,long argl, void *argp)
+{
+       if(!p_surewarehk_Free)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_EX_FREE,ENGINE_R_NOT_INITIALISED);
+       }
+       else
+               p_surewarehk_Free((char *)item,0);
+}
+
+#if 0
+/* not currently used (bug?) */
+/* This cleans up an DH KM key (destroys the key into hardware), 
+called when ex_data is freed */
+static void surewarehk_dh_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
+       int idx,long argl, void *argp)
+{
+       if(!p_surewarehk_Free)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_EX_FREE,ENGINE_R_NOT_INITIALISED);
+       }
+       else
+               p_surewarehk_Free((char *)item,1);
+}
+#endif
+
+/*
+* return number of decrypted bytes
+*/
+#ifndef OPENSSL_NO_RSA
+static int surewarehk_rsa_priv_dec(int flen,const unsigned char *from,unsigned char *to,
+                       RSA *rsa,int padding)
+{
+       int ret=0,tlen;
+       char *buf=NULL,*hptr=NULL;
+       char msg[64]="ENGINE_rsa_priv_dec";
+       if (!p_surewarehk_Rsa_Priv_Dec)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,ENGINE_R_NOT_INITIALISED);
+       }
+       /* extract ref to private key */
+       else if (!(hptr=RSA_get_ex_data(rsa, rsaHndidx)))
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,SUREWARE_R_MISSING_KEY_COMPONENTS);
+               goto err;
+       }
+       /* analyse what padding we can do into the hardware */
+       if (padding==RSA_PKCS1_PADDING)
+       {
+               /* do it one shot */
+               ret=p_surewarehk_Rsa_Priv_Dec(msg,flen,(unsigned char *)from,&tlen,to,hptr,SUREWARE_PKCS1_PAD);
+               surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,ret);
+               if (ret!=1)
+                       goto err;
+               ret=tlen;
+       }
+       else /* do with no padding into hardware */
+       {
+               ret=p_surewarehk_Rsa_Priv_Dec(msg,flen,(unsigned char *)from,&tlen,to,hptr,SUREWARE_NO_PAD);
+               surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,ret);
+               if (ret!=1)
+                       goto err;
+               /* intermediate buffer for padding */
+               if ((buf=OPENSSL_malloc(tlen)) == NULL)
+               {
+                       RSAerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,ERR_R_MALLOC_FAILURE);
+                       goto err;
+               }
+               memcpy(buf,to,tlen);/* transfert to into buf */
+               switch (padding) /* check padding in software */
+               {
+#ifndef OPENSSL_NO_SHA
+               case RSA_PKCS1_OAEP_PADDING:
+                       ret=RSA_padding_check_PKCS1_OAEP(to,tlen,(unsigned char *)buf,tlen,tlen,NULL,0);
+                       break;
+#endif
+               case RSA_SSLV23_PADDING:
+                       ret=RSA_padding_check_SSLv23(to,tlen,(unsigned char *)buf,flen,tlen);
+                       break;
+               case RSA_NO_PADDING:
+                       ret=RSA_padding_check_none(to,tlen,(unsigned char *)buf,flen,tlen);
+                       break;
+               default:
+                       RSAerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,RSA_R_UNKNOWN_PADDING_TYPE);
+                       goto err;
+               }
+               if (ret < 0)
+                       RSAerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,RSA_R_PADDING_CHECK_FAILED);
+       }
+err:
+       if (buf)
+       {
+               memset(buf,0,tlen);
+               OPENSSL_free(buf);
+       }
+       return ret;
+}
+
+/*
+* Does what OpenSSL rsa_priv_enc does.
+*/
+static int surewarehk_rsa_sign(int flen,const unsigned char *from,unsigned char *to,
+                           RSA *rsa,int padding)
+{
+       int ret=0,tlen;
+       char *hptr=NULL;
+       char msg[64]="ENGINE_rsa_sign";
+       if (!p_surewarehk_Rsa_Sign)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_ENC,ENGINE_R_NOT_INITIALISED);
+       }
+       /* extract ref to private key */
+       else if (!(hptr=RSA_get_ex_data(rsa, rsaHndidx)))
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_ENC,SUREWARE_R_MISSING_KEY_COMPONENTS);
+       }
+       else
+       {
+               switch (padding)
+               {
+               case RSA_PKCS1_PADDING: /* do it in one shot */
+                       ret=p_surewarehk_Rsa_Sign(msg,flen,(unsigned char *)from,&tlen,to,hptr,SUREWARE_PKCS1_PAD);
+                       surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_RSA_PRIV_ENC,ret);
+                       break;
+               case RSA_NO_PADDING:
+               default:
+                       RSAerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_ENC,RSA_R_UNKNOWN_PADDING_TYPE);
+               }
+       }
+       return ret==1 ? tlen : ret;
+}
+
+#endif
+
+#ifndef OPENSSL_NO_DSA
+/* DSA sign and verify */
+static DSA_SIG * surewarehk_dsa_do_sign(const unsigned char *from, int flen, DSA *dsa)
+{
+       int ret=0;
+       char *hptr=NULL;
+       DSA_SIG *psign=NULL;
+       char msg[64]="ENGINE_dsa_do_sign";
+       if (!p_surewarehk_Dsa_Sign)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_DSA_DO_SIGN,ENGINE_R_NOT_INITIALISED);
+       }
+       /* extract ref to private key */
+       else if (!(hptr=DSA_get_ex_data(dsa, dsaHndidx)))
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_DSA_DO_SIGN,SUREWARE_R_MISSING_KEY_COMPONENTS);
+       }
+       else
+       {
+               if((psign = DSA_SIG_new()) == NULL)
+               {
+                       SUREWAREerr(SUREWARE_F_SUREWAREHK_DSA_DO_SIGN,ERR_R_MALLOC_FAILURE);
+                       goto err;
+               }
+               psign->r=BN_new();
+               psign->s=BN_new();
+               bn_expand2(psign->r, 20/sizeof(BN_ULONG));
+               bn_expand2(psign->s, 20/sizeof(BN_ULONG));
+               if (!psign->r || psign->r->dmax!=20/sizeof(BN_ULONG) ||
+                       !psign->s || psign->s->dmax!=20/sizeof(BN_ULONG))
+                       goto err;
+               ret=p_surewarehk_Dsa_Sign(msg,flen,from,
+                                         (unsigned long *)psign->r->d,
+                                         (unsigned long *)psign->s->d,
+                                         hptr);
+               surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_DSA_DO_SIGN,ret);
+       }
+       psign->r->top=20/sizeof(BN_ULONG);
+       bn_fix_top(psign->r);
+       psign->s->top=20/sizeof(BN_ULONG);
+       bn_fix_top(psign->s);
+
+err:   
+       if (psign)
+       {
+               DSA_SIG_free(psign);
+               psign=NULL;
+       }
+       return psign;
+}
+#endif
+
+static int surewarehk_modexp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                            const BIGNUM *m, BN_CTX *ctx)
+{
+       int ret=0;
+       char msg[64]="ENGINE_modexp";
+       if (!p_surewarehk_Mod_Exp)
+       {
+               SUREWAREerr(SUREWARE_F_SUREWAREHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
+       }
+       else
+       {
+               bn_expand2(r,m->top);
+               if (r && r->dmax==m->top)
+               {
+                       /* do it*/
+                       ret=p_surewarehk_Mod_Exp(msg,
+                                                m->top*sizeof(BN_ULONG),
+                                                (unsigned long *)m->d,
+                                                p->top*sizeof(BN_ULONG),
+                                                (unsigned long *)p->d,
+                                                a->top*sizeof(BN_ULONG),
+                                                (unsigned long *)a->d,
+                                                (unsigned long *)r->d);
+                       surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_MOD_EXP,ret);
+                       if (ret==1)
+                       {
+                               /* normalise result */
+                               r->top=m->top;
+                               bn_fix_top(r);
+                       }
+               }
+       }
+       return ret;
+}
+#endif /* !OPENSSL_NO_HW_SureWare */
+#endif /* !OPENSSL_NO_HW */
diff --git a/engines/e_sureware_err.c b/engines/e_sureware_err.c
new file mode 100644 (file)
index 0000000..69955da
--- /dev/null
@@ -0,0 +1,150 @@
+/* hw_sureware_err.c */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+/* NOTE: this file was auto generated by the mkerr.pl script: any changes
+ * made to it will be overwritten when the script next updates this file,
+ * only reason strings will be preserved.
+ */
+
+#include <stdio.h>
+#include <openssl/err.h>
+#include "hw_sureware_err.h"
+
+/* BEGIN ERROR CODES */
+#ifndef OPENSSL_NO_ERR
+static ERR_STRING_DATA SUREWARE_str_functs[]=
+       {
+{ERR_PACK(0,SUREWARE_F_SUREWAREHK_CTRL,0),     "SUREWAREHK_CTRL"},
+{ERR_PACK(0,SUREWARE_F_SUREWAREHK_DSA_DO_SIGN,0),      "SUREWAREHK_DSA_DO_SIGN"},
+{ERR_PACK(0,SUREWARE_F_SUREWAREHK_EX_FREE,0),  "SUREWAREHK_EX_FREE"},
+{ERR_PACK(0,SUREWARE_F_SUREWAREHK_FINISH,0),   "SUREWAREHK_FINISH"},
+{ERR_PACK(0,SUREWARE_F_SUREWAREHK_INIT,0),     "SUREWAREHK_INIT"},
+{ERR_PACK(0,SUREWARE_F_SUREWAREHK_LOAD_PRIVATE_KEY,0), "SUREWAREHK_LOAD_PRIVATE_KEY"},
+{ERR_PACK(0,SUREWARE_F_SUREWAREHK_LOAD_PUBLIC_KEY,0),  "SUREWAREHK_LOAD_PUBLIC_KEY"},
+{ERR_PACK(0,SUREWARE_F_SUREWAREHK_MOD_EXP,0),  "SUREWAREHK_MOD_EXP"},
+{ERR_PACK(0,SUREWARE_F_SUREWAREHK_RAND_BYTES,0),       "SUREWAREHK_RAND_BYTES"},
+{ERR_PACK(0,SUREWARE_F_SUREWAREHK_RAND_SEED,0),        "SUREWAREHK_RAND_SEED"},
+{ERR_PACK(0,SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,0),     "SUREWAREHK_RSA_PRIV_DEC"},
+{ERR_PACK(0,SUREWARE_F_SUREWAREHK_RSA_PRIV_ENC,0),     "SUREWAREHK_RSA_PRIV_ENC"},
+{0,NULL}
+       };
+
+static ERR_STRING_DATA SUREWARE_str_reasons[]=
+       {
+{SUREWARE_R_BIO_WAS_FREED                ,"bio was freed"},
+{SUREWARE_R_MISSING_KEY_COMPONENTS       ,"missing key components"},
+{SUREWARE_R_REQUEST_FAILED               ,"request failed"},
+{SUREWARE_R_REQUEST_FALLBACK             ,"request fallback"},
+{SUREWARE_R_SIZE_TOO_LARGE_OR_TOO_SMALL  ,"size too large or too small"},
+{SUREWARE_R_UNIT_FAILURE                 ,"unit failure"},
+{0,NULL}
+       };
+
+#endif
+
+#ifdef SUREWARE_LIB_NAME
+static ERR_STRING_DATA SUREWARE_lib_name[]=
+        {
+{0     ,SUREWARE_LIB_NAME},
+{0,NULL}
+       };
+#endif
+
+
+static int SUREWARE_lib_error_code=0;
+static int SUREWARE_error_init=1;
+
+static void ERR_load_SUREWARE_strings(void)
+       {
+       if (SUREWARE_lib_error_code == 0)
+               SUREWARE_lib_error_code=ERR_get_next_error_library();
+
+       if (SUREWARE_error_init)
+               {
+               SUREWARE_error_init=0;
+#ifndef OPENSSL_NO_ERR
+               ERR_load_strings(SUREWARE_lib_error_code,SUREWARE_str_functs);
+               ERR_load_strings(SUREWARE_lib_error_code,SUREWARE_str_reasons);
+#endif
+
+#ifdef SUREWARE_LIB_NAME
+               SUREWARE_lib_name->error = ERR_PACK(SUREWARE_lib_error_code,0,0);
+               ERR_load_strings(0,SUREWARE_lib_name);
+#endif
+               }
+       }
+
+static void ERR_unload_SUREWARE_strings(void)
+       {
+       if (SUREWARE_error_init == 0)
+               {
+#ifndef OPENSSL_NO_ERR
+               ERR_unload_strings(SUREWARE_lib_error_code,SUREWARE_str_functs);
+               ERR_unload_strings(SUREWARE_lib_error_code,SUREWARE_str_reasons);
+#endif
+
+#ifdef SUREWARE_LIB_NAME
+               ERR_unload_strings(0,SUREWARE_lib_name);
+#endif
+               SUREWARE_error_init=1;
+               }
+       }
+
+static void ERR_SUREWARE_error(int function, int reason, char *file, int line)
+       {
+       if (SUREWARE_lib_error_code == 0)
+               SUREWARE_lib_error_code=ERR_get_next_error_library();
+       ERR_PUT_error(SUREWARE_lib_error_code,function,reason,file,line);
+       }
diff --git a/engines/e_sureware_err.h b/engines/e_sureware_err.h
new file mode 100644 (file)
index 0000000..bc52af5
--- /dev/null
@@ -0,0 +1,94 @@
+/* ====================================================================
+ * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#ifndef HEADER_SUREWARE_ERR_H
+#define HEADER_SUREWARE_ERR_H
+
+/* BEGIN ERROR CODES */
+/* The following lines are auto generated by the script mkerr.pl. Any changes
+ * made after this point may be overwritten when the script is next run.
+ */
+static void ERR_load_SUREWARE_strings(void);
+static void ERR_unload_SUREWARE_strings(void);
+static void ERR_SUREWARE_error(int function, int reason, char *file, int line);
+#define SUREWAREerr(f,r) ERR_SUREWARE_error((f),(r),__FILE__,__LINE__)
+
+/* Error codes for the SUREWARE functions. */
+
+/* Function codes. */
+#define SUREWARE_F_SUREWAREHK_CTRL                      100
+#define SUREWARE_F_SUREWAREHK_DSA_DO_SIGN               101
+#define SUREWARE_F_SUREWAREHK_EX_FREE                   102
+#define SUREWARE_F_SUREWAREHK_FINISH                    103
+#define SUREWARE_F_SUREWAREHK_INIT                      104
+#define SUREWARE_F_SUREWAREHK_LOAD_PRIVATE_KEY          105
+#define SUREWARE_F_SUREWAREHK_LOAD_PUBLIC_KEY           106
+#define SUREWARE_F_SUREWAREHK_MOD_EXP                   107
+#define SUREWARE_F_SUREWAREHK_RAND_BYTES                108
+#define SUREWARE_F_SUREWAREHK_RAND_SEED                         109
+#define SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC              110
+#define SUREWARE_F_SUREWAREHK_RSA_PRIV_ENC              111
+
+/* Reason codes. */
+#define SUREWARE_R_BIO_WAS_FREED                        100
+#define SUREWARE_R_MISSING_KEY_COMPONENTS               105
+#define SUREWARE_R_REQUEST_FAILED                       101
+#define SUREWARE_R_REQUEST_FALLBACK                     102
+#define SUREWARE_R_SIZE_TOO_LARGE_OR_TOO_SMALL          103
+#define SUREWARE_R_UNIT_FAILURE                                 104
+
+#ifdef  __cplusplus
+}
+#endif
+#endif
diff --git a/engines/e_ubsec.c b/engines/e_ubsec.c
new file mode 100644 (file)
index 0000000..ed8401e
--- /dev/null
@@ -0,0 +1,1059 @@
+/* crypto/engine/hw_ubsec.c */
+/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL
+ * project 2000.
+ *
+ * Cloned shamelessly by Joe Tardo. 
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2001 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    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
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <stdio.h>
+#include <openssl/crypto.h>
+#include "cryptlib.h"
+#include <openssl/dso.h>
+#include <openssl/engine.h>
+
+#ifndef OPENSSL_NO_HW
+#ifndef OPENSSL_NO_HW_UBSEC
+
+#ifdef FLAT_INC
+#include "hw_ubsec.h"
+#else
+#include "vendor_defns/hw_ubsec.h"
+#endif
+
+#define UBSEC_LIB_NAME "ubsec engine"
+#include "hw_ubsec_err.c"
+
+#define FAIL_TO_SOFTWARE -15
+
+static int ubsec_destroy(ENGINE *e);
+static int ubsec_init(ENGINE *e);
+static int ubsec_finish(ENGINE *e);
+static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
+static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+               const BIGNUM *m, BN_CTX *ctx);
+static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+                       const BIGNUM *q, const BIGNUM *dp,
+                       const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx);
+#ifndef OPENSSL_NO_RSA
+static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
+#endif
+static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
+               const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
+#ifndef OPENSSL_NO_DSA
+#ifdef NOT_USED
+static int ubsec_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
+               BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
+               BN_CTX *ctx, BN_MONT_CTX *in_mont);
+static int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
+               const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
+               BN_MONT_CTX *m_ctx);
+#endif
+static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
+static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len,
+                                DSA_SIG *sig, DSA *dsa);
+#endif
+#ifndef OPENSSL_NO_DH
+static int ubsec_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);
+static int ubsec_dh_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh);
+static int ubsec_dh_generate_key(DH *dh);
+#endif
+
+#ifdef NOT_USED
+static int ubsec_rand_bytes(unsigned char *buf, int num);
+static int ubsec_rand_status(void);
+#endif
+
+#define UBSEC_CMD_SO_PATH              ENGINE_CMD_BASE
+static const ENGINE_CMD_DEFN ubsec_cmd_defns[] = {
+       {UBSEC_CMD_SO_PATH,
+               "SO_PATH",
+               "Specifies the path to the 'ubsec' shared library",
+               ENGINE_CMD_FLAG_STRING},
+       {0, NULL, NULL, 0}
+       };
+
+#ifndef OPENSSL_NO_RSA
+/* Our internal RSA_METHOD that we provide pointers to */
+static RSA_METHOD ubsec_rsa =
+       {
+       "UBSEC RSA method",
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+       ubsec_rsa_mod_exp,
+       ubsec_mod_exp_mont,
+       NULL,
+       NULL,
+       0,
+       NULL,
+       NULL,
+       NULL
+       };
+#endif
+
+#ifndef OPENSSL_NO_DSA
+/* Our internal DSA_METHOD that we provide pointers to */
+static DSA_METHOD ubsec_dsa =
+       {
+       "UBSEC DSA method",
+       ubsec_dsa_do_sign, /* dsa_do_sign */
+       NULL, /* dsa_sign_setup */
+       ubsec_dsa_verify, /* dsa_do_verify */
+       NULL, /* ubsec_dsa_mod_exp */ /* dsa_mod_exp */
+       NULL, /* ubsec_mod_exp_dsa */ /* bn_mod_exp */
+       NULL, /* init */
+       NULL, /* finish */
+       0, /* flags */
+       NULL /* app_data */
+       };
+#endif
+
+#ifndef OPENSSL_NO_DH
+/* Our internal DH_METHOD that we provide pointers to */
+static DH_METHOD ubsec_dh =
+       {
+       "UBSEC DH method",
+       ubsec_dh_generate_key,
+       ubsec_dh_compute_key,
+       ubsec_mod_exp_dh,
+       NULL,
+       NULL,
+       0,
+       NULL
+       };
+#endif
+
+/* Constants used when creating the ENGINE */
+static const char *engine_ubsec_id = "ubsec";
+static const char *engine_ubsec_name = "UBSEC hardware engine support";
+
+/* This internal function is used by ENGINE_ubsec() 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
+#ifndef HAVE_UBSEC_DH
+       const DH_METHOD *meth3;
+#endif /* HAVE_UBSEC_DH */
+#endif
+       if(!ENGINE_set_id(e, engine_ubsec_id) ||
+                       !ENGINE_set_name(e, engine_ubsec_name) ||
+#ifndef OPENSSL_NO_RSA
+                       !ENGINE_set_RSA(e, &ubsec_rsa) ||
+#endif
+#ifndef OPENSSL_NO_DSA
+                       !ENGINE_set_DSA(e, &ubsec_dsa) ||
+#endif
+#ifndef OPENSSL_NO_DH
+                       !ENGINE_set_DH(e, &ubsec_dh) ||
+#endif
+                       !ENGINE_set_destroy_function(e, ubsec_destroy) ||
+                       !ENGINE_set_init_function(e, ubsec_init) ||
+                       !ENGINE_set_finish_function(e, ubsec_finish) ||
+                       !ENGINE_set_ctrl_function(e, ubsec_ctrl) ||
+                       !ENGINE_set_cmd_defns(e, ubsec_cmd_defns))
+               return 0;
+
+#ifndef OPENSSL_NO_RSA
+       /* We know that the "PKCS1_SSLeay()" functions hook properly
+        * to the Broadcom-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();
+       ubsec_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
+       ubsec_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
+       ubsec_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
+       ubsec_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
+#endif
+
+#ifndef OPENSSL_NO_DH
+#ifndef HAVE_UBSEC_DH
+       /* Much the same for Diffie-Hellman */
+       meth3 = DH_OpenSSL();
+       ubsec_dh.generate_key = meth3->generate_key;
+       ubsec_dh.compute_key = meth3->compute_key;
+#endif /* HAVE_UBSEC_DH */
+#endif
+
+       /* Ensure the ubsec error handling is set up */
+       ERR_load_UBSEC_strings();
+       return 1;
+       }
+
+static ENGINE *engine_ubsec(void)
+       {
+       ENGINE *ret = ENGINE_new();
+       if(!ret)
+               return NULL;
+       if(!bind_helper(ret))
+               {
+               ENGINE_free(ret);
+               return NULL;
+               }
+       return ret;
+       }
+
+void ENGINE_load_ubsec(void)
+       {
+       /* Copied from eng_[openssl|dyn].c */
+       ENGINE *toadd = engine_ubsec();
+       if(!toadd) return;
+       ENGINE_add(toadd);
+       ENGINE_free(toadd);
+       ERR_clear_error();
+       }
+
+/* This is a process-global DSO handle used for loading and unloading
+ * the UBSEC 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 *ubsec_dso = NULL;
+
+/* These are the function pointers that are (un)set when the library has
+ * successfully (un)loaded. */
+
+static t_UBSEC_ubsec_bytes_to_bits *p_UBSEC_ubsec_bytes_to_bits = NULL;
+static t_UBSEC_ubsec_bits_to_bytes *p_UBSEC_ubsec_bits_to_bytes = NULL;
+static t_UBSEC_ubsec_open *p_UBSEC_ubsec_open = NULL;
+static t_UBSEC_ubsec_close *p_UBSEC_ubsec_close = NULL;
+#ifndef OPENSSL_NO_DH
+static t_UBSEC_diffie_hellman_generate_ioctl 
+       *p_UBSEC_diffie_hellman_generate_ioctl = NULL;
+static t_UBSEC_diffie_hellman_agree_ioctl *p_UBSEC_diffie_hellman_agree_ioctl = NULL;
+#endif
+/* #ifndef OPENSSL_NO_RSA */
+static t_UBSEC_rsa_mod_exp_ioctl *p_UBSEC_rsa_mod_exp_ioctl = NULL;
+static t_UBSEC_rsa_mod_exp_crt_ioctl *p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
+/* #endif */
+#ifndef OPENSSL_NO_DSA
+static t_UBSEC_dsa_sign_ioctl *p_UBSEC_dsa_sign_ioctl = NULL;
+static t_UBSEC_dsa_verify_ioctl *p_UBSEC_dsa_verify_ioctl = NULL;
+#endif
+static t_UBSEC_math_accelerate_ioctl *p_UBSEC_math_accelerate_ioctl = NULL;
+static t_UBSEC_rng_ioctl *p_UBSEC_rng_ioctl = NULL;
+static t_UBSEC_max_key_len_ioctl *p_UBSEC_max_key_len_ioctl = NULL;
+
+static int max_key_len = 1024;  /* ??? */
+
+/* 
+ * These are the static string constants for the DSO file name and the function
+ * symbol names to bind to. 
+ */
+
+static const char *UBSEC_LIBNAME = NULL;
+static const char *get_UBSEC_LIBNAME(void)
+       {
+       if(UBSEC_LIBNAME)
+               return UBSEC_LIBNAME;
+       return "ubsec";
+       }
+static void free_UBSEC_LIBNAME(void)
+       {
+       if(UBSEC_LIBNAME)
+               OPENSSL_free((void*)UBSEC_LIBNAME);
+       UBSEC_LIBNAME = NULL;
+       }
+static long set_UBSEC_LIBNAME(const char *name)
+       {
+       free_UBSEC_LIBNAME();
+       return (((UBSEC_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
+       }
+static const char *UBSEC_F1 = "ubsec_bytes_to_bits";
+static const char *UBSEC_F2 = "ubsec_bits_to_bytes";
+static const char *UBSEC_F3 = "ubsec_open";
+static const char *UBSEC_F4 = "ubsec_close";
+#ifndef OPENSSL_NO_DH
+static const char *UBSEC_F5 = "diffie_hellman_generate_ioctl";
+static const char *UBSEC_F6 = "diffie_hellman_agree_ioctl";
+#endif
+/* #ifndef OPENSSL_NO_RSA */
+static const char *UBSEC_F7 = "rsa_mod_exp_ioctl";
+static const char *UBSEC_F8 = "rsa_mod_exp_crt_ioctl";
+/* #endif */
+#ifndef OPENSSL_NO_DSA
+static const char *UBSEC_F9 = "dsa_sign_ioctl";
+static const char *UBSEC_F10 = "dsa_verify_ioctl";
+#endif
+static const char *UBSEC_F11 = "math_accelerate_ioctl";
+static const char *UBSEC_F12 = "rng_ioctl";
+static const char *UBSEC_F13 = "ubsec_max_key_len_ioctl";
+
+/* Destructor (complements the "ENGINE_ubsec()" constructor) */
+static int ubsec_destroy(ENGINE *e)
+       {
+       free_UBSEC_LIBNAME();
+       ERR_unload_UBSEC_strings();
+       return 1;
+       }
+
+/* (de)initialisation functions. */
+static int ubsec_init(ENGINE *e)
+       {
+       t_UBSEC_ubsec_bytes_to_bits *p1;
+       t_UBSEC_ubsec_bits_to_bytes *p2;
+       t_UBSEC_ubsec_open *p3;
+       t_UBSEC_ubsec_close *p4;
+#ifndef OPENSSL_NO_DH
+       t_UBSEC_diffie_hellman_generate_ioctl *p5;
+       t_UBSEC_diffie_hellman_agree_ioctl *p6;
+#endif
+/* #ifndef OPENSSL_NO_RSA */
+       t_UBSEC_rsa_mod_exp_ioctl *p7;
+       t_UBSEC_rsa_mod_exp_crt_ioctl *p8;
+/* #endif */
+#ifndef OPENSSL_NO_DSA
+       t_UBSEC_dsa_sign_ioctl *p9;
+       t_UBSEC_dsa_verify_ioctl *p10;
+#endif
+       t_UBSEC_math_accelerate_ioctl *p11;
+       t_UBSEC_rng_ioctl *p12;
+        t_UBSEC_max_key_len_ioctl *p13;
+       int fd = 0;
+
+       if(ubsec_dso != NULL)
+               {
+               UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_ALREADY_LOADED);
+               goto err;
+               }
+       /* 
+        * Attempt to load libubsec.so/ubsec.dll/whatever. 
+        */
+       ubsec_dso = DSO_load(NULL, get_UBSEC_LIBNAME(), NULL, 0);
+       if(ubsec_dso == NULL)
+               {
+               UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE);
+               goto err;
+               }
+
+       if (
+       !(p1 = (t_UBSEC_ubsec_bytes_to_bits *) DSO_bind_func(ubsec_dso, UBSEC_F1)) ||
+       !(p2 = (t_UBSEC_ubsec_bits_to_bytes *) DSO_bind_func(ubsec_dso, UBSEC_F2)) ||
+       !(p3 = (t_UBSEC_ubsec_open *) DSO_bind_func(ubsec_dso, UBSEC_F3)) ||
+       !(p4 = (t_UBSEC_ubsec_close *) DSO_bind_func(ubsec_dso, UBSEC_F4)) ||
+#ifndef OPENSSL_NO_DH
+       !(p5 = (t_UBSEC_diffie_hellman_generate_ioctl *) 
+                               DSO_bind_func(ubsec_dso, UBSEC_F5)) ||
+       !(p6 = (t_UBSEC_diffie_hellman_agree_ioctl *) 
+                               DSO_bind_func(ubsec_dso, UBSEC_F6)) ||
+#endif
+/* #ifndef OPENSSL_NO_RSA */
+       !(p7 = (t_UBSEC_rsa_mod_exp_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F7)) ||
+       !(p8 = (t_UBSEC_rsa_mod_exp_crt_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F8)) ||
+/* #endif */
+#ifndef OPENSSL_NO_DSA
+       !(p9 = (t_UBSEC_dsa_sign_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F9)) ||
+       !(p10 = (t_UBSEC_dsa_verify_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F10)) ||
+#endif
+       !(p11 = (t_UBSEC_math_accelerate_ioctl *) 
+                               DSO_bind_func(ubsec_dso, UBSEC_F11)) ||
+       !(p12 = (t_UBSEC_rng_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F12)) ||
+        !(p13 = (t_UBSEC_max_key_len_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F13)))
+               {
+               UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE);
+               goto err;
+               }
+
+       /* Copy the pointers */
+       p_UBSEC_ubsec_bytes_to_bits = p1;
+       p_UBSEC_ubsec_bits_to_bytes = p2;
+       p_UBSEC_ubsec_open = p3;
+       p_UBSEC_ubsec_close = p4;
+#ifndef OPENSSL_NO_DH
+       p_UBSEC_diffie_hellman_generate_ioctl = p5;
+       p_UBSEC_diffie_hellman_agree_ioctl = p6;
+#endif
+#ifndef OPENSSL_NO_RSA
+       p_UBSEC_rsa_mod_exp_ioctl = p7;
+       p_UBSEC_rsa_mod_exp_crt_ioctl = p8;
+#endif
+#ifndef OPENSSL_NO_DSA
+       p_UBSEC_dsa_sign_ioctl = p9;
+       p_UBSEC_dsa_verify_ioctl = p10;
+#endif
+       p_UBSEC_math_accelerate_ioctl = p11;
+       p_UBSEC_rng_ioctl = p12;
+        p_UBSEC_max_key_len_ioctl = p13;
+
+       /* Perform an open to see if there's actually any unit running. */
+       if (((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) > 0) && (p_UBSEC_max_key_len_ioctl(fd, &max_key_len) == 0))
+       {
+          p_UBSEC_ubsec_close(fd);
+          return 1;
+       }
+       else
+       {
+         UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE);
+       }
+
+err:
+       if(ubsec_dso)
+               DSO_free(ubsec_dso);
+       p_UBSEC_ubsec_bytes_to_bits = NULL;
+       p_UBSEC_ubsec_bits_to_bytes = NULL;
+       p_UBSEC_ubsec_open = NULL;
+       p_UBSEC_ubsec_close = NULL;
+#ifndef OPENSSL_NO_DH
+       p_UBSEC_diffie_hellman_generate_ioctl = NULL;
+       p_UBSEC_diffie_hellman_agree_ioctl = NULL;
+#endif
+#ifndef OPENSSL_NO_RSA
+       p_UBSEC_rsa_mod_exp_ioctl = NULL;
+       p_UBSEC_rsa_mod_exp_crt_ioctl = NULL;
+#endif
+#ifndef OPENSSL_NO_DSA
+       p_UBSEC_dsa_sign_ioctl = NULL;
+       p_UBSEC_dsa_verify_ioctl = NULL;
+#endif
+       p_UBSEC_math_accelerate_ioctl = NULL;
+       p_UBSEC_rng_ioctl = NULL;
+        p_UBSEC_max_key_len_ioctl = NULL;
+
+       return 0;
+       }
+
+static int ubsec_finish(ENGINE *e)
+       {
+       free_UBSEC_LIBNAME();
+       if(ubsec_dso == NULL)
+               {
+               UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_NOT_LOADED);
+&nbs