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