hw_ncipher.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/* 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
* 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"
#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);
/* Functions to handle mutexes if have dynamic locks */
static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
#if 1 /* This is a HACK which will disappear in 0.9.8 */
/* Functions to handle mutexes if only have static locks */
static int hwcrhk_static_mutex_init(HWCryptoHook_Mutex *m,
static int hwcrhk_static_mutex_lock(HWCryptoHook_Mutex *m);
static void hwcrhk_static_mutex_unlock(HWCryptoHook_Mutex *m);
static void hwcrhk_static_mutex_destroy(HWCryptoHook_Mutex *m);
#endif
/* BIGNUM stuff */
#ifndef OPENSSL_NO_RSA
/* RSA stuff */
#endif
/* This function is aliased to mod_exp (with the mont stuff dropped). */
#ifndef OPENSSL_NO_DH
/* DH stuff */
/* This function is alised to mod_exp (with the DH and mont dropped). */
#endif
/* RAND stuff */
static int hwcrhk_rand_status(void);
/* KM stuff */
/* Interaction stuff */
static int hwcrhk_insert_card(const char *prompt_info,
const char *wrong_info,
static int hwcrhk_get_pass(const char *prompt_info,
/* The definitions for control commands specific to this engine */
#define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
"SO_PATH",
"Specifies the path to the 'hwcrhk' shared library",
"FORK_CHECK",
"Turns fork() checking on or off (boolean)",
"THREAD_LOCKING",
"Turns thread-safe locking on or off (boolean)",
"SET_USER_INTERFACE",
"Set the global user interface (internal)",
"SET_CALLBACK_DATA",
"Set the global user interface extra data (internal)",
};
#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,
NULL,
NULL,
0,
NULL,
NULL,
};
#endif
#ifndef OPENSSL_NO_DH
/* Our internal DH_METHOD that we provide pointers to */
{
"nCipher DH method",
NULL,
NULL,
NULL,
NULL,
0,
};
#endif
static RAND_METHOD hwcrhk_rand =
{
/* "nCipher RAND method", */
NULL,
NULL,
NULL,
};
/* 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 */
{
void *callback_data;
};
/* hwcryptohook.h has some typedefs that turn
struct HWCryptoHook_CallerContextValue
into HWCryptoHook_CallerContext */
{
backward compatibility! */
void *callback_data;
};
/* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
BIGNUM's, so lets define a couple of conversion macros */
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. */
/* 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
#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_init_function(e, hwcrhk_init) ||
!ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
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();
#endif
#ifndef OPENSSL_NO_DH
/* Much the same for Diffie-Hellman */
meth2 = DH_OpenSSL();
#endif
/* Ensure the hwcrhk error handling is set up */
return 1;
}
#ifndef ENGINE_DYNAMIC_SUPPORT
static ENGINE *engine_ncipher(void)
{
if(!ret)
return NULL;
if(!bind_helper(ret))
{
return NULL;
}
return ret;
}
void ENGINE_load_chil(void)
{
/* Copied from eng_[openssl|dyn].c */
if(!toadd) return;
}
#endif
/* This is a process-global DSO handle used for loading and unloading
* the HWCryptoHook library. NB: This is only set (or unset) during an
* init() or finish() call (reference counts permitting) and they're
* operating with global locks, so this should be thread-safe
* implicitly. */
static HWCryptoHook_ContextHandle hwcrhk_context = 0;
#ifndef OPENSSL_NO_RSA
#endif
/* These are the function pointers that are (un)set when the library has
* successfully (un)loaded. */
#ifndef OPENSSL_NO_RSA
#endif
#ifndef OPENSSL_NO_RSA
#endif
/* 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);
}
static const char *get_HWCRHK_LIBNAME(void)
{
if(HWCRHK_LIBNAME)
return HWCRHK_LIBNAME;
return "nfhwcrhk";
}
static long set_HWCRHK_LIBNAME(const char *name)
{
}
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 */
{
char tempbuf[1024];
cac);
if (!*hac)
return 0;
return 1;
}
/* similarly to release one. */
{
}
/* Destructor (complements the "ENGINE_ncipher()" constructor) */
static int hwcrhk_destroy(ENGINE *e)
{
return 1;
}
/* (de)initialisation functions. */
static int hwcrhk_init(ENGINE *e)
{
#ifndef OPENSSL_NO_RSA
#endif
if(hwcrhk_dso != NULL)
{
goto err;
}
/* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
if(hwcrhk_dso == NULL)
{
goto err;
}
if(!(p1 = (HWCryptoHook_Init_t *)
!(p2 = (HWCryptoHook_Finish_t *)
!(p3 = (HWCryptoHook_ModExp_t *)
#ifndef OPENSSL_NO_RSA
!(p4 = (HWCryptoHook_RSA_t *)
!(p5 = (HWCryptoHook_RSALoadKey_t *)
!(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
!(p7 = (HWCryptoHook_RSAUnloadKey_t *)
#endif
!(p8 = (HWCryptoHook_RandomBytes_t *)
!(p9 = (HWCryptoHook_ModExpCRT_t *)
{
goto err;
}
/* Copy the pointers */
p_hwcrhk_Init = p1;
#ifndef OPENSSL_NO_RSA
p_hwcrhk_RSA = p4;
#endif
/* Check if the application decided to support dynamic locks,
and if it does, use them. */
if (disable_mutex_callbacks == 0)
{
if (CRYPTO_get_dynlock_create_callback() != NULL &&
CRYPTO_get_dynlock_lock_callback() != NULL &&
{
}
else if (CRYPTO_get_locking_callback() != NULL)
{
ERR_add_error_data(1,"You HAVE to add dynamic locking callbacks via CRYPTO_set_dynlock_{create,lock,destroy}_callback()");
#if 1 /* This is a HACK which will disappear in 0.9.8 */
#else
goto err;
#endif
}
}
/* Try and get a context - if not, we may have a DSO but no
* accelerator! */
{
goto err;
}
/* Everything's fine. */
#ifndef OPENSSL_NO_RSA
if (hndidx_rsa == -1)
"nFast HWCryptoHook RSA key handle",
#endif
return 1;
err:
if(hwcrhk_dso)
hwcrhk_dso = NULL;
#ifndef OPENSSL_NO_RSA
p_hwcrhk_RSA = NULL;
#endif
return 0;
}
static int hwcrhk_finish(ENGINE *e)
{
int to_return = 1;
if(hwcrhk_dso == NULL)
{
to_return = 0;
goto err;
}
if(!DSO_free(hwcrhk_dso))
{
to_return = 0;
goto err;
}
err:
if (logstream)
hwcrhk_dso = NULL;
#ifndef OPENSSL_NO_RSA
p_hwcrhk_RSA = NULL;
#endif
return to_return;
}
{
int to_return = 1;
switch(cmd)
{
case HWCRHK_CMD_SO_PATH:
if(hwcrhk_dso)
{
return 0;
}
if(p == NULL)
{
return 0;
}
return set_HWCRHK_LIBNAME((const char *)p);
{
if (logstream)
{
}
else
}
break;
break;
break;
break;
/* this enables or disables the "SimpleForkCheck" flag used in the
* initialisation structure. */
case HWCRHK_CMD_FORK_CHECK:
if(i)
else
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. */
break;
disable_mutex_callbacks = ((i == 0) ? 0 : 1);
break;
/* The command isn't understood by this engine */
default:
to_return = 0;
break;
}
return to_return;
}
{
#ifndef OPENSSL_NO_RSA
#endif
#ifndef OPENSSL_NO_RSA
HWCryptoHook_MPI e, n;
#endif
#if !defined(OPENSSL_NO_RSA)
char tempbuf[1024];
#endif
#if !defined(OPENSSL_NO_RSA)
#endif
if(!hwcrhk_context)
{
goto err;
}
#ifndef OPENSSL_NO_RSA
if (!hptr)
{
goto err;
}
{
goto err;
}
if (!*hptr)
{
goto err;
}
#endif
#ifndef OPENSSL_NO_RSA
{
goto err;
}
{
goto err;
}
bn_fix_top(rtmp->e);
bn_fix_top(rtmp->n);
res = EVP_PKEY_new();
#endif
if (!res)
return res;
err:
if (res)
#ifndef OPENSSL_NO_RSA
if (rtmp)
#endif
return NULL;
}
{
#ifndef OPENSSL_NO_RSA
#endif
if (res)
{
#ifndef OPENSSL_NO_RSA
case EVP_PKEY_RSA:
{
}
break;
#endif
default:
goto err;
}
return res;
err:
if (res)
return NULL;
}
/* A little mod_exp */
{
char tempbuf[1024];
/* 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. */
to_return = 0; /* expect failure */
if(!hwcrhk_context)
{
goto err;
}
/* Prepare the params */
/* Perform the operation */
/* Convert the response */
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)
{
}
else
{
}
goto err;
}
to_return = 1;
err:
return to_return;
}
#ifndef OPENSSL_NO_RSA
{
char tempbuf[1024];
if(!hwcrhk_context)
{
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. */
!= NULL)
{
if(!rsa->n)
{
goto err;
}
/* Prepare the params */
/* Perform the operation */
/* Convert the response */
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)
{
}
else
{
}
goto err;
}
}
else
{
{
goto err;
}
/* Prepare the params */
/* Perform the operation */
/* Convert the response */
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)
{
}
else
{
}
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). */
{
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). */
{
return hwcrhk_mod_exp(r, a, p, m, ctx);
}
#endif
/* Random bytes are good */
{
char tempbuf[1024];
int to_return = 0; /* assume failure */
int ret;
if(!hwcrhk_context)
{
goto err;
}
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)
{
}
else
{
}
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 */
{
char tempbuf[1024];
#ifndef OPENSSL_NO_RSA
#endif
#if !defined(OPENSSL_NO_RSA)
int ret;
#endif
#ifndef OPENSSL_NO_RSA
if(hptr)
{
}
#endif
}
/* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
* these just wrap the POSIX functions and add some logging.
*/
{
return 1; /* failure */
return 0; /* success */
}
{
return 0;
}
{
}
{
}
/* Mutex upcalls to use if the application does not support dynamic locks */
static int hwcrhk_static_mutex_init(HWCryptoHook_Mutex *m,
{
return 0;
}
static int hwcrhk_static_mutex_lock(HWCryptoHook_Mutex *m)
{
return 0;
}
static void hwcrhk_static_mutex_unlock(HWCryptoHook_Mutex *m)
{
}
static void hwcrhk_static_mutex_destroy(HWCryptoHook_Mutex *m)
{
}
static int hwcrhk_get_pass(const char *prompt_info,
{
void *callback_data = NULL;
if (cactx)
{
if (cactx->password_callback)
if (cactx->callback_data)
}
if (ppctx)
{
{
}
if (ppctx->callback_data)
}
{
return -1;
}
if (ui_method)
{
if (ui)
{
int ok;
"pass phrase", prompt_info);
if (ok >= 0)
do
{
}
if (ok >= 0)
}
}
else
{
}
if(!*len_io)
return -1;
return 0;
}
static int hwcrhk_insert_card(const char *prompt_info,
const char *wrong_info,
{
int ok = -1;
void *callback_data = NULL;
if (cactx)
{
if (cactx->callback_data)
}
if (ppctx)
{
if (ppctx->callback_data)
}
{
return -1;
}
if (ui)
{
char answer;
if (wrong_info)
"Current card: \"%s\"\n", wrong_info);
if (ok >= 0 && prompt_info)
{
"Insert card \"%s\"", prompt_info);
"\n then hit <enter> or C<enter> to cancel\n",
}
if (ok >= 0)
ok = 1;
else if (ok < 0)
ok = -1;
else
ok = 0;
}
return ok;
}
{
if (logstr)
if (lstream)
{
}
}
/* This stuff is needed if this ENGINE is being compiled into a self-contained
* shared-library. */
#ifdef ENGINE_DYNAMIC_SUPPORT
{
return 0;
if(!bind_helper(e))
return 0;
return 1;
}
#endif /* ENGINE_DYNAMIC_SUPPORT */
#endif /* !OPENSSL_NO_HW_NCIPHER */
#endif /* !OPENSSL_NO_HW */