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