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