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