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