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