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