1/* crypto/engine/hw_aep.c */
2/*
3 */
4/* ====================================================================
5 * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in
16 *    the documentation and/or other materials provided with the
17 *    distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this
20 *    software must display the following acknowledgment:
21 *    "This product includes software developed by the OpenSSL Project
22 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23 *
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 *    endorse or promote products derived from this software without
26 *    prior written permission. For written permission, please contact
27 *    licensing@OpenSSL.org.
28 *
29 * 5. Products derived from this software may not be called "OpenSSL"
30 *    nor may "OpenSSL" appear in their names without prior written
31 *    permission of the OpenSSL Project.
32 *
33 * 6. Redistributions of any form whatsoever must retain the following
34 *    acknowledgment:
35 *    "This product includes software developed by the OpenSSL Project
36 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com).  This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com).
55 *
56 */
57
58#include <stdio.h>
59#include <openssl/bn.h>
60#include <string.h>
61
62#include <openssl/e_os2.h>
63#if !defined(OPENSSL_SYS_MSDOS) || defined(__DJGPP__)
64#include <sys/types.h>
65#include <unistd.h>
66#else
67#include <process.h>
68typedef int pid_t;
69#endif
70
71#include <openssl/crypto.h>
72#include <openssl/dso.h>
73#include <openssl/engine.h>
74#include <openssl/buffer.h>
75
76#ifndef OPENSSL_NO_HW
77#ifndef OPENSSL_NO_HW_AEP
78#ifdef FLAT_INC
79#include "aep.h"
80#else
81#include "vendor_defns/aep.h"
82#endif
83
84#define AEP_LIB_NAME "aep engine"
85#define FAIL_TO_SW 0x10101010
86
87#include "hw_aep_err.c"
88
89static int aep_init(ENGINE *e);
90static int aep_finish(ENGINE *e);
91static int aep_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
92static int aep_destroy(ENGINE *e);
93
94static AEP_RV aep_get_connection(AEP_CONNECTION_HNDL_PTR hConnection);
95static AEP_RV aep_return_connection(AEP_CONNECTION_HNDL hConnection);
96static AEP_RV aep_close_connection(AEP_CONNECTION_HNDL hConnection);
97static AEP_RV aep_close_all_connections(int use_engine_lock, int *in_use);
98
99/* BIGNUM stuff */
100static int aep_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
101	const BIGNUM *m, BN_CTX *ctx);
102
103static AEP_RV aep_mod_exp_crt(BIGNUM *r,const  BIGNUM *a, const BIGNUM *p,
104	const BIGNUM *q, const BIGNUM *dmp1,const BIGNUM *dmq1,
105	const BIGNUM *iqmp, BN_CTX *ctx);
106
107/* RSA stuff */
108#ifndef OPENSSL_NO_RSA
109static int aep_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa);
110#endif
111
112/* This function is aliased to mod_exp (with the mont stuff dropped). */
113static int aep_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
114	const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
115
116/* DSA stuff */
117#ifndef OPENSSL_NO_DSA
118static int aep_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
119	BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
120	BN_CTX *ctx, BN_MONT_CTX *in_mont);
121
122static int aep_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
123	const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
124	BN_MONT_CTX *m_ctx);
125#endif
126
127/* DH stuff */
128/* This function is aliased to mod_exp (with the DH and mont dropped). */
129#ifndef OPENSSL_NO_DH
130static int aep_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
131	const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
132#endif
133
134/* rand stuff   */
135#ifdef AEPRAND
136static int aep_rand(unsigned char *buf, int num);
137static int aep_rand_status(void);
138#endif
139
140/* Bignum conversion stuff */
141static AEP_RV GetBigNumSize(AEP_VOID_PTR ArbBigNum, AEP_U32* BigNumSize);
142static AEP_RV MakeAEPBigNum(AEP_VOID_PTR ArbBigNum, AEP_U32 BigNumSize,
143	unsigned char* AEP_BigNum);
144static AEP_RV ConvertAEPBigNum(void* ArbBigNum, AEP_U32 BigNumSize,
145	unsigned char* AEP_BigNum);
146
147/* The definitions for control commands specific to this engine */
148#define AEP_CMD_SO_PATH		ENGINE_CMD_BASE
149static const ENGINE_CMD_DEFN aep_cmd_defns[] =
150	{
151	{ AEP_CMD_SO_PATH,
152	  "SO_PATH",
153	  "Specifies the path to the 'aep' shared library",
154	  ENGINE_CMD_FLAG_STRING
155	},
156	{0, NULL, NULL, 0}
157	};
158
159#ifndef OPENSSL_NO_RSA
160/* Our internal RSA_METHOD that we provide pointers to */
161static RSA_METHOD aep_rsa =
162	{
163	"Aep RSA method",
164	NULL,                /*rsa_pub_encrypt*/
165	NULL,                /*rsa_pub_decrypt*/
166	NULL,                /*rsa_priv_encrypt*/
167	NULL,                /*rsa_priv_encrypt*/
168	aep_rsa_mod_exp,     /*rsa_mod_exp*/
169	aep_mod_exp_mont,    /*bn_mod_exp*/
170	NULL,                /*init*/
171	NULL,                /*finish*/
172	0,                   /*flags*/
173	NULL,                /*app_data*/
174	NULL,                /*rsa_sign*/
175	NULL                 /*rsa_verify*/
176	};
177#endif
178
179#ifndef OPENSSL_NO_DSA
180/* Our internal DSA_METHOD that we provide pointers to */
181static DSA_METHOD aep_dsa =
182	{
183	"Aep DSA method",
184	NULL,                /* dsa_do_sign */
185	NULL,                /* dsa_sign_setup */
186	NULL,                /* dsa_do_verify */
187	aep_dsa_mod_exp,     /* dsa_mod_exp */
188	aep_mod_exp_dsa,     /* bn_mod_exp */
189	NULL,                /* init */
190	NULL,                /* finish */
191	0,                   /* flags */
192	NULL                 /* app_data */
193	};
194#endif
195
196#ifndef OPENSSL_NO_DH
197/* Our internal DH_METHOD that we provide pointers to */
198static DH_METHOD aep_dh =
199	{
200	"Aep DH method",
201	NULL,
202	NULL,
203	aep_mod_exp_dh,
204	NULL,
205	NULL,
206	0,
207	NULL
208	};
209#endif
210
211#ifdef AEPRAND
212/* our internal RAND_method that we provide pointers to  */
213static RAND_METHOD aep_random =
214	{
215	/*"AEP RAND method", */
216	NULL,
217	aep_rand,
218	NULL,
219	NULL,
220	aep_rand,
221	aep_rand_status,
222	};
223#endif
224
225/*Define an array of structures to hold connections*/
226static AEP_CONNECTION_ENTRY aep_app_conn_table[MAX_PROCESS_CONNECTIONS];
227
228/*Used to determine if this is a new process*/
229static pid_t    recorded_pid = 0;
230
231#ifdef AEPRAND
232static AEP_U8   rand_block[RAND_BLK_SIZE];
233static AEP_U32  rand_block_bytes = 0;
234#endif
235
236/* Constants used when creating the ENGINE */
237static const char *engine_aep_id = "aep";
238static const char *engine_aep_name = "Aep hardware engine support";
239
240static int max_key_len = 2176;
241
242
243/* This internal function is used by ENGINE_aep() and possibly by the
244 * "dynamic" ENGINE support too */
245static int bind_aep(ENGINE *e)
246	{
247#ifndef OPENSSL_NO_RSA
248	const RSA_METHOD  *meth1;
249#endif
250#ifndef OPENSSL_NO_DSA
251	const DSA_METHOD  *meth2;
252#endif
253#ifndef OPENSSL_NO_DH
254	const DH_METHOD	  *meth3;
255#endif
256
257	if(!ENGINE_set_id(e, engine_aep_id) ||
258		!ENGINE_set_name(e, engine_aep_name) ||
259#ifndef OPENSSL_NO_RSA
260		!ENGINE_set_RSA(e, &aep_rsa) ||
261#endif
262#ifndef OPENSSL_NO_DSA
263		!ENGINE_set_DSA(e, &aep_dsa) ||
264#endif
265#ifndef OPENSSL_NO_DH
266		!ENGINE_set_DH(e, &aep_dh) ||
267#endif
268#ifdef AEPRAND
269		!ENGINE_set_RAND(e, &aep_random) ||
270#endif
271		!ENGINE_set_init_function(e, aep_init) ||
272		!ENGINE_set_destroy_function(e, aep_destroy) ||
273		!ENGINE_set_finish_function(e, aep_finish) ||
274		!ENGINE_set_ctrl_function(e, aep_ctrl) ||
275		!ENGINE_set_cmd_defns(e, aep_cmd_defns))
276		return 0;
277
278#ifndef OPENSSL_NO_RSA
279	/* We know that the "PKCS1_SSLeay()" functions hook properly
280	 * to the aep-specific mod_exp and mod_exp_crt so we use
281	 * those functions. NB: We don't use ENGINE_openssl() or
282	 * anything "more generic" because something like the RSAref
283	 * code may not hook properly, and if you own one of these
284	 * cards then you have the right to do RSA operations on it
285	 * anyway! */
286	meth1 = RSA_PKCS1_SSLeay();
287	aep_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
288	aep_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
289	aep_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
290	aep_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
291#endif
292
293
294#ifndef OPENSSL_NO_DSA
295	/* Use the DSA_OpenSSL() method and just hook the mod_exp-ish
296	 * bits. */
297	meth2 = DSA_OpenSSL();
298	aep_dsa.dsa_do_sign    = meth2->dsa_do_sign;
299	aep_dsa.dsa_sign_setup = meth2->dsa_sign_setup;
300	aep_dsa.dsa_do_verify  = meth2->dsa_do_verify;
301
302	aep_dsa = *DSA_get_default_method();
303	aep_dsa.dsa_mod_exp = aep_dsa_mod_exp;
304	aep_dsa.bn_mod_exp = aep_mod_exp_dsa;
305#endif
306
307#ifndef OPENSSL_NO_DH
308	/* Much the same for Diffie-Hellman */
309	meth3 = DH_OpenSSL();
310	aep_dh.generate_key = meth3->generate_key;
311	aep_dh.compute_key  = meth3->compute_key;
312	aep_dh.bn_mod_exp   = meth3->bn_mod_exp;
313#endif
314
315	/* Ensure the aep error handling is set up */
316	ERR_load_AEPHK_strings();
317
318	return 1;
319}
320
321#ifdef ENGINE_DYNAMIC_SUPPORT
322static int bind_helper(ENGINE *e, const char *id)
323	{
324	if(id && (strcmp(id, engine_aep_id) != 0))
325		return 0;
326	if(!bind_aep(e))
327		return 0;
328	return 1;
329	}
330IMPLEMENT_DYNAMIC_CHECK_FN()
331IMPLEMENT_DYNAMIC_BIND_FN(bind_helper)
332#else
333static ENGINE *engine_aep(void)
334	{
335	ENGINE *ret = ENGINE_new();
336	if(!ret)
337		return NULL;
338	if(!bind_aep(ret))
339		{
340		ENGINE_free(ret);
341		return NULL;
342		}
343	return ret;
344	}
345
346void ENGINE_load_aep(void)
347	{
348	/* Copied from eng_[openssl|dyn].c */
349	ENGINE *toadd = engine_aep();
350	if(!toadd) return;
351	ENGINE_add(toadd);
352	ENGINE_free(toadd);
353	ERR_clear_error();
354	}
355#endif
356
357/* This is a process-global DSO handle used for loading and unloading
358 * the Aep library. NB: This is only set (or unset) during an
359 * init() or finish() call (reference counts permitting) and they're
360 * operating with global locks, so this should be thread-safe
361 * implicitly. */
362static DSO *aep_dso = NULL;
363
364/* These are the static string constants for the DSO file name and the function
365 * symbol names to bind to.
366*/
367static const char *AEP_LIBNAME = NULL;
368static const char *get_AEP_LIBNAME(void)
369	{
370	if(AEP_LIBNAME)
371		return AEP_LIBNAME;
372	return "aep";
373	}
374static void free_AEP_LIBNAME(void)
375	{
376	if(AEP_LIBNAME)
377		OPENSSL_free((void*)AEP_LIBNAME);
378	AEP_LIBNAME = NULL;
379	}
380static long set_AEP_LIBNAME(const char *name)
381	{
382	free_AEP_LIBNAME();
383	return ((AEP_LIBNAME = BUF_strdup(name)) != NULL ? 1 : 0);
384	}
385
386static const char *AEP_F1    = "AEP_ModExp";
387static const char *AEP_F2    = "AEP_ModExpCrt";
388#ifdef AEPRAND
389static const char *AEP_F3    = "AEP_GenRandom";
390#endif
391static const char *AEP_F4    = "AEP_Finalize";
392static const char *AEP_F5    = "AEP_Initialize";
393static const char *AEP_F6    = "AEP_OpenConnection";
394static const char *AEP_F7    = "AEP_SetBNCallBacks";
395static const char *AEP_F8    = "AEP_CloseConnection";
396
397/* These are the function pointers that are (un)set when the library has
398 * successfully (un)loaded. */
399static t_AEP_OpenConnection    *p_AEP_OpenConnection  = NULL;
400static t_AEP_CloseConnection   *p_AEP_CloseConnection = NULL;
401static t_AEP_ModExp            *p_AEP_ModExp          = NULL;
402static t_AEP_ModExpCrt         *p_AEP_ModExpCrt       = NULL;
403#ifdef AEPRAND
404static t_AEP_GenRandom         *p_AEP_GenRandom       = NULL;
405#endif
406static t_AEP_Initialize        *p_AEP_Initialize      = NULL;
407static t_AEP_Finalize          *p_AEP_Finalize        = NULL;
408static t_AEP_SetBNCallBacks    *p_AEP_SetBNCallBacks  = NULL;
409
410/* (de)initialisation functions. */
411static int aep_init(ENGINE *e)
412	{
413	t_AEP_ModExp          *p1;
414	t_AEP_ModExpCrt       *p2;
415#ifdef AEPRAND
416	t_AEP_GenRandom       *p3;
417#endif
418	t_AEP_Finalize        *p4;
419	t_AEP_Initialize      *p5;
420	t_AEP_OpenConnection  *p6;
421	t_AEP_SetBNCallBacks  *p7;
422	t_AEP_CloseConnection *p8;
423
424	int to_return = 0;
425
426	if(aep_dso != NULL)
427		{
428		AEPHKerr(AEPHK_F_AEP_INIT,AEPHK_R_ALREADY_LOADED);
429		goto err;
430		}
431	/* Attempt to load libaep.so. */
432
433	aep_dso = DSO_load(NULL, get_AEP_LIBNAME(), NULL, 0);
434
435	if(aep_dso == NULL)
436		{
437		AEPHKerr(AEPHK_F_AEP_INIT,AEPHK_R_NOT_LOADED);
438		goto err;
439		}
440
441	if(	!(p1 = (t_AEP_ModExp *)     DSO_bind_func( aep_dso,AEP_F1))  ||
442		!(p2 = (t_AEP_ModExpCrt*)   DSO_bind_func( aep_dso,AEP_F2))  ||
443#ifdef AEPRAND
444		!(p3 = (t_AEP_GenRandom*)   DSO_bind_func( aep_dso,AEP_F3))  ||
445#endif
446		!(p4 = (t_AEP_Finalize*)    DSO_bind_func( aep_dso,AEP_F4))  ||
447		!(p5 = (t_AEP_Initialize*)  DSO_bind_func( aep_dso,AEP_F5))  ||
448		!(p6 = (t_AEP_OpenConnection*) DSO_bind_func( aep_dso,AEP_F6))  ||
449		!(p7 = (t_AEP_SetBNCallBacks*) DSO_bind_func( aep_dso,AEP_F7))  ||
450		!(p8 = (t_AEP_CloseConnection*) DSO_bind_func( aep_dso,AEP_F8)))
451		{
452		AEPHKerr(AEPHK_F_AEP_INIT,AEPHK_R_NOT_LOADED);
453		goto err;
454		}
455
456	/* Copy the pointers */
457
458	p_AEP_ModExp           = p1;
459	p_AEP_ModExpCrt        = p2;
460#ifdef AEPRAND
461	p_AEP_GenRandom        = p3;
462#endif
463	p_AEP_Finalize         = p4;
464	p_AEP_Initialize       = p5;
465	p_AEP_OpenConnection   = p6;
466	p_AEP_SetBNCallBacks   = p7;
467	p_AEP_CloseConnection  = p8;
468
469	to_return = 1;
470
471	return to_return;
472
473 err:
474
475	if(aep_dso)
476		DSO_free(aep_dso);
477
478	p_AEP_OpenConnection    = NULL;
479	p_AEP_ModExp            = NULL;
480	p_AEP_ModExpCrt         = NULL;
481#ifdef AEPRAND
482	p_AEP_GenRandom         = NULL;
483#endif
484	p_AEP_Initialize        = NULL;
485	p_AEP_Finalize          = NULL;
486	p_AEP_SetBNCallBacks    = NULL;
487	p_AEP_CloseConnection   = NULL;
488
489	return to_return;
490	}
491
492/* Destructor (complements the "ENGINE_aep()" constructor) */
493static int aep_destroy(ENGINE *e)
494	{
495	free_AEP_LIBNAME();
496	ERR_unload_AEPHK_strings();
497	return 1;
498	}
499
500static int aep_finish(ENGINE *e)
501	{
502	int to_return = 0, in_use;
503	AEP_RV rv;
504
505	if(aep_dso == NULL)
506		{
507		AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_NOT_LOADED);
508		goto err;
509		}
510
511	rv = aep_close_all_connections(0, &in_use);
512	if (rv != AEP_R_OK)
513		{
514		AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_CLOSE_HANDLES_FAILED);
515		goto err;
516		}
517	if (in_use)
518		{
519		AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_CONNECTIONS_IN_USE);
520		goto err;
521		}
522
523	rv = p_AEP_Finalize();
524	if (rv != AEP_R_OK)
525		{
526		AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_FINALIZE_FAILED);
527		goto err;
528		}
529
530	if(!DSO_free(aep_dso))
531		{
532		AEPHKerr(AEPHK_F_AEP_FINISH,AEPHK_R_UNIT_FAILURE);
533		goto err;
534		}
535
536	aep_dso = NULL;
537	p_AEP_CloseConnection   = NULL;
538	p_AEP_OpenConnection    = NULL;
539	p_AEP_ModExp            = NULL;
540	p_AEP_ModExpCrt         = NULL;
541#ifdef AEPRAND
542	p_AEP_GenRandom         = NULL;
543#endif
544	p_AEP_Initialize        = NULL;
545	p_AEP_Finalize          = NULL;
546	p_AEP_SetBNCallBacks    = NULL;
547
548	to_return = 1;
549 err:
550	return to_return;
551	}
552
553static int aep_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
554	{
555	int initialised = ((aep_dso == NULL) ? 0 : 1);
556	switch(cmd)
557		{
558	case AEP_CMD_SO_PATH:
559		if(p == NULL)
560			{
561			AEPHKerr(AEPHK_F_AEP_CTRL,
562				ERR_R_PASSED_NULL_PARAMETER);
563			return 0;
564			}
565		if(initialised)
566			{
567			AEPHKerr(AEPHK_F_AEP_CTRL,
568				AEPHK_R_ALREADY_LOADED);
569			return 0;
570			}
571		return set_AEP_LIBNAME((const char*)p);
572	default:
573		break;
574		}
575	AEPHKerr(AEPHK_F_AEP_CTRL,AEPHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
576	return 0;
577	}
578
579static int aep_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
580	const BIGNUM *m, BN_CTX *ctx)
581	{
582	int to_return = 0;
583	int 	r_len = 0;
584	AEP_CONNECTION_HNDL hConnection;
585	AEP_RV rv;
586
587	r_len = BN_num_bits(m);
588
589	/* Perform in software if modulus is too large for hardware. */
590
591	if (r_len > max_key_len){
592		AEPHKerr(AEPHK_F_AEP_MOD_EXP, AEPHK_R_SIZE_TOO_LARGE_OR_TOO_SMALL);
593		return BN_mod_exp(r, a, p, m, ctx);
594	}
595
596	/*Grab a connection from the pool*/
597	rv = aep_get_connection(&hConnection);
598	if (rv != AEP_R_OK)
599		{
600		AEPHKerr(AEPHK_F_AEP_MOD_EXP,AEPHK_R_GET_HANDLE_FAILED);
601		return BN_mod_exp(r, a, p, m, ctx);
602		}
603
604	/*To the card with the mod exp*/
605	rv = p_AEP_ModExp(hConnection,(void*)a, (void*)p,(void*)m, (void*)r,NULL);
606
607	if (rv !=  AEP_R_OK)
608		{
609		AEPHKerr(AEPHK_F_AEP_MOD_EXP,AEPHK_R_MOD_EXP_FAILED);
610		rv = aep_close_connection(hConnection);
611		return BN_mod_exp(r, a, p, m, ctx);
612		}
613
614	/*Return the connection to the pool*/
615	rv = aep_return_connection(hConnection);
616	if (rv != AEP_R_OK)
617		{
618		AEPHKerr(AEPHK_F_AEP_RAND,AEPHK_R_RETURN_CONNECTION_FAILED);
619		goto err;
620		}
621
622	to_return = 1;
623 err:
624	return to_return;
625	}
626
627static AEP_RV aep_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
628	const BIGNUM *q, const BIGNUM *dmp1,
629	const BIGNUM *dmq1,const BIGNUM *iqmp, BN_CTX *ctx)
630	{
631	AEP_RV rv = AEP_R_OK;
632	AEP_CONNECTION_HNDL hConnection;
633
634	/*Grab a connection from the pool*/
635	rv = aep_get_connection(&hConnection);
636	if (rv != AEP_R_OK)
637		{
638		AEPHKerr(AEPHK_F_AEP_MOD_EXP_CRT,AEPHK_R_GET_HANDLE_FAILED);
639		return FAIL_TO_SW;
640		}
641
642	/*To the card with the mod exp*/
643	rv = p_AEP_ModExpCrt(hConnection,(void*)a, (void*)p, (void*)q, (void*)dmp1,(void*)dmq1,
644		(void*)iqmp,(void*)r,NULL);
645	if (rv != AEP_R_OK)
646		{
647		AEPHKerr(AEPHK_F_AEP_MOD_EXP_CRT,AEPHK_R_MOD_EXP_CRT_FAILED);
648		rv = aep_close_connection(hConnection);
649		return FAIL_TO_SW;
650		}
651
652	/*Return the connection to the pool*/
653	rv = aep_return_connection(hConnection);
654	if (rv != AEP_R_OK)
655		{
656		AEPHKerr(AEPHK_F_AEP_RAND,AEPHK_R_RETURN_CONNECTION_FAILED);
657		goto err;
658		}
659
660 err:
661	return rv;
662	}
663
664
665#ifdef AEPRAND
666static int aep_rand(unsigned char *buf,int len )
667	{
668	AEP_RV rv = AEP_R_OK;
669	AEP_CONNECTION_HNDL hConnection;
670
671	CRYPTO_w_lock(CRYPTO_LOCK_RAND);
672
673	/*Can the request be serviced with what's already in the buffer?*/
674	if (len <= rand_block_bytes)
675		{
676		memcpy(buf, &rand_block[RAND_BLK_SIZE - rand_block_bytes], len);
677		rand_block_bytes -= len;
678		CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
679		}
680	else
681		/*If not the get another block of random bytes*/
682		{
683		CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
684
685		rv = aep_get_connection(&hConnection);
686		if (rv !=  AEP_R_OK)
687			{
688			AEPHKerr(AEPHK_F_AEP_RAND,AEPHK_R_GET_HANDLE_FAILED);
689			goto err_nounlock;
690			}
691
692		if (len > RAND_BLK_SIZE)
693			{
694			rv = p_AEP_GenRandom(hConnection, len, 2, buf, NULL);
695			if (rv !=  AEP_R_OK)
696				{
697				AEPHKerr(AEPHK_F_AEP_RAND,AEPHK_R_GET_RANDOM_FAILED);
698				goto err_nounlock;
699				}
700			}
701		else
702			{
703			CRYPTO_w_lock(CRYPTO_LOCK_RAND);
704
705			rv = p_AEP_GenRandom(hConnection, RAND_BLK_SIZE, 2, &rand_block[0], NULL);
706			if (rv !=  AEP_R_OK)
707				{
708				AEPHKerr(AEPHK_F_AEP_RAND,AEPHK_R_GET_RANDOM_FAILED);
709
710				goto err;
711				}
712
713			rand_block_bytes = RAND_BLK_SIZE;
714
715			memcpy(buf, &rand_block[RAND_BLK_SIZE - rand_block_bytes], len);
716			rand_block_bytes -= len;
717
718			CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
719			}
720
721		rv = aep_return_connection(hConnection);
722		if (rv != AEP_R_OK)
723			{
724			AEPHKerr(AEPHK_F_AEP_RAND,AEPHK_R_RETURN_CONNECTION_FAILED);
725
726			goto err_nounlock;
727			}
728		}
729
730	return 1;
731 err:
732	CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
733 err_nounlock:
734	return 0;
735	}
736
737static int aep_rand_status(void)
738{
739	return 1;
740}
741#endif
742
743#ifndef OPENSSL_NO_RSA
744static int aep_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa)
745	{
746	BN_CTX *ctx = NULL;
747	int to_return = 0;
748	AEP_RV rv = AEP_R_OK;
749
750	if ((ctx = BN_CTX_new()) == NULL)
751		goto err;
752
753	if (!aep_dso)
754		{
755		AEPHKerr(AEPHK_F_AEP_RSA_MOD_EXP,AEPHK_R_NOT_LOADED);
756		goto err;
757		}
758
759	/*See if we have all the necessary bits for a crt*/
760	if (rsa->q && rsa->dmp1 && rsa->dmq1 && rsa->iqmp)
761		{
762		rv =  aep_mod_exp_crt(r0,I,rsa->p,rsa->q, rsa->dmp1,rsa->dmq1,rsa->iqmp,ctx);
763
764		if (rv == FAIL_TO_SW){
765			const RSA_METHOD *meth = RSA_PKCS1_SSLeay();
766			to_return = (*meth->rsa_mod_exp)(r0, I, rsa);
767			goto err;
768		}
769		else if (rv != AEP_R_OK)
770			goto err;
771		}
772	else
773		{
774		if (!rsa->d || !rsa->n)
775			{
776			AEPHKerr(AEPHK_F_AEP_RSA_MOD_EXP,AEPHK_R_MISSING_KEY_COMPONENTS);
777			goto err;
778			}
779
780		rv = aep_mod_exp(r0,I,rsa->d,rsa->n,ctx);
781		if  (rv != AEP_R_OK)
782			goto err;
783
784		}
785
786	to_return = 1;
787
788 err:
789	if(ctx)
790		BN_CTX_free(ctx);
791	return to_return;
792}
793#endif
794
795#ifndef OPENSSL_NO_DSA
796static int aep_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1,
797	BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m,
798	BN_CTX *ctx, BN_MONT_CTX *in_mont)
799	{
800	BIGNUM t;
801	int to_return = 0;
802	BN_init(&t);
803
804	/* let rr = a1 ^ p1 mod m */
805	if (!aep_mod_exp(rr,a1,p1,m,ctx)) goto end;
806	/* let t = a2 ^ p2 mod m */
807	if (!aep_mod_exp(&t,a2,p2,m,ctx)) goto end;
808	/* let rr = rr * t mod m */
809	if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end;
810	to_return = 1;
811 end:
812	BN_free(&t);
813	return to_return;
814	}
815
816static int aep_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a,
817	const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
818	BN_MONT_CTX *m_ctx)
819	{
820	return aep_mod_exp(r, a, p, m, ctx);
821	}
822#endif
823
824/* This function is aliased to mod_exp (with the mont stuff dropped). */
825static int aep_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
826	const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
827	{
828	return aep_mod_exp(r, a, p, m, ctx);
829	}
830
831#ifndef OPENSSL_NO_DH
832/* This function is aliased to mod_exp (with the dh and mont dropped). */
833static int aep_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a,
834	const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx,
835	BN_MONT_CTX *m_ctx)
836	{
837	return aep_mod_exp(r, a, p, m, ctx);
838	}
839#endif
840
841static AEP_RV aep_get_connection(AEP_CONNECTION_HNDL_PTR phConnection)
842	{
843	int count;
844	AEP_RV rv = AEP_R_OK;
845
846	/*Get the current process id*/
847	pid_t curr_pid;
848
849	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
850
851	curr_pid = getpid();
852
853	/*Check if this is the first time this is being called from the current
854	  process*/
855	if (recorded_pid != curr_pid)
856		{
857		/*Remember our pid so we can check if we're in a new process*/
858		recorded_pid = curr_pid;
859
860		/*Call Finalize to make sure we have not inherited some data
861		  from a parent process*/
862		p_AEP_Finalize();
863
864		/*Initialise the AEP API*/
865		rv = p_AEP_Initialize(NULL);
866
867		if (rv != AEP_R_OK)
868			{
869			AEPHKerr(AEPHK_F_AEP_GET_CONNECTION,AEPHK_R_INIT_FAILURE);
870			recorded_pid = 0;
871			goto end;
872			}
873
874		/*Set the AEP big num call back functions*/
875		rv = p_AEP_SetBNCallBacks(&GetBigNumSize, &MakeAEPBigNum,
876			&ConvertAEPBigNum);
877
878		if (rv != AEP_R_OK)
879			{
880			AEPHKerr(AEPHK_F_AEP_GET_CONNECTION,AEPHK_R_SETBNCALLBACK_FAILURE);
881			recorded_pid = 0;
882			goto end;
883			}
884
885#ifdef AEPRAND
886		/*Reset the rand byte count*/
887		rand_block_bytes = 0;
888#endif
889
890		/*Init the structures*/
891		for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
892			{
893			aep_app_conn_table[count].conn_state = NotConnected;
894			aep_app_conn_table[count].conn_hndl  = 0;
895			}
896
897		/*Open a connection*/
898		rv = p_AEP_OpenConnection(phConnection);
899
900		if (rv != AEP_R_OK)
901			{
902			AEPHKerr(AEPHK_F_AEP_GET_CONNECTION,AEPHK_R_UNIT_FAILURE);
903			recorded_pid = 0;
904			goto end;
905			}
906
907		aep_app_conn_table[0].conn_state = InUse;
908		aep_app_conn_table[0].conn_hndl = *phConnection;
909		goto end;
910		}
911	/*Check the existing connections to see if we can find a free one*/
912	for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
913		{
914		if (aep_app_conn_table[count].conn_state == Connected)
915			{
916			aep_app_conn_table[count].conn_state = InUse;
917			*phConnection = aep_app_conn_table[count].conn_hndl;
918			goto end;
919			}
920		}
921	/*If no connections available, we're going to have to try
922	  to open a new one*/
923	for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
924		{
925		if (aep_app_conn_table[count].conn_state == NotConnected)
926			{
927			/*Open a connection*/
928			rv = p_AEP_OpenConnection(phConnection);
929
930			if (rv != AEP_R_OK)
931				{
932				AEPHKerr(AEPHK_F_AEP_GET_CONNECTION,AEPHK_R_UNIT_FAILURE);
933				goto end;
934				}
935
936			aep_app_conn_table[count].conn_state = InUse;
937			aep_app_conn_table[count].conn_hndl = *phConnection;
938			goto end;
939			}
940		}
941	rv = AEP_R_GENERAL_ERROR;
942 end:
943	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
944	return rv;
945	}
946
947
948static AEP_RV aep_return_connection(AEP_CONNECTION_HNDL hConnection)
949	{
950	int count;
951
952	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
953
954	/*Find the connection item that matches this connection handle*/
955	for(count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
956		{
957		if (aep_app_conn_table[count].conn_hndl == hConnection)
958			{
959			aep_app_conn_table[count].conn_state = Connected;
960			break;
961			}
962		}
963
964	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
965
966	return AEP_R_OK;
967	}
968
969static AEP_RV aep_close_connection(AEP_CONNECTION_HNDL hConnection)
970	{
971	int count;
972	AEP_RV rv = AEP_R_OK;
973
974	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
975
976	/*Find the connection item that matches this connection handle*/
977	for(count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
978		{
979		if (aep_app_conn_table[count].conn_hndl == hConnection)
980			{
981			rv = p_AEP_CloseConnection(aep_app_conn_table[count].conn_hndl);
982			if (rv != AEP_R_OK)
983				goto end;
984			aep_app_conn_table[count].conn_state = NotConnected;
985			aep_app_conn_table[count].conn_hndl  = 0;
986			break;
987			}
988		}
989
990 end:
991	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
992	return rv;
993	}
994
995static AEP_RV aep_close_all_connections(int use_engine_lock, int *in_use)
996	{
997	int count;
998	AEP_RV rv = AEP_R_OK;
999
1000	*in_use = 0;
1001	if (use_engine_lock) CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
1002	for (count = 0;count < MAX_PROCESS_CONNECTIONS;count ++)
1003		{
1004		switch (aep_app_conn_table[count].conn_state)
1005			{
1006		case Connected:
1007			rv = p_AEP_CloseConnection(aep_app_conn_table[count].conn_hndl);
1008			if (rv != AEP_R_OK)
1009				goto end;
1010			aep_app_conn_table[count].conn_state = NotConnected;
1011			aep_app_conn_table[count].conn_hndl  = 0;
1012			break;
1013		case InUse:
1014			(*in_use)++;
1015			break;
1016		case NotConnected:
1017			break;
1018			}
1019		}
1020 end:
1021	if (use_engine_lock) CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
1022	return rv;
1023	}
1024
1025/*BigNum call back functions, used to convert OpenSSL bignums into AEP bignums.
1026  Note only 32bit Openssl build support*/
1027
1028static AEP_RV GetBigNumSize(AEP_VOID_PTR ArbBigNum, AEP_U32* BigNumSize)
1029	{
1030	BIGNUM* bn;
1031
1032	/*Cast the ArbBigNum pointer to our BIGNUM struct*/
1033	bn = (BIGNUM*) ArbBigNum;
1034
1035#ifdef SIXTY_FOUR_BIT_LONG
1036	*BigNumSize = bn->top << 3;
1037#else
1038	/*Size of the bignum in bytes is equal to the bn->top (no of 32 bit
1039	  words) multiplies by 4*/
1040	*BigNumSize = bn->top << 2;
1041#endif
1042
1043	return AEP_R_OK;
1044	}
1045
1046static AEP_RV MakeAEPBigNum(AEP_VOID_PTR ArbBigNum, AEP_U32 BigNumSize,
1047	unsigned char* AEP_BigNum)
1048	{
1049	BIGNUM* bn;
1050
1051#ifndef SIXTY_FOUR_BIT_LONG
1052	unsigned char* buf;
1053	int i;
1054#endif
1055
1056	/*Cast the ArbBigNum pointer to our BIGNUM struct*/
1057	bn = (BIGNUM*) ArbBigNum;
1058
1059#ifdef SIXTY_FOUR_BIT_LONG
1060  	memcpy(AEP_BigNum, bn->d, BigNumSize);
1061#else
1062	/*Must copy data into a (monotone) least significant byte first format
1063	  performing endian conversion if necessary*/
1064	for(i=0;i<bn->top;i++)
1065		{
1066		buf = (unsigned char*)&bn->d[i];
1067
1068		*((AEP_U32*)AEP_BigNum) = (AEP_U32)
1069			((unsigned) buf[1] << 8 | buf[0]) |
1070			((unsigned) buf[3] << 8 | buf[2])  << 16;
1071
1072		AEP_BigNum += 4;
1073		}
1074#endif
1075
1076	return AEP_R_OK;
1077	}
1078
1079/*Turn an AEP Big Num back to a user big num*/
1080static AEP_RV ConvertAEPBigNum(void* ArbBigNum, AEP_U32 BigNumSize,
1081	unsigned char* AEP_BigNum)
1082	{
1083	BIGNUM* bn;
1084#ifndef SIXTY_FOUR_BIT_LONG
1085	int i;
1086#endif
1087
1088	bn = (BIGNUM*)ArbBigNum;
1089
1090	/*Expand the result bn so that it can hold our big num.
1091	  Size is in bits*/
1092	bn_expand(bn, (int)(BigNumSize << 3));
1093
1094#ifdef SIXTY_FOUR_BIT_LONG
1095	bn->top = BigNumSize >> 3;
1096
1097	if((BigNumSize & 7) != 0)
1098		bn->top++;
1099
1100	memset(bn->d, 0, bn->top << 3);
1101
1102	memcpy(bn->d, AEP_BigNum, BigNumSize);
1103#else
1104	bn->top = BigNumSize >> 2;
1105
1106	for(i=0;i<bn->top;i++)
1107		{
1108		bn->d[i] = (AEP_U32)
1109			((unsigned) AEP_BigNum[3] << 8 | AEP_BigNum[2]) << 16 |
1110			((unsigned) AEP_BigNum[1] << 8 | AEP_BigNum[0]);
1111		AEP_BigNum += 4;
1112		}
1113#endif
1114
1115	return AEP_R_OK;
1116}
1117
1118#endif /* !OPENSSL_NO_HW_AEP */
1119#endif /* !OPENSSL_NO_HW */
1120