1160814Ssimon/* Written by Corinne Dive-Reclus(cdive@baltimore.com)
2160814Ssimon*
3160814Ssimon*
4160814Ssimon* Redistribution and use in source and binary forms, with or without
5160814Ssimon* modification, are permitted provided that the following conditions
6160814Ssimon* are met:
7160814Ssimon*
8160814Ssimon* 1. Redistributions of source code must retain the above copyright
9160814Ssimon*    notice, this list of conditions and the following disclaimer.
10160814Ssimon*
11160814Ssimon* 2. Redistributions in binary form must reproduce the above copyright
12160814Ssimon*    notice, this list of conditions and the following disclaimer in
13160814Ssimon*    the documentation and/or other materials provided with the
14160814Ssimon*    distribution.
15160814Ssimon*
16160814Ssimon* 3. All advertising materials mentioning features or use of this
17160814Ssimon*    software must display the following acknowledgment:
18160814Ssimon*    "This product includes software developed by the OpenSSL Project
19160814Ssimon*    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
20160814Ssimon*
21160814Ssimon* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22160814Ssimon*    endorse or promote products derived from this software without
23160814Ssimon*    prior written permission. For written permission, please contact
24160814Ssimon*    licensing@OpenSSL.org.
25160814Ssimon*
26160814Ssimon* 5. Products derived from this software may not be called "OpenSSL"
27160814Ssimon*    nor may "OpenSSL" appear in their names without prior written
28160814Ssimon*    permission of the OpenSSL Project.
29160814Ssimon*
30160814Ssimon* 6. Redistributions of any form whatsoever must retain the following
31160814Ssimon*    acknowledgment:
32160814Ssimon*    "This product includes software developed by the OpenSSL Project
33160814Ssimon*    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
34160814Ssimon*
35160814Ssimon* Written by Corinne Dive-Reclus(cdive@baltimore.com)
36160814Ssimon*
37160814Ssimon* Copyright@2001 Baltimore Technologies Ltd.
38160814Ssimon* All right Reserved.
39160814Ssimon*																								*
40160814Ssimon*		THIS FILE IS PROVIDED BY BALTIMORE TECHNOLOGIES ``AS IS'' AND																			*
41160814Ssimon*		ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE					*
42160814Ssimon*		IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE				*
43160814Ssimon*		ARE DISCLAIMED.  IN NO EVENT SHALL BALTIMORE TECHNOLOGIES BE LIABLE						*
44160814Ssimon*		FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL				*
45160814Ssimon*		DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS					*
46160814Ssimon*		OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)					*
47160814Ssimon*		HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT				*
48160814Ssimon*		LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY				*
49160814Ssimon*		OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF					*
50160814Ssimon*		SUCH DAMAGE.																			*
51160814Ssimon====================================================================*/
52160814Ssimon
53160814Ssimon#include <stdio.h>
54160814Ssimon#include <string.h>
55160814Ssimon#include <openssl/crypto.h>
56160814Ssimon#include <openssl/pem.h>
57160814Ssimon#include <openssl/dso.h>
58160814Ssimon#include <openssl/engine.h>
59160814Ssimon#include <openssl/rand.h>
60160814Ssimon#ifndef OPENSSL_NO_RSA
61160814Ssimon#include <openssl/rsa.h>
62160814Ssimon#endif
63160814Ssimon#ifndef OPENSSL_NO_DSA
64160814Ssimon#include <openssl/dsa.h>
65160814Ssimon#endif
66160814Ssimon#ifndef OPENSSL_NO_DH
67160814Ssimon#include <openssl/dh.h>
68160814Ssimon#endif
69160814Ssimon#include <openssl/bn.h>
70160814Ssimon
71160814Ssimon#ifndef OPENSSL_NO_HW
72160814Ssimon#ifndef OPENSSL_NO_HW_SUREWARE
73160814Ssimon
74160814Ssimon#ifdef FLAT_INC
75160814Ssimon#include "sureware.h"
76160814Ssimon#else
77160814Ssimon#include "vendor_defns/sureware.h"
78160814Ssimon#endif
79160814Ssimon
80160814Ssimon#define SUREWARE_LIB_NAME "sureware engine"
81160814Ssimon#include "e_sureware_err.c"
82160814Ssimon
83160814Ssimonstatic int surewarehk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
84160814Ssimonstatic int surewarehk_destroy(ENGINE *e);
85160814Ssimonstatic int surewarehk_init(ENGINE *e);
86160814Ssimonstatic int surewarehk_finish(ENGINE *e);
87160814Ssimonstatic int surewarehk_modexp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
88160814Ssimon	const BIGNUM *m, BN_CTX *ctx);
89160814Ssimon
90160814Ssimon/* RSA stuff */
91160814Ssimon#ifndef OPENSSL_NO_RSA
92160814Ssimonstatic int surewarehk_rsa_priv_dec(int flen,const unsigned char *from,unsigned char *to,
93160814Ssimon			RSA *rsa,int padding);
94160814Ssimonstatic int surewarehk_rsa_sign(int flen,const unsigned char *from,unsigned char *to,
95160814Ssimon			    RSA *rsa,int padding);
96160814Ssimon#endif
97160814Ssimon
98160814Ssimon/* RAND stuff */
99160814Ssimonstatic int surewarehk_rand_bytes(unsigned char *buf, int num);
100160814Ssimonstatic void surewarehk_rand_seed(const void *buf, int num);
101160814Ssimonstatic void surewarehk_rand_add(const void *buf, int num, double entropy);
102160814Ssimon
103160814Ssimon/* KM stuff */
104160814Ssimonstatic EVP_PKEY *surewarehk_load_privkey(ENGINE *e, const char *key_id,
105160814Ssimon	UI_METHOD *ui_method, void *callback_data);
106160814Ssimonstatic EVP_PKEY *surewarehk_load_pubkey(ENGINE *e, const char *key_id,
107160814Ssimon	UI_METHOD *ui_method, void *callback_data);
108160814Ssimonstatic void surewarehk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
109160814Ssimon	int idx,long argl, void *argp);
110160814Ssimon#if 0
111160814Ssimonstatic void surewarehk_dh_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
112160814Ssimon	int idx,long argl, void *argp);
113160814Ssimon#endif
114160814Ssimon
115160814Ssimon#ifndef OPENSSL_NO_RSA
116160814Ssimon/* This function is aliased to mod_exp (with the mont stuff dropped). */
117160814Ssimonstatic int surewarehk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
118160814Ssimon		const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
119160814Ssimon{
120160814Ssimon	return surewarehk_modexp(r, a, p, m, ctx);
121160814Ssimon}
122160814Ssimon
123160814Ssimon/* Our internal RSA_METHOD that we provide pointers to */
124160814Ssimonstatic RSA_METHOD surewarehk_rsa =
125160814Ssimon	{
126160814Ssimon	"SureWare RSA method",
127160814Ssimon	NULL, /* pub_enc*/
128160814Ssimon	NULL, /* pub_dec*/
129160814Ssimon	surewarehk_rsa_sign, /* our rsa_sign is OpenSSL priv_enc*/
130160814Ssimon	surewarehk_rsa_priv_dec, /* priv_dec*/
131160814Ssimon	NULL, /*mod_exp*/
132160814Ssimon	surewarehk_mod_exp_mont, /*mod_exp_mongomery*/
133160814Ssimon	NULL, /* init*/
134160814Ssimon	NULL, /* finish*/
135160814Ssimon	0,	/* RSA flag*/
136160814Ssimon	NULL,
137160814Ssimon	NULL, /* OpenSSL sign*/
138160814Ssimon	NULL, /* OpenSSL verify*/
139160814Ssimon	NULL  /* keygen */
140160814Ssimon	};
141160814Ssimon#endif
142160814Ssimon
143160814Ssimon#ifndef OPENSSL_NO_DH
144160814Ssimon/* Our internal DH_METHOD that we provide pointers to */
145160814Ssimon/* This function is aliased to mod_exp (with the dh and mont dropped). */
146160814Ssimonstatic int surewarehk_modexp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
147160814Ssimon	const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
148160814Ssimon{
149160814Ssimon	return surewarehk_modexp(r, a, p, m, ctx);
150160814Ssimon}
151160814Ssimon
152160814Ssimonstatic DH_METHOD surewarehk_dh =
153160814Ssimon	{
154160814Ssimon	"SureWare DH method",
155160814Ssimon	NULL,/*gen_key*/
156160814Ssimon	NULL,/*agree,*/
157160814Ssimon	surewarehk_modexp_dh, /*dh mod exp*/
158160814Ssimon	NULL, /* init*/
159160814Ssimon	NULL, /* finish*/
160160814Ssimon	0,    /* flags*/
161160814Ssimon	NULL,
162160814Ssimon	NULL
163160814Ssimon	};
164160814Ssimon#endif
165160814Ssimon
166160814Ssimonstatic RAND_METHOD surewarehk_rand =
167160814Ssimon	{
168160814Ssimon	/* "SureWare RAND method", */
169160814Ssimon	surewarehk_rand_seed,
170160814Ssimon	surewarehk_rand_bytes,
171160814Ssimon	NULL,/*cleanup*/
172160814Ssimon	surewarehk_rand_add,
173160814Ssimon	surewarehk_rand_bytes,
174160814Ssimon	NULL,/*rand_status*/
175160814Ssimon	};
176160814Ssimon
177160814Ssimon#ifndef OPENSSL_NO_DSA
178160814Ssimon/* DSA stuff */
179160814Ssimonstatic	DSA_SIG * surewarehk_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
180160814Ssimonstatic int surewarehk_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
181160814Ssimon		BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
182160814Ssimon		BN_CTX *ctx, BN_MONT_CTX *in_mont)
183160814Ssimon{
184160814Ssimon	BIGNUM t;
185160814Ssimon	int to_return = 0;
186160814Ssimon	BN_init(&t);
187160814Ssimon	/* let rr = a1 ^ p1 mod m */
188160814Ssimon	if (!surewarehk_modexp(rr,a1,p1,m,ctx)) goto end;
189160814Ssimon	/* let t = a2 ^ p2 mod m */
190160814Ssimon	if (!surewarehk_modexp(&t,a2,p2,m,ctx)) goto end;
191160814Ssimon	/* let rr = rr * t mod m */
192160814Ssimon	if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end;
193160814Ssimon	to_return = 1;
194160814Ssimonend:
195160814Ssimon	BN_free(&t);
196160814Ssimon	return to_return;
197160814Ssimon}
198160814Ssimon
199160814Ssimonstatic DSA_METHOD surewarehk_dsa =
200160814Ssimon	{
201160814Ssimon	 "SureWare DSA method",
202160814Ssimon	surewarehk_dsa_do_sign,
203160814Ssimon	NULL,/*sign setup*/
204160814Ssimon	NULL,/*verify,*/
205160814Ssimon	surewarehk_dsa_mod_exp,/*mod exp*/
206160814Ssimon	NULL,/*bn mod exp*/
207160814Ssimon	NULL, /*init*/
208160814Ssimon	NULL,/*finish*/
209160814Ssimon	0,
210160814Ssimon	NULL,
211160814Ssimon	NULL,
212160814Ssimon	NULL
213160814Ssimon	};
214160814Ssimon#endif
215160814Ssimon
216160814Ssimonstatic const char *engine_sureware_id = "sureware";
217160814Ssimonstatic const char *engine_sureware_name = "SureWare hardware engine support";
218160814Ssimon
219160814Ssimon/* Now, to our own code */
220160814Ssimon
221160814Ssimon/* As this is only ever called once, there's no need for locking
222160814Ssimon * (indeed - the lock will already be held by our caller!!!) */
223160814Ssimonstatic int bind_sureware(ENGINE *e)
224160814Ssimon{
225160814Ssimon#ifndef OPENSSL_NO_RSA
226160814Ssimon	const RSA_METHOD *meth1;
227160814Ssimon#endif
228160814Ssimon#ifndef OPENSSL_NO_DSA
229160814Ssimon	const DSA_METHOD *meth2;
230160814Ssimon#endif
231160814Ssimon#ifndef OPENSSL_NO_DH
232160814Ssimon	const DH_METHOD *meth3;
233160814Ssimon#endif
234160814Ssimon
235160814Ssimon	if(!ENGINE_set_id(e, engine_sureware_id) ||
236160814Ssimon	   !ENGINE_set_name(e, engine_sureware_name) ||
237160814Ssimon#ifndef OPENSSL_NO_RSA
238160814Ssimon	   !ENGINE_set_RSA(e, &surewarehk_rsa) ||
239160814Ssimon#endif
240160814Ssimon#ifndef OPENSSL_NO_DSA
241160814Ssimon	   !ENGINE_set_DSA(e, &surewarehk_dsa) ||
242160814Ssimon#endif
243160814Ssimon#ifndef OPENSSL_NO_DH
244160814Ssimon	   !ENGINE_set_DH(e, &surewarehk_dh) ||
245160814Ssimon#endif
246160814Ssimon	   !ENGINE_set_RAND(e, &surewarehk_rand) ||
247160814Ssimon	   !ENGINE_set_destroy_function(e, surewarehk_destroy) ||
248160814Ssimon	   !ENGINE_set_init_function(e, surewarehk_init) ||
249160814Ssimon	   !ENGINE_set_finish_function(e, surewarehk_finish) ||
250160814Ssimon	   !ENGINE_set_ctrl_function(e, surewarehk_ctrl) ||
251160814Ssimon	   !ENGINE_set_load_privkey_function(e, surewarehk_load_privkey) ||
252160814Ssimon	   !ENGINE_set_load_pubkey_function(e, surewarehk_load_pubkey))
253160814Ssimon	  return 0;
254160814Ssimon
255160814Ssimon#ifndef OPENSSL_NO_RSA
256160814Ssimon	/* We know that the "PKCS1_SSLeay()" functions hook properly
257160814Ssimon	 * to the cswift-specific mod_exp and mod_exp_crt so we use
258160814Ssimon	 * those functions. NB: We don't use ENGINE_openssl() or
259160814Ssimon	 * anything "more generic" because something like the RSAref
260160814Ssimon	 * code may not hook properly, and if you own one of these
261160814Ssimon	 * cards then you have the right to do RSA operations on it
262160814Ssimon	 * anyway! */
263160814Ssimon	meth1 = RSA_PKCS1_SSLeay();
264160814Ssimon	if (meth1)
265160814Ssimon	{
266160814Ssimon		surewarehk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
267160814Ssimon		surewarehk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
268160814Ssimon	}
269160814Ssimon#endif
270160814Ssimon
271160814Ssimon#ifndef OPENSSL_NO_DSA
272160814Ssimon	/* Use the DSA_OpenSSL() method and just hook the mod_exp-ish
273160814Ssimon	 * bits. */
274160814Ssimon	meth2 = DSA_OpenSSL();
275160814Ssimon	if (meth2)
276160814Ssimon	{
277160814Ssimon		surewarehk_dsa.dsa_do_verify = meth2->dsa_do_verify;
278160814Ssimon	}
279160814Ssimon#endif
280160814Ssimon
281160814Ssimon#ifndef OPENSSL_NO_DH
282160814Ssimon	/* Much the same for Diffie-Hellman */
283160814Ssimon	meth3 = DH_OpenSSL();
284160814Ssimon	if (meth3)
285160814Ssimon	{
286160814Ssimon		surewarehk_dh.generate_key = meth3->generate_key;
287160814Ssimon		surewarehk_dh.compute_key = meth3->compute_key;
288160814Ssimon	}
289160814Ssimon#endif
290160814Ssimon
291160814Ssimon	/* Ensure the sureware error handling is set up */
292160814Ssimon	ERR_load_SUREWARE_strings();
293160814Ssimon	return 1;
294160814Ssimon}
295160814Ssimon
296160814Ssimon#ifndef OPENSSL_NO_DYNAMIC_ENGINE
297160814Ssimonstatic int bind_helper(ENGINE *e, const char *id)
298160814Ssimon	{
299160814Ssimon	if(id && (strcmp(id, engine_sureware_id) != 0))
300160814Ssimon		return 0;
301160814Ssimon	if(!bind_sureware(e))
302160814Ssimon		return 0;
303160814Ssimon	return 1;
304160814Ssimon	}
305160814SsimonIMPLEMENT_DYNAMIC_CHECK_FN()
306160814SsimonIMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
307160814Ssimon#else
308160814Ssimonstatic ENGINE *engine_sureware(void)
309160814Ssimon	{
310160814Ssimon	ENGINE *ret = ENGINE_new();
311160814Ssimon	if(!ret)
312160814Ssimon		return NULL;
313160814Ssimon	if(!bind_sureware(ret))
314160814Ssimon		{
315160814Ssimon		ENGINE_free(ret);
316160814Ssimon		return NULL;
317160814Ssimon		}
318160814Ssimon	return ret;
319160814Ssimon	}
320160814Ssimon
321160814Ssimonvoid ENGINE_load_sureware(void)
322160814Ssimon	{
323160814Ssimon	/* Copied from eng_[openssl|dyn].c */
324160814Ssimon	ENGINE *toadd = engine_sureware();
325160814Ssimon	if(!toadd) return;
326160814Ssimon	ENGINE_add(toadd);
327160814Ssimon	ENGINE_free(toadd);
328160814Ssimon	ERR_clear_error();
329160814Ssimon	}
330160814Ssimon#endif
331160814Ssimon
332160814Ssimon/* This is a process-global DSO handle used for loading and unloading
333160814Ssimon * the SureWareHook library. NB: This is only set (or unset) during an
334160814Ssimon * init() or finish() call (reference counts permitting) and they're
335160814Ssimon * operating with global locks, so this should be thread-safe
336160814Ssimon * implicitly. */
337160814Ssimonstatic DSO *surewarehk_dso = NULL;
338160814Ssimon#ifndef OPENSSL_NO_RSA
339160814Ssimonstatic int rsaHndidx = -1;	/* Index for KM handle.  Not really used yet. */
340160814Ssimon#endif
341160814Ssimon#ifndef OPENSSL_NO_DSA
342160814Ssimonstatic int dsaHndidx = -1;	/* Index for KM handle.  Not really used yet. */
343160814Ssimon#endif
344160814Ssimon
345160814Ssimon/* These are the function pointers that are (un)set when the library has
346160814Ssimon * successfully (un)loaded. */
347160814Ssimonstatic SureWareHook_Init_t *p_surewarehk_Init = NULL;
348160814Ssimonstatic SureWareHook_Finish_t *p_surewarehk_Finish = NULL;
349160814Ssimonstatic SureWareHook_Rand_Bytes_t *p_surewarehk_Rand_Bytes = NULL;
350160814Ssimonstatic SureWareHook_Rand_Seed_t *p_surewarehk_Rand_Seed = NULL;
351160814Ssimonstatic SureWareHook_Load_Privkey_t *p_surewarehk_Load_Privkey = NULL;
352160814Ssimonstatic SureWareHook_Info_Pubkey_t *p_surewarehk_Info_Pubkey = NULL;
353160814Ssimonstatic SureWareHook_Load_Rsa_Pubkey_t *p_surewarehk_Load_Rsa_Pubkey = NULL;
354160814Ssimonstatic SureWareHook_Load_Dsa_Pubkey_t *p_surewarehk_Load_Dsa_Pubkey = NULL;
355160814Ssimonstatic SureWareHook_Free_t *p_surewarehk_Free=NULL;
356160814Ssimonstatic SureWareHook_Rsa_Priv_Dec_t *p_surewarehk_Rsa_Priv_Dec=NULL;
357160814Ssimonstatic SureWareHook_Rsa_Sign_t *p_surewarehk_Rsa_Sign=NULL;
358160814Ssimonstatic SureWareHook_Dsa_Sign_t *p_surewarehk_Dsa_Sign=NULL;
359160814Ssimonstatic SureWareHook_Mod_Exp_t *p_surewarehk_Mod_Exp=NULL;
360160814Ssimon
361160814Ssimon/* Used in the DSO operations. */
362160814Ssimonstatic const char *surewarehk_LIBNAME = "SureWareHook";
363160814Ssimonstatic const char *n_surewarehk_Init = "SureWareHook_Init";
364160814Ssimonstatic const char *n_surewarehk_Finish = "SureWareHook_Finish";
365160814Ssimonstatic const char *n_surewarehk_Rand_Bytes="SureWareHook_Rand_Bytes";
366160814Ssimonstatic const char *n_surewarehk_Rand_Seed="SureWareHook_Rand_Seed";
367160814Ssimonstatic const char *n_surewarehk_Load_Privkey="SureWareHook_Load_Privkey";
368160814Ssimonstatic const char *n_surewarehk_Info_Pubkey="SureWareHook_Info_Pubkey";
369160814Ssimonstatic const char *n_surewarehk_Load_Rsa_Pubkey="SureWareHook_Load_Rsa_Pubkey";
370160814Ssimonstatic const char *n_surewarehk_Load_Dsa_Pubkey="SureWareHook_Load_Dsa_Pubkey";
371160814Ssimonstatic const char *n_surewarehk_Free="SureWareHook_Free";
372160814Ssimonstatic const char *n_surewarehk_Rsa_Priv_Dec="SureWareHook_Rsa_Priv_Dec";
373160814Ssimonstatic const char *n_surewarehk_Rsa_Sign="SureWareHook_Rsa_Sign";
374160814Ssimonstatic const char *n_surewarehk_Dsa_Sign="SureWareHook_Dsa_Sign";
375160814Ssimonstatic const char *n_surewarehk_Mod_Exp="SureWareHook_Mod_Exp";
376160814Ssimonstatic BIO *logstream = NULL;
377160814Ssimon
378160814Ssimon/* SureWareHook library functions and mechanics - these are used by the
379160814Ssimon * higher-level functions further down. NB: As and where there's no
380160814Ssimon * error checking, take a look lower down where these functions are
381160814Ssimon * called, the checking and error handling is probably down there.
382160814Ssimon*/
383160814Ssimonstatic int threadsafe=1;
384160814Ssimonstatic int surewarehk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
385160814Ssimon{
386160814Ssimon	int to_return = 1;
387160814Ssimon
388160814Ssimon	switch(cmd)
389160814Ssimon	{
390160814Ssimon		case ENGINE_CTRL_SET_LOGSTREAM:
391160814Ssimon		{
392160814Ssimon			BIO *bio = (BIO *)p;
393160814Ssimon			CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
394160814Ssimon			if (logstream)
395160814Ssimon			{
396160814Ssimon				BIO_free(logstream);
397160814Ssimon				logstream = NULL;
398160814Ssimon			}
399160814Ssimon			if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
400160814Ssimon				logstream = bio;
401160814Ssimon			else
402160814Ssimon				SUREWAREerr(SUREWARE_F_SUREWAREHK_CTRL,SUREWARE_R_BIO_WAS_FREED);
403160814Ssimon		}
404160814Ssimon		CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
405160814Ssimon		break;
406160814Ssimon	/* This will prevent the initialisation function from "installing"
407160814Ssimon	 * the mutex-handling callbacks, even if they are available from
408160814Ssimon	 * within the library (or were provided to the library from the
409160814Ssimon	 * calling application). This is to remove any baggage for
410160814Ssimon	 * applications not using multithreading. */
411160814Ssimon	case ENGINE_CTRL_CHIL_NO_LOCKING:
412160814Ssimon		CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
413160814Ssimon		threadsafe = 0;
414160814Ssimon		CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
415160814Ssimon		break;
416160814Ssimon
417160814Ssimon	/* The command isn't understood by this engine */
418160814Ssimon	default:
419160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_CTRL,
420160814Ssimon			ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
421160814Ssimon		to_return = 0;
422160814Ssimon		break;
423160814Ssimon		}
424160814Ssimon
425160814Ssimon	return to_return;
426160814Ssimon}
427160814Ssimon
428160814Ssimon/* Destructor (complements the "ENGINE_surewarehk()" constructor) */
429160814Ssimonstatic int surewarehk_destroy(ENGINE *e)
430160814Ssimon{
431160814Ssimon	ERR_unload_SUREWARE_strings();
432160814Ssimon	return 1;
433160814Ssimon}
434160814Ssimon
435160814Ssimon/* (de)initialisation functions. */
436160814Ssimonstatic int surewarehk_init(ENGINE *e)
437160814Ssimon{
438160814Ssimon	char msg[64]="ENGINE_init";
439160814Ssimon	SureWareHook_Init_t *p1=NULL;
440160814Ssimon	SureWareHook_Finish_t *p2=NULL;
441160814Ssimon	SureWareHook_Rand_Bytes_t *p3=NULL;
442160814Ssimon	SureWareHook_Rand_Seed_t *p4=NULL;
443160814Ssimon	SureWareHook_Load_Privkey_t *p5=NULL;
444160814Ssimon	SureWareHook_Load_Rsa_Pubkey_t *p6=NULL;
445160814Ssimon	SureWareHook_Free_t *p7=NULL;
446160814Ssimon	SureWareHook_Rsa_Priv_Dec_t *p8=NULL;
447160814Ssimon	SureWareHook_Rsa_Sign_t *p9=NULL;
448160814Ssimon	SureWareHook_Dsa_Sign_t *p12=NULL;
449160814Ssimon	SureWareHook_Info_Pubkey_t *p13=NULL;
450160814Ssimon	SureWareHook_Load_Dsa_Pubkey_t *p14=NULL;
451160814Ssimon	SureWareHook_Mod_Exp_t *p15=NULL;
452160814Ssimon
453160814Ssimon	if(surewarehk_dso != NULL)
454160814Ssimon	{
455160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_INIT,ENGINE_R_ALREADY_LOADED);
456160814Ssimon		goto err;
457160814Ssimon	}
458160814Ssimon	/* Attempt to load libsurewarehk.so/surewarehk.dll/whatever. */
459160814Ssimon	surewarehk_dso = DSO_load(NULL, surewarehk_LIBNAME, NULL, 0);
460160814Ssimon	if(surewarehk_dso == NULL)
461160814Ssimon	{
462160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_INIT,ENGINE_R_DSO_FAILURE);
463160814Ssimon		goto err;
464160814Ssimon	}
465160814Ssimon	if(!(p1=(SureWareHook_Init_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Init)) ||
466160814Ssimon	   !(p2=(SureWareHook_Finish_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Finish)) ||
467160814Ssimon	   !(p3=(SureWareHook_Rand_Bytes_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Rand_Bytes)) ||
468160814Ssimon	   !(p4=(SureWareHook_Rand_Seed_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Rand_Seed)) ||
469160814Ssimon	   !(p5=(SureWareHook_Load_Privkey_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Load_Privkey)) ||
470160814Ssimon	   !(p6=(SureWareHook_Load_Rsa_Pubkey_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Load_Rsa_Pubkey)) ||
471160814Ssimon	   !(p7=(SureWareHook_Free_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Free)) ||
472160814Ssimon	   !(p8=(SureWareHook_Rsa_Priv_Dec_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Rsa_Priv_Dec)) ||
473160814Ssimon	   !(p9=(SureWareHook_Rsa_Sign_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Rsa_Sign)) ||
474160814Ssimon	   !(p12=(SureWareHook_Dsa_Sign_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Dsa_Sign)) ||
475160814Ssimon	   !(p13=(SureWareHook_Info_Pubkey_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Info_Pubkey)) ||
476160814Ssimon	   !(p14=(SureWareHook_Load_Dsa_Pubkey_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Load_Dsa_Pubkey)) ||
477160814Ssimon	   !(p15=(SureWareHook_Mod_Exp_t*)DSO_bind_func(surewarehk_dso, n_surewarehk_Mod_Exp)))
478160814Ssimon	{
479160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_INIT,ENGINE_R_DSO_FAILURE);
480160814Ssimon		goto err;
481160814Ssimon	}
482160814Ssimon	/* Copy the pointers */
483160814Ssimon	p_surewarehk_Init = p1;
484160814Ssimon	p_surewarehk_Finish = p2;
485160814Ssimon	p_surewarehk_Rand_Bytes = p3;
486160814Ssimon	p_surewarehk_Rand_Seed = p4;
487160814Ssimon	p_surewarehk_Load_Privkey = p5;
488160814Ssimon	p_surewarehk_Load_Rsa_Pubkey = p6;
489160814Ssimon	p_surewarehk_Free = p7;
490160814Ssimon	p_surewarehk_Rsa_Priv_Dec = p8;
491160814Ssimon	p_surewarehk_Rsa_Sign = p9;
492160814Ssimon	p_surewarehk_Dsa_Sign = p12;
493160814Ssimon	p_surewarehk_Info_Pubkey = p13;
494160814Ssimon	p_surewarehk_Load_Dsa_Pubkey = p14;
495160814Ssimon	p_surewarehk_Mod_Exp = p15;
496160814Ssimon	/* Contact the hardware and initialises it. */
497160814Ssimon	if(p_surewarehk_Init(msg,threadsafe)==SUREWAREHOOK_ERROR_UNIT_FAILURE)
498160814Ssimon	{
499160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_INIT,SUREWARE_R_UNIT_FAILURE);
500160814Ssimon		goto err;
501160814Ssimon	}
502160814Ssimon	if(p_surewarehk_Init(msg,threadsafe)==SUREWAREHOOK_ERROR_UNIT_FAILURE)
503160814Ssimon	{
504160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_INIT,SUREWARE_R_UNIT_FAILURE);
505160814Ssimon		goto err;
506160814Ssimon	}
507160814Ssimon	/* try to load the default private key, if failed does not return a failure but
508160814Ssimon           wait for an explicit ENGINE_load_privakey */
509160814Ssimon	surewarehk_load_privkey(e,NULL,NULL,NULL);
510160814Ssimon
511160814Ssimon	/* Everything's fine. */
512160814Ssimon#ifndef OPENSSL_NO_RSA
513160814Ssimon	if (rsaHndidx == -1)
514160814Ssimon		rsaHndidx = RSA_get_ex_new_index(0,
515160814Ssimon						"SureWareHook RSA key handle",
516160814Ssimon						NULL, NULL, surewarehk_ex_free);
517160814Ssimon#endif
518160814Ssimon#ifndef OPENSSL_NO_DSA
519160814Ssimon	if (dsaHndidx == -1)
520160814Ssimon		dsaHndidx = DSA_get_ex_new_index(0,
521160814Ssimon						"SureWareHook DSA key handle",
522160814Ssimon						NULL, NULL, surewarehk_ex_free);
523160814Ssimon#endif
524160814Ssimon
525160814Ssimon	return 1;
526160814Ssimonerr:
527160814Ssimon	if(surewarehk_dso)
528160814Ssimon		DSO_free(surewarehk_dso);
529160814Ssimon	surewarehk_dso = NULL;
530160814Ssimon	p_surewarehk_Init = NULL;
531160814Ssimon	p_surewarehk_Finish = NULL;
532160814Ssimon	p_surewarehk_Rand_Bytes = NULL;
533160814Ssimon	p_surewarehk_Rand_Seed = NULL;
534160814Ssimon	p_surewarehk_Load_Privkey = NULL;
535160814Ssimon	p_surewarehk_Load_Rsa_Pubkey = NULL;
536160814Ssimon	p_surewarehk_Free = NULL;
537160814Ssimon	p_surewarehk_Rsa_Priv_Dec = NULL;
538160814Ssimon	p_surewarehk_Rsa_Sign = NULL;
539160814Ssimon	p_surewarehk_Dsa_Sign = NULL;
540160814Ssimon	p_surewarehk_Info_Pubkey = NULL;
541160814Ssimon	p_surewarehk_Load_Dsa_Pubkey = NULL;
542160814Ssimon	p_surewarehk_Mod_Exp = NULL;
543160814Ssimon	return 0;
544160814Ssimon}
545160814Ssimon
546160814Ssimonstatic int surewarehk_finish(ENGINE *e)
547160814Ssimon{
548160814Ssimon	int to_return = 1;
549160814Ssimon	if(surewarehk_dso == NULL)
550160814Ssimon		{
551160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_FINISH,ENGINE_R_NOT_LOADED);
552160814Ssimon		to_return = 0;
553160814Ssimon		goto err;
554160814Ssimon		}
555160814Ssimon	p_surewarehk_Finish();
556160814Ssimon	if(!DSO_free(surewarehk_dso))
557160814Ssimon		{
558160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_FINISH,ENGINE_R_DSO_FAILURE);
559160814Ssimon		to_return = 0;
560160814Ssimon		goto err;
561160814Ssimon		}
562160814Ssimon err:
563160814Ssimon	if (logstream)
564160814Ssimon		BIO_free(logstream);
565160814Ssimon	surewarehk_dso = NULL;
566160814Ssimon	p_surewarehk_Init = NULL;
567160814Ssimon	p_surewarehk_Finish = NULL;
568160814Ssimon	p_surewarehk_Rand_Bytes = NULL;
569160814Ssimon	p_surewarehk_Rand_Seed = NULL;
570160814Ssimon	p_surewarehk_Load_Privkey = NULL;
571160814Ssimon	p_surewarehk_Load_Rsa_Pubkey = NULL;
572160814Ssimon	p_surewarehk_Free = NULL;
573160814Ssimon	p_surewarehk_Rsa_Priv_Dec = NULL;
574160814Ssimon	p_surewarehk_Rsa_Sign = NULL;
575160814Ssimon	p_surewarehk_Dsa_Sign = NULL;
576160814Ssimon	p_surewarehk_Info_Pubkey = NULL;
577160814Ssimon	p_surewarehk_Load_Dsa_Pubkey = NULL;
578160814Ssimon	p_surewarehk_Mod_Exp = NULL;
579160814Ssimon	return to_return;
580160814Ssimon}
581160814Ssimon
582160814Ssimonstatic void surewarehk_error_handling(char *const msg,int func,int ret)
583160814Ssimon{
584160814Ssimon	switch (ret)
585160814Ssimon	{
586160814Ssimon		case SUREWAREHOOK_ERROR_UNIT_FAILURE:
587160814Ssimon			ENGINEerr(func,SUREWARE_R_UNIT_FAILURE);
588160814Ssimon			break;
589160814Ssimon		case SUREWAREHOOK_ERROR_FALLBACK:
590160814Ssimon			ENGINEerr(func,SUREWARE_R_REQUEST_FALLBACK);
591160814Ssimon			break;
592160814Ssimon		case SUREWAREHOOK_ERROR_DATA_SIZE:
593160814Ssimon			ENGINEerr(func,SUREWARE_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
594160814Ssimon			break;
595160814Ssimon		case SUREWAREHOOK_ERROR_INVALID_PAD:
596160814Ssimon			ENGINEerr(func,SUREWARE_R_PADDING_CHECK_FAILED);
597160814Ssimon			break;
598160814Ssimon		default:
599160814Ssimon			ENGINEerr(func,SUREWARE_R_REQUEST_FAILED);
600160814Ssimon			break;
601160814Ssimon		case 1:/*nothing*/
602160814Ssimon			msg[0]='\0';
603160814Ssimon	}
604160814Ssimon	if (*msg)
605160814Ssimon	{
606160814Ssimon		ERR_add_error_data(1,msg);
607160814Ssimon		if (logstream)
608160814Ssimon		{
609160814Ssimon			CRYPTO_w_lock(CRYPTO_LOCK_BIO);
610160814Ssimon			BIO_write(logstream, msg, strlen(msg));
611160814Ssimon			CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
612160814Ssimon		}
613160814Ssimon	}
614160814Ssimon}
615160814Ssimon
616160814Ssimonstatic int surewarehk_rand_bytes(unsigned char *buf, int num)
617160814Ssimon{
618160814Ssimon	int ret=0;
619160814Ssimon	char msg[64]="ENGINE_rand_bytes";
620160814Ssimon	if(!p_surewarehk_Rand_Bytes)
621160814Ssimon	{
622160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_RAND_BYTES,ENGINE_R_NOT_INITIALISED);
623160814Ssimon	}
624160814Ssimon	else
625160814Ssimon	{
626160814Ssimon		ret = p_surewarehk_Rand_Bytes(msg,buf, num);
627160814Ssimon		surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_RAND_BYTES,ret);
628160814Ssimon	}
629160814Ssimon	return ret==1 ? 1 : 0;
630160814Ssimon}
631160814Ssimon
632160814Ssimonstatic void surewarehk_rand_seed(const void *buf, int num)
633160814Ssimon{
634160814Ssimon	int ret=0;
635160814Ssimon	char msg[64]="ENGINE_rand_seed";
636160814Ssimon	if(!p_surewarehk_Rand_Seed)
637160814Ssimon	{
638160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_RAND_SEED,ENGINE_R_NOT_INITIALISED);
639160814Ssimon	}
640160814Ssimon	else
641160814Ssimon	{
642160814Ssimon		ret = p_surewarehk_Rand_Seed(msg,buf, num);
643160814Ssimon		surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_RAND_SEED,ret);
644160814Ssimon	}
645160814Ssimon}
646160814Ssimon
647160814Ssimonstatic void surewarehk_rand_add(const void *buf, int num, double entropy)
648160814Ssimon{
649160814Ssimon	surewarehk_rand_seed(buf,num);
650160814Ssimon}
651160814Ssimon
652160814Ssimonstatic EVP_PKEY* sureware_load_public(ENGINE *e,const char *key_id,char *hptr,unsigned long el,char keytype)
653160814Ssimon{
654160814Ssimon	EVP_PKEY *res = NULL;
655160814Ssimon#ifndef OPENSSL_NO_RSA
656160814Ssimon	RSA *rsatmp = NULL;
657160814Ssimon#endif
658160814Ssimon#ifndef OPENSSL_NO_DSA
659160814Ssimon	DSA *dsatmp=NULL;
660160814Ssimon#endif
661160814Ssimon	char msg[64]="sureware_load_public";
662160814Ssimon	int ret=0;
663160814Ssimon	if(!p_surewarehk_Load_Rsa_Pubkey || !p_surewarehk_Load_Dsa_Pubkey)
664160814Ssimon	{
665160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWARE_LOAD_PUBLIC,ENGINE_R_NOT_INITIALISED);
666160814Ssimon		goto err;
667160814Ssimon	}
668160814Ssimon	switch (keytype)
669160814Ssimon	{
670160814Ssimon#ifndef OPENSSL_NO_RSA
671160814Ssimon	case 1: /*RSA*/
672160814Ssimon		/* set private external reference */
673160814Ssimon		rsatmp = RSA_new_method(e);
674160814Ssimon		RSA_set_ex_data(rsatmp,rsaHndidx,hptr);
675160814Ssimon		rsatmp->flags |= RSA_FLAG_EXT_PKEY;
676160814Ssimon
677160814Ssimon		/* set public big nums*/
678160814Ssimon		rsatmp->e = BN_new();
679160814Ssimon		rsatmp->n = BN_new();
680160814Ssimon		bn_expand2(rsatmp->e, el/sizeof(BN_ULONG));
681160814Ssimon		bn_expand2(rsatmp->n, el/sizeof(BN_ULONG));
682160814Ssimon		if (!rsatmp->e || rsatmp->e->dmax!=(int)(el/sizeof(BN_ULONG))||
683160814Ssimon			!rsatmp->n || rsatmp->n->dmax!=(int)(el/sizeof(BN_ULONG)))
684160814Ssimon			goto err;
685160814Ssimon		ret=p_surewarehk_Load_Rsa_Pubkey(msg,key_id,el,
686160814Ssimon						 (unsigned long *)rsatmp->n->d,
687160814Ssimon						 (unsigned long *)rsatmp->e->d);
688160814Ssimon		surewarehk_error_handling(msg,SUREWARE_F_SUREWARE_LOAD_PUBLIC,ret);
689160814Ssimon		if (ret!=1)
690160814Ssimon		{
691160814Ssimon			SUREWAREerr(SUREWARE_F_SUREWARE_LOAD_PUBLIC,ENGINE_R_FAILED_LOADING_PUBLIC_KEY);
692160814Ssimon			goto err;
693160814Ssimon		}
694160814Ssimon		/* normalise pub e and pub n */
695160814Ssimon		rsatmp->e->top=el/sizeof(BN_ULONG);
696160814Ssimon		bn_fix_top(rsatmp->e);
697160814Ssimon		rsatmp->n->top=el/sizeof(BN_ULONG);
698160814Ssimon		bn_fix_top(rsatmp->n);
699160814Ssimon		/* create an EVP object: engine + rsa key */
700160814Ssimon		res = EVP_PKEY_new();
701160814Ssimon		EVP_PKEY_assign_RSA(res, rsatmp);
702160814Ssimon		break;
703160814Ssimon#endif
704160814Ssimon
705160814Ssimon#ifndef OPENSSL_NO_DSA
706160814Ssimon	case 2:/*DSA*/
707160814Ssimon		/* set private/public external reference */
708160814Ssimon		dsatmp = DSA_new_method(e);
709160814Ssimon		DSA_set_ex_data(dsatmp,dsaHndidx,hptr);
710160814Ssimon		/*dsatmp->flags |= DSA_FLAG_EXT_PKEY;*/
711160814Ssimon
712160814Ssimon		/* set public key*/
713160814Ssimon		dsatmp->pub_key = BN_new();
714160814Ssimon		dsatmp->p = BN_new();
715160814Ssimon		dsatmp->q = BN_new();
716160814Ssimon		dsatmp->g = BN_new();
717160814Ssimon		bn_expand2(dsatmp->pub_key, el/sizeof(BN_ULONG));
718160814Ssimon		bn_expand2(dsatmp->p, el/sizeof(BN_ULONG));
719160814Ssimon		bn_expand2(dsatmp->q, 20/sizeof(BN_ULONG));
720160814Ssimon		bn_expand2(dsatmp->g, el/sizeof(BN_ULONG));
721160814Ssimon		if (!dsatmp->pub_key || dsatmp->pub_key->dmax!=(int)(el/sizeof(BN_ULONG))||
722160814Ssimon			!dsatmp->p || dsatmp->p->dmax!=(int)(el/sizeof(BN_ULONG)) ||
723160814Ssimon			!dsatmp->q || dsatmp->q->dmax!=20/sizeof(BN_ULONG) ||
724160814Ssimon			!dsatmp->g || dsatmp->g->dmax!=(int)(el/sizeof(BN_ULONG)))
725160814Ssimon			goto err;
726160814Ssimon
727160814Ssimon		ret=p_surewarehk_Load_Dsa_Pubkey(msg,key_id,el,
728160814Ssimon						 (unsigned long *)dsatmp->pub_key->d,
729160814Ssimon						 (unsigned long *)dsatmp->p->d,
730160814Ssimon						 (unsigned long *)dsatmp->q->d,
731160814Ssimon						 (unsigned long *)dsatmp->g->d);
732160814Ssimon		surewarehk_error_handling(msg,SUREWARE_F_SUREWARE_LOAD_PUBLIC,ret);
733160814Ssimon		if (ret!=1)
734160814Ssimon		{
735160814Ssimon			SUREWAREerr(SUREWARE_F_SUREWARE_LOAD_PUBLIC,ENGINE_R_FAILED_LOADING_PUBLIC_KEY);
736160814Ssimon			goto err;
737160814Ssimon		}
738160814Ssimon		/* set parameters */
739160814Ssimon		/* normalise pubkey and parameters in case of */
740160814Ssimon		dsatmp->pub_key->top=el/sizeof(BN_ULONG);
741160814Ssimon		bn_fix_top(dsatmp->pub_key);
742160814Ssimon		dsatmp->p->top=el/sizeof(BN_ULONG);
743160814Ssimon		bn_fix_top(dsatmp->p);
744160814Ssimon		dsatmp->q->top=20/sizeof(BN_ULONG);
745160814Ssimon		bn_fix_top(dsatmp->q);
746160814Ssimon		dsatmp->g->top=el/sizeof(BN_ULONG);
747160814Ssimon		bn_fix_top(dsatmp->g);
748160814Ssimon
749160814Ssimon		/* create an EVP object: engine + rsa key */
750160814Ssimon		res = EVP_PKEY_new();
751160814Ssimon		EVP_PKEY_assign_DSA(res, dsatmp);
752160814Ssimon		break;
753160814Ssimon#endif
754160814Ssimon
755160814Ssimon	default:
756160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWARE_LOAD_PUBLIC,ENGINE_R_FAILED_LOADING_PRIVATE_KEY);
757160814Ssimon		goto err;
758160814Ssimon	}
759160814Ssimon	return res;
760160814Ssimon err:
761160814Ssimon#ifndef OPENSSL_NO_RSA
762160814Ssimon	if (rsatmp)
763160814Ssimon		RSA_free(rsatmp);
764160814Ssimon#endif
765160814Ssimon#ifndef OPENSSL_NO_DSA
766160814Ssimon	if (dsatmp)
767160814Ssimon		DSA_free(dsatmp);
768160814Ssimon#endif
769160814Ssimon	return NULL;
770160814Ssimon}
771160814Ssimon
772160814Ssimonstatic EVP_PKEY *surewarehk_load_privkey(ENGINE *e, const char *key_id,
773160814Ssimon					 UI_METHOD *ui_method, void *callback_data)
774160814Ssimon{
775160814Ssimon	EVP_PKEY *res = NULL;
776160814Ssimon	int ret=0;
777160814Ssimon	unsigned long el=0;
778160814Ssimon	char *hptr=NULL;
779160814Ssimon	char keytype=0;
780160814Ssimon	char msg[64]="ENGINE_load_privkey";
781160814Ssimon
782160814Ssimon	if(!p_surewarehk_Load_Privkey)
783160814Ssimon	{
784160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_LOAD_PRIVKEY,ENGINE_R_NOT_INITIALISED);
785160814Ssimon	}
786160814Ssimon	else
787160814Ssimon	{
788160814Ssimon		ret=p_surewarehk_Load_Privkey(msg,key_id,&hptr,&el,&keytype);
789160814Ssimon		if (ret!=1)
790160814Ssimon		{
791160814Ssimon			SUREWAREerr(SUREWARE_F_SUREWAREHK_LOAD_PRIVKEY,ENGINE_R_FAILED_LOADING_PRIVATE_KEY);
792160814Ssimon			ERR_add_error_data(1,msg);
793160814Ssimon		}
794160814Ssimon		else
795160814Ssimon			res=sureware_load_public(e,key_id,hptr,el,keytype);
796160814Ssimon	}
797160814Ssimon	return res;
798160814Ssimon}
799160814Ssimon
800160814Ssimonstatic EVP_PKEY *surewarehk_load_pubkey(ENGINE *e, const char *key_id,
801160814Ssimon					 UI_METHOD *ui_method, void *callback_data)
802160814Ssimon{
803160814Ssimon	EVP_PKEY *res = NULL;
804160814Ssimon	int ret=0;
805160814Ssimon	unsigned long el=0;
806160814Ssimon	char *hptr=NULL;
807160814Ssimon	char keytype=0;
808160814Ssimon	char msg[64]="ENGINE_load_pubkey";
809160814Ssimon
810160814Ssimon	if(!p_surewarehk_Info_Pubkey)
811160814Ssimon	{
812160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_LOAD_PUBKEY,ENGINE_R_NOT_INITIALISED);
813160814Ssimon	}
814160814Ssimon	else
815160814Ssimon	{
816160814Ssimon		/* call once to identify if DSA or RSA */
817160814Ssimon		ret=p_surewarehk_Info_Pubkey(msg,key_id,&el,&keytype);
818160814Ssimon		if (ret!=1)
819160814Ssimon		{
820160814Ssimon			SUREWAREerr(SUREWARE_F_SUREWAREHK_LOAD_PUBKEY,ENGINE_R_FAILED_LOADING_PUBLIC_KEY);
821160814Ssimon			ERR_add_error_data(1,msg);
822160814Ssimon		}
823160814Ssimon		else
824160814Ssimon			res=sureware_load_public(e,key_id,hptr,el,keytype);
825160814Ssimon	}
826160814Ssimon	return res;
827160814Ssimon}
828160814Ssimon
829160814Ssimon/* This cleans up an RSA/DSA KM key(do not destroy the key into the hardware)
830160814Ssimon, called when ex_data is freed */
831160814Ssimonstatic void surewarehk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
832160814Ssimon	int idx,long argl, void *argp)
833160814Ssimon{
834160814Ssimon	if(!p_surewarehk_Free)
835160814Ssimon	{
836160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_EX_FREE,ENGINE_R_NOT_INITIALISED);
837160814Ssimon	}
838160814Ssimon	else
839160814Ssimon		p_surewarehk_Free((char *)item,0);
840160814Ssimon}
841160814Ssimon
842160814Ssimon#if 0
843160814Ssimon/* not currently used (bug?) */
844160814Ssimon/* This cleans up an DH KM key (destroys the key into hardware),
845160814Ssimoncalled when ex_data is freed */
846160814Ssimonstatic void surewarehk_dh_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
847160814Ssimon	int idx,long argl, void *argp)
848160814Ssimon{
849160814Ssimon	if(!p_surewarehk_Free)
850160814Ssimon	{
851160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_DH_EX_FREE,ENGINE_R_NOT_INITIALISED);
852160814Ssimon	}
853160814Ssimon	else
854160814Ssimon		p_surewarehk_Free((char *)item,1);
855160814Ssimon}
856160814Ssimon#endif
857160814Ssimon
858160814Ssimon/*
859160814Ssimon* return number of decrypted bytes
860160814Ssimon*/
861160814Ssimon#ifndef OPENSSL_NO_RSA
862160814Ssimonstatic int surewarehk_rsa_priv_dec(int flen,const unsigned char *from,unsigned char *to,
863160814Ssimon			RSA *rsa,int padding)
864160814Ssimon{
865160814Ssimon	int ret=0,tlen;
866160814Ssimon	char *buf=NULL,*hptr=NULL;
867160814Ssimon	char msg[64]="ENGINE_rsa_priv_dec";
868160814Ssimon	if (!p_surewarehk_Rsa_Priv_Dec)
869160814Ssimon	{
870160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,ENGINE_R_NOT_INITIALISED);
871160814Ssimon	}
872160814Ssimon	/* extract ref to private key */
873160814Ssimon	else if (!(hptr=RSA_get_ex_data(rsa, rsaHndidx)))
874160814Ssimon	{
875160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,SUREWARE_R_MISSING_KEY_COMPONENTS);
876160814Ssimon		goto err;
877160814Ssimon	}
878160814Ssimon	/* analyse what padding we can do into the hardware */
879160814Ssimon	if (padding==RSA_PKCS1_PADDING)
880160814Ssimon	{
881160814Ssimon		/* do it one shot */
882160814Ssimon		ret=p_surewarehk_Rsa_Priv_Dec(msg,flen,(unsigned char *)from,&tlen,to,hptr,SUREWARE_PKCS1_PAD);
883160814Ssimon		surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,ret);
884160814Ssimon		if (ret!=1)
885160814Ssimon			goto err;
886160814Ssimon		ret=tlen;
887160814Ssimon	}
888160814Ssimon	else /* do with no padding into hardware */
889160814Ssimon	{
890160814Ssimon		ret=p_surewarehk_Rsa_Priv_Dec(msg,flen,(unsigned char *)from,&tlen,to,hptr,SUREWARE_NO_PAD);
891160814Ssimon		surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,ret);
892160814Ssimon		if (ret!=1)
893160814Ssimon			goto err;
894160814Ssimon		/* intermediate buffer for padding */
895160814Ssimon		if ((buf=OPENSSL_malloc(tlen)) == NULL)
896160814Ssimon		{
897160814Ssimon			SUREWAREerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,ERR_R_MALLOC_FAILURE);
898160814Ssimon			goto err;
899160814Ssimon		}
900160814Ssimon		memcpy(buf,to,tlen);/* transfert to into buf */
901160814Ssimon		switch (padding) /* check padding in software */
902160814Ssimon		{
903160814Ssimon#ifndef OPENSSL_NO_SHA
904160814Ssimon		case RSA_PKCS1_OAEP_PADDING:
905160814Ssimon			ret=RSA_padding_check_PKCS1_OAEP(to,tlen,(unsigned char *)buf,tlen,tlen,NULL,0);
906160814Ssimon			break;
907160814Ssimon#endif
908160814Ssimon 		case RSA_SSLV23_PADDING:
909160814Ssimon			ret=RSA_padding_check_SSLv23(to,tlen,(unsigned char *)buf,flen,tlen);
910160814Ssimon			break;
911160814Ssimon		case RSA_NO_PADDING:
912160814Ssimon			ret=RSA_padding_check_none(to,tlen,(unsigned char *)buf,flen,tlen);
913160814Ssimon			break;
914160814Ssimon		default:
915160814Ssimon			SUREWAREerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,SUREWARE_R_UNKNOWN_PADDING_TYPE);
916160814Ssimon			goto err;
917160814Ssimon		}
918160814Ssimon		if (ret < 0)
919160814Ssimon			SUREWAREerr(SUREWARE_F_SUREWAREHK_RSA_PRIV_DEC,SUREWARE_R_PADDING_CHECK_FAILED);
920160814Ssimon	}
921160814Ssimonerr:
922160814Ssimon	if (buf)
923160814Ssimon	{
924160814Ssimon		OPENSSL_cleanse(buf,tlen);
925160814Ssimon		OPENSSL_free(buf);
926160814Ssimon	}
927160814Ssimon	return ret;
928160814Ssimon}
929160814Ssimon
930160814Ssimon/*
931160814Ssimon* Does what OpenSSL rsa_priv_enc does.
932160814Ssimon*/
933160814Ssimonstatic int surewarehk_rsa_sign(int flen,const unsigned char *from,unsigned char *to,
934160814Ssimon			    RSA *rsa,int padding)
935160814Ssimon{
936160814Ssimon	int ret=0,tlen;
937160814Ssimon	char *hptr=NULL;
938160814Ssimon	char msg[64]="ENGINE_rsa_sign";
939160814Ssimon	if (!p_surewarehk_Rsa_Sign)
940160814Ssimon	{
941160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_RSA_SIGN,ENGINE_R_NOT_INITIALISED);
942160814Ssimon	}
943160814Ssimon	/* extract ref to private key */
944160814Ssimon	else if (!(hptr=RSA_get_ex_data(rsa, rsaHndidx)))
945160814Ssimon	{
946160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_RSA_SIGN,SUREWARE_R_MISSING_KEY_COMPONENTS);
947160814Ssimon	}
948160814Ssimon	else
949160814Ssimon	{
950160814Ssimon		switch (padding)
951160814Ssimon		{
952160814Ssimon		case RSA_PKCS1_PADDING: /* do it in one shot */
953160814Ssimon			ret=p_surewarehk_Rsa_Sign(msg,flen,(unsigned char *)from,&tlen,to,hptr,SUREWARE_PKCS1_PAD);
954160814Ssimon			surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_RSA_SIGN,ret);
955160814Ssimon			break;
956160814Ssimon		case RSA_NO_PADDING:
957160814Ssimon		default:
958160814Ssimon			SUREWAREerr(SUREWARE_F_SUREWAREHK_RSA_SIGN,SUREWARE_R_UNKNOWN_PADDING_TYPE);
959160814Ssimon		}
960160814Ssimon	}
961160814Ssimon	return ret==1 ? tlen : ret;
962160814Ssimon}
963160814Ssimon
964160814Ssimon#endif
965160814Ssimon
966160814Ssimon#ifndef OPENSSL_NO_DSA
967160814Ssimon/* DSA sign and verify */
968160814Ssimonstatic	DSA_SIG * surewarehk_dsa_do_sign(const unsigned char *from, int flen, DSA *dsa)
969160814Ssimon{
970160814Ssimon	int ret=0;
971160814Ssimon	char *hptr=NULL;
972160814Ssimon	DSA_SIG *psign=NULL;
973160814Ssimon	char msg[64]="ENGINE_dsa_do_sign";
974160814Ssimon	if (!p_surewarehk_Dsa_Sign)
975160814Ssimon	{
976160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_DSA_DO_SIGN,ENGINE_R_NOT_INITIALISED);
977160814Ssimon		goto err;
978160814Ssimon	}
979160814Ssimon	/* extract ref to private key */
980160814Ssimon	else if (!(hptr=DSA_get_ex_data(dsa, dsaHndidx)))
981160814Ssimon	{
982160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_DSA_DO_SIGN,SUREWARE_R_MISSING_KEY_COMPONENTS);
983160814Ssimon		goto err;
984160814Ssimon	}
985160814Ssimon	else
986160814Ssimon	{
987160814Ssimon		if((psign = DSA_SIG_new()) == NULL)
988160814Ssimon		{
989160814Ssimon			SUREWAREerr(SUREWARE_F_SUREWAREHK_DSA_DO_SIGN,ERR_R_MALLOC_FAILURE);
990160814Ssimon			goto err;
991160814Ssimon		}
992160814Ssimon		psign->r=BN_new();
993160814Ssimon		psign->s=BN_new();
994160814Ssimon		bn_expand2(psign->r, 20/sizeof(BN_ULONG));
995160814Ssimon		bn_expand2(psign->s, 20/sizeof(BN_ULONG));
996160814Ssimon		if (!psign->r || psign->r->dmax!=20/sizeof(BN_ULONG) ||
997160814Ssimon			!psign->s || psign->s->dmax!=20/sizeof(BN_ULONG))
998160814Ssimon			goto err;
999160814Ssimon		ret=p_surewarehk_Dsa_Sign(msg,flen,from,
1000160814Ssimon					  (unsigned long *)psign->r->d,
1001160814Ssimon					  (unsigned long *)psign->s->d,
1002160814Ssimon					  hptr);
1003160814Ssimon		surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_DSA_DO_SIGN,ret);
1004160814Ssimon	}
1005160814Ssimon	psign->r->top=20/sizeof(BN_ULONG);
1006160814Ssimon	bn_fix_top(psign->r);
1007160814Ssimon	psign->s->top=20/sizeof(BN_ULONG);
1008160814Ssimon	bn_fix_top(psign->s);
1009160814Ssimon
1010160814Ssimonerr:
1011160814Ssimon	if (psign)
1012160814Ssimon	{
1013160814Ssimon		DSA_SIG_free(psign);
1014160814Ssimon		psign=NULL;
1015160814Ssimon	}
1016160814Ssimon	return psign;
1017160814Ssimon}
1018160814Ssimon#endif
1019160814Ssimon
1020160814Ssimonstatic int surewarehk_modexp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1021160814Ssimon			     const BIGNUM *m, BN_CTX *ctx)
1022160814Ssimon{
1023160814Ssimon	int ret=0;
1024160814Ssimon	char msg[64]="ENGINE_modexp";
1025160814Ssimon	if (!p_surewarehk_Mod_Exp)
1026160814Ssimon	{
1027160814Ssimon		SUREWAREerr(SUREWARE_F_SUREWAREHK_MODEXP,ENGINE_R_NOT_INITIALISED);
1028160814Ssimon	}
1029160814Ssimon	else
1030160814Ssimon	{
1031160814Ssimon		bn_expand2(r,m->top);
1032160814Ssimon		if (r && r->dmax==m->top)
1033160814Ssimon		{
1034160814Ssimon			/* do it*/
1035160814Ssimon			ret=p_surewarehk_Mod_Exp(msg,
1036160814Ssimon						 m->top*sizeof(BN_ULONG),
1037160814Ssimon						 (unsigned long *)m->d,
1038160814Ssimon						 p->top*sizeof(BN_ULONG),
1039160814Ssimon						 (unsigned long *)p->d,
1040160814Ssimon						 a->top*sizeof(BN_ULONG),
1041160814Ssimon						 (unsigned long *)a->d,
1042160814Ssimon						 (unsigned long *)r->d);
1043160814Ssimon			surewarehk_error_handling(msg,SUREWARE_F_SUREWAREHK_MODEXP,ret);
1044160814Ssimon			if (ret==1)
1045160814Ssimon			{
1046160814Ssimon				/* normalise result */
1047160814Ssimon				r->top=m->top;
1048160814Ssimon				bn_fix_top(r);
1049160814Ssimon			}
1050160814Ssimon		}
1051160814Ssimon	}
1052160814Ssimon	return ret;
1053160814Ssimon}
1054160814Ssimon#endif /* !OPENSSL_NO_HW_SureWare */
1055160814Ssimon#endif /* !OPENSSL_NO_HW */
1056