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