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