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