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