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