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