e_4758cca.c revision 296465
1/* Author: Maurice Gittens <maurice@gittens.nl> */ 2/* ==================================================================== 3 * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in 14 * the documentation and/or other materials provided with the 15 * distribution. 16 * 17 * 3. All advertising materials mentioning features or use of this 18 * software must display the following acknowledgment: 19 * "This product includes software developed by the OpenSSL Project 20 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 21 * 22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23 * endorse or promote products derived from this software without 24 * prior written permission. For written permission, please contact 25 * licensing@OpenSSL.org. 26 * 27 * 5. Products derived from this software may not be called "OpenSSL" 28 * nor may "OpenSSL" appear in their names without prior written 29 * permission of the OpenSSL Project. 30 * 31 * 6. Redistributions of any form whatsoever must retain the following 32 * acknowledgment: 33 * "This product includes software developed by the OpenSSL Project 34 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 35 * 36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47 * OF THE POSSIBILITY OF SUCH DAMAGE. 48 * ==================================================================== 49 * 50 * This product includes cryptographic software written by Eric Young 51 * (eay@cryptsoft.com). This product includes software written by Tim 52 * Hudson (tjh@cryptsoft.com). 53 * 54 */ 55 56#include <stdio.h> 57#include <string.h> 58#include <openssl/crypto.h> 59#include <openssl/dso.h> 60#include <openssl/x509.h> 61#include <openssl/objects.h> 62#include <openssl/engine.h> 63#include <openssl/rand.h> 64#ifndef OPENSSL_NO_RSA 65# include <openssl/rsa.h> 66#endif 67#include <openssl/bn.h> 68 69#ifndef OPENSSL_NO_HW 70# ifndef OPENSSL_NO_HW_4758_CCA 71 72# ifdef FLAT_INC 73# include "hw_4758_cca.h" 74# else 75# include "vendor_defns/hw_4758_cca.h" 76# endif 77 78# include "e_4758cca_err.c" 79 80static int ibm_4758_cca_destroy(ENGINE *e); 81static int ibm_4758_cca_init(ENGINE *e); 82static int ibm_4758_cca_finish(ENGINE *e); 83static int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p, 84 void (*f) (void)); 85 86/* rsa functions */ 87/* -------------*/ 88# ifndef OPENSSL_NO_RSA 89static int cca_rsa_pub_enc(int flen, const unsigned char *from, 90 unsigned char *to, RSA *rsa, int padding); 91static int cca_rsa_priv_dec(int flen, const unsigned char *from, 92 unsigned char *to, RSA *rsa, int padding); 93static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len, 94 unsigned char *sigret, unsigned int *siglen, 95 const RSA *rsa); 96static int cca_rsa_verify(int dtype, const unsigned char *m, 97 unsigned int m_len, unsigned char *sigbuf, 98 unsigned int siglen, const RSA *rsa); 99 100/* utility functions */ 101/* ---------------------*/ 102static EVP_PKEY *ibm_4758_load_privkey(ENGINE *, const char *, 103 UI_METHOD *ui_method, 104 void *callback_data); 105static EVP_PKEY *ibm_4758_load_pubkey(ENGINE *, const char *, 106 UI_METHOD *ui_method, 107 void *callback_data); 108 109static int getModulusAndExponent(const unsigned char *token, 110 long *exponentLength, 111 unsigned char *exponent, long *modulusLength, 112 long *modulusFieldLength, 113 unsigned char *modulus); 114# endif 115 116/* RAND number functions */ 117/* ---------------------*/ 118static int cca_get_random_bytes(unsigned char *, int); 119static int cca_random_status(void); 120 121# ifndef OPENSSL_NO_RSA 122static void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad, 123 int idx, long argl, void *argp); 124# endif 125 126/* Function pointers for CCA verbs */ 127/* -------------------------------*/ 128# ifndef OPENSSL_NO_RSA 129static F_KEYRECORDREAD keyRecordRead; 130static F_DIGITALSIGNATUREGENERATE digitalSignatureGenerate; 131static F_DIGITALSIGNATUREVERIFY digitalSignatureVerify; 132static F_PUBLICKEYEXTRACT publicKeyExtract; 133static F_PKAENCRYPT pkaEncrypt; 134static F_PKADECRYPT pkaDecrypt; 135# endif 136static F_RANDOMNUMBERGENERATE randomNumberGenerate; 137 138/* static variables */ 139/* ----------------*/ 140static const char *CCA4758_LIB_NAME = NULL; 141static const char *get_CCA4758_LIB_NAME(void) 142{ 143 if (CCA4758_LIB_NAME) 144 return CCA4758_LIB_NAME; 145 return CCA_LIB_NAME; 146} 147 148static void free_CCA4758_LIB_NAME(void) 149{ 150 if (CCA4758_LIB_NAME) 151 OPENSSL_free((void *)CCA4758_LIB_NAME); 152 CCA4758_LIB_NAME = NULL; 153} 154 155static long set_CCA4758_LIB_NAME(const char *name) 156{ 157 free_CCA4758_LIB_NAME(); 158 return (((CCA4758_LIB_NAME = BUF_strdup(name)) != NULL) ? 1 : 0); 159} 160 161# ifndef OPENSSL_NO_RSA 162static const char *n_keyRecordRead = CSNDKRR; 163static const char *n_digitalSignatureGenerate = CSNDDSG; 164static const char *n_digitalSignatureVerify = CSNDDSV; 165static const char *n_publicKeyExtract = CSNDPKX; 166static const char *n_pkaEncrypt = CSNDPKE; 167static const char *n_pkaDecrypt = CSNDPKD; 168# endif 169static const char *n_randomNumberGenerate = CSNBRNG; 170 171# ifndef OPENSSL_NO_RSA 172static int hndidx = -1; 173# endif 174static DSO *dso = NULL; 175 176/* openssl engine initialization structures */ 177/* ----------------------------------------*/ 178 179# define CCA4758_CMD_SO_PATH ENGINE_CMD_BASE 180static const ENGINE_CMD_DEFN cca4758_cmd_defns[] = { 181 {CCA4758_CMD_SO_PATH, 182 "SO_PATH", 183 "Specifies the path to the '4758cca' shared library", 184 ENGINE_CMD_FLAG_STRING}, 185 {0, NULL, NULL, 0} 186}; 187 188# ifndef OPENSSL_NO_RSA 189static RSA_METHOD ibm_4758_cca_rsa = { 190 "IBM 4758 CCA RSA method", 191 cca_rsa_pub_enc, 192 NULL, 193 NULL, 194 cca_rsa_priv_dec, 195 NULL, /* rsa_mod_exp, */ 196 NULL, /* mod_exp_mont, */ 197 NULL, /* init */ 198 NULL, /* finish */ 199 RSA_FLAG_SIGN_VER, /* flags */ 200 NULL, /* app_data */ 201 cca_rsa_sign, /* rsa_sign */ 202 cca_rsa_verify, /* rsa_verify */ 203 NULL /* rsa_keygen */ 204}; 205# endif 206 207static RAND_METHOD ibm_4758_cca_rand = { 208 /* "IBM 4758 RAND method", */ 209 NULL, /* seed */ 210 cca_get_random_bytes, /* get random bytes from the card */ 211 NULL, /* cleanup */ 212 NULL, /* add */ 213 cca_get_random_bytes, /* pseudo rand */ 214 cca_random_status, /* status */ 215}; 216 217static const char *engine_4758_cca_id = "4758cca"; 218static const char *engine_4758_cca_name = 219 "IBM 4758 CCA hardware engine support"; 220# ifndef OPENSSL_NO_DYNAMIC_ENGINE 221/* Compatibility hack, the dynamic library uses this form in the path */ 222static const char *engine_4758_cca_id_alt = "4758_cca"; 223# endif 224 225/* engine implementation */ 226/* ---------------------*/ 227static int bind_helper(ENGINE *e) 228{ 229 if (!ENGINE_set_id(e, engine_4758_cca_id) || 230 !ENGINE_set_name(e, engine_4758_cca_name) || 231# ifndef OPENSSL_NO_RSA 232 !ENGINE_set_RSA(e, &ibm_4758_cca_rsa) || 233# endif 234 !ENGINE_set_RAND(e, &ibm_4758_cca_rand) || 235 !ENGINE_set_destroy_function(e, ibm_4758_cca_destroy) || 236 !ENGINE_set_init_function(e, ibm_4758_cca_init) || 237 !ENGINE_set_finish_function(e, ibm_4758_cca_finish) || 238 !ENGINE_set_ctrl_function(e, ibm_4758_cca_ctrl) || 239# ifndef OPENSSL_NO_RSA 240 !ENGINE_set_load_privkey_function(e, ibm_4758_load_privkey) || 241 !ENGINE_set_load_pubkey_function(e, ibm_4758_load_pubkey) || 242# endif 243 !ENGINE_set_cmd_defns(e, cca4758_cmd_defns)) 244 return 0; 245 /* Ensure the error handling is set up */ 246 ERR_load_CCA4758_strings(); 247 return 1; 248} 249 250# ifdef OPENSSL_NO_DYNAMIC_ENGINE 251static ENGINE *engine_4758_cca(void) 252{ 253 ENGINE *ret = ENGINE_new(); 254 if (!ret) 255 return NULL; 256 if (!bind_helper(ret)) { 257 ENGINE_free(ret); 258 return NULL; 259 } 260 return ret; 261} 262 263void ENGINE_load_4758cca(void) 264{ 265 ENGINE *e_4758 = engine_4758_cca(); 266 if (!e_4758) 267 return; 268 ENGINE_add(e_4758); 269 ENGINE_free(e_4758); 270 ERR_clear_error(); 271} 272# endif 273 274static int ibm_4758_cca_destroy(ENGINE *e) 275{ 276 ERR_unload_CCA4758_strings(); 277 free_CCA4758_LIB_NAME(); 278 return 1; 279} 280 281static int ibm_4758_cca_init(ENGINE *e) 282{ 283 if (dso) { 284 CCA4758err(CCA4758_F_IBM_4758_CCA_INIT, CCA4758_R_ALREADY_LOADED); 285 goto err; 286 } 287 288 dso = DSO_load(NULL, get_CCA4758_LIB_NAME(), NULL, 0); 289 if (!dso) { 290 CCA4758err(CCA4758_F_IBM_4758_CCA_INIT, CCA4758_R_DSO_FAILURE); 291 goto err; 292 } 293# ifndef OPENSSL_NO_RSA 294 if (!(keyRecordRead = (F_KEYRECORDREAD) 295 DSO_bind_func(dso, n_keyRecordRead)) || 296 !(randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 297 DSO_bind_func(dso, n_randomNumberGenerate)) || 298 !(digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE) 299 DSO_bind_func(dso, n_digitalSignatureGenerate)) || 300 !(digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY) 301 DSO_bind_func(dso, n_digitalSignatureVerify)) || 302 !(publicKeyExtract = (F_PUBLICKEYEXTRACT) 303 DSO_bind_func(dso, n_publicKeyExtract)) || 304 !(pkaEncrypt = (F_PKAENCRYPT) 305 DSO_bind_func(dso, n_pkaEncrypt)) || !(pkaDecrypt = (F_PKADECRYPT) 306 DSO_bind_func(dso, 307 n_pkaDecrypt))) 308 { 309 CCA4758err(CCA4758_F_IBM_4758_CCA_INIT, CCA4758_R_DSO_FAILURE); 310 goto err; 311 } 312# else 313 if (!(randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 314 DSO_bind_func(dso, n_randomNumberGenerate))) { 315 CCA4758err(CCA4758_F_IBM_4758_CCA_INIT, CCA4758_R_DSO_FAILURE); 316 goto err; 317 } 318# endif 319 320# ifndef OPENSSL_NO_RSA 321 hndidx = RSA_get_ex_new_index(0, "IBM 4758 CCA RSA key handle", 322 NULL, NULL, cca_ex_free); 323# endif 324 325 return 1; 326 err: 327 if (dso) 328 DSO_free(dso); 329 dso = NULL; 330 331# ifndef OPENSSL_NO_RSA 332 keyRecordRead = (F_KEYRECORDREAD) 0; 333 digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE) 0; 334 digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0; 335 publicKeyExtract = (F_PUBLICKEYEXTRACT)0; 336 pkaEncrypt = (F_PKAENCRYPT) 0; 337 pkaDecrypt = (F_PKADECRYPT) 0; 338# endif 339 randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 0; 340 return 0; 341} 342 343static int ibm_4758_cca_finish(ENGINE *e) 344{ 345 free_CCA4758_LIB_NAME(); 346 if (!dso) { 347 CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH, CCA4758_R_NOT_LOADED); 348 return 0; 349 } 350 if (!DSO_free(dso)) { 351 CCA4758err(CCA4758_F_IBM_4758_CCA_FINISH, CCA4758_R_UNIT_FAILURE); 352 return 0; 353 } 354 dso = NULL; 355# ifndef OPENSSL_NO_RSA 356 keyRecordRead = (F_KEYRECORDREAD) 0; 357 randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 0; 358 digitalSignatureGenerate = (F_DIGITALSIGNATUREGENERATE) 0; 359 digitalSignatureVerify = (F_DIGITALSIGNATUREVERIFY)0; 360 publicKeyExtract = (F_PUBLICKEYEXTRACT)0; 361 pkaEncrypt = (F_PKAENCRYPT) 0; 362 pkaDecrypt = (F_PKADECRYPT) 0; 363# endif 364 randomNumberGenerate = (F_RANDOMNUMBERGENERATE) 0; 365 return 1; 366} 367 368static int ibm_4758_cca_ctrl(ENGINE *e, int cmd, long i, void *p, 369 void (*f) (void)) 370{ 371 int initialised = ((dso == NULL) ? 0 : 1); 372 switch (cmd) { 373 case CCA4758_CMD_SO_PATH: 374 if (p == NULL) { 375 CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL, 376 ERR_R_PASSED_NULL_PARAMETER); 377 return 0; 378 } 379 if (initialised) { 380 CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL, CCA4758_R_ALREADY_LOADED); 381 return 0; 382 } 383 return set_CCA4758_LIB_NAME((const char *)p); 384 default: 385 break; 386 } 387 CCA4758err(CCA4758_F_IBM_4758_CCA_CTRL, 388 CCA4758_R_COMMAND_NOT_IMPLEMENTED); 389 return 0; 390} 391 392# ifndef OPENSSL_NO_RSA 393 394# define MAX_CCA_PKA_TOKEN_SIZE 2500 395 396static EVP_PKEY *ibm_4758_load_privkey(ENGINE *e, const char *key_id, 397 UI_METHOD *ui_method, 398 void *callback_data) 399{ 400 RSA *rtmp = NULL; 401 EVP_PKEY *res = NULL; 402 unsigned char *keyToken = NULL; 403 unsigned char pubKeyToken[MAX_CCA_PKA_TOKEN_SIZE]; 404 long pubKeyTokenLength = MAX_CCA_PKA_TOKEN_SIZE; 405 long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE; 406 long returnCode; 407 long reasonCode; 408 long exitDataLength = 0; 409 long ruleArrayLength = 0; 410 unsigned char exitData[8]; 411 unsigned char ruleArray[8]; 412 unsigned char keyLabel[64]; 413 unsigned long keyLabelLength = strlen(key_id); 414 unsigned char modulus[256]; 415 long modulusFieldLength = sizeof(modulus); 416 long modulusLength = 0; 417 unsigned char exponent[256]; 418 long exponentLength = sizeof(exponent); 419 420 if (keyLabelLength > sizeof(keyLabel)) { 421 CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY, 422 CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL); 423 return NULL; 424 } 425 426 memset(keyLabel, ' ', sizeof(keyLabel)); 427 memcpy(keyLabel, key_id, keyLabelLength); 428 429 keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long)); 430 if (!keyToken) { 431 CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE); 432 goto err; 433 } 434 435 keyRecordRead(&returnCode, &reasonCode, &exitDataLength, 436 exitData, &ruleArrayLength, ruleArray, keyLabel, 437 &keyTokenLength, keyToken + sizeof(long)); 438 439 if (returnCode) { 440 CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY, 441 CCA4758_R_FAILED_LOADING_PRIVATE_KEY); 442 goto err; 443 } 444 445 publicKeyExtract(&returnCode, &reasonCode, &exitDataLength, 446 exitData, &ruleArrayLength, ruleArray, &keyTokenLength, 447 keyToken + sizeof(long), &pubKeyTokenLength, 448 pubKeyToken); 449 450 if (returnCode) { 451 CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY, 452 CCA4758_R_FAILED_LOADING_PRIVATE_KEY); 453 goto err; 454 } 455 456 if (!getModulusAndExponent(pubKeyToken, &exponentLength, 457 exponent, &modulusLength, &modulusFieldLength, 458 modulus)) { 459 CCA4758err(CCA4758_F_IBM_4758_LOAD_PRIVKEY, 460 CCA4758_R_FAILED_LOADING_PRIVATE_KEY); 461 goto err; 462 } 463 464 (*(long *)keyToken) = keyTokenLength; 465 rtmp = RSA_new_method(e); 466 RSA_set_ex_data(rtmp, hndidx, (char *)keyToken); 467 468 rtmp->e = BN_bin2bn(exponent, exponentLength, NULL); 469 rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL); 470 rtmp->flags |= RSA_FLAG_EXT_PKEY; 471 472 res = EVP_PKEY_new(); 473 EVP_PKEY_assign_RSA(res, rtmp); 474 475 return res; 476 err: 477 if (keyToken) 478 OPENSSL_free(keyToken); 479 if (res) 480 EVP_PKEY_free(res); 481 if (rtmp) 482 RSA_free(rtmp); 483 return NULL; 484} 485 486static EVP_PKEY *ibm_4758_load_pubkey(ENGINE *e, const char *key_id, 487 UI_METHOD *ui_method, 488 void *callback_data) 489{ 490 RSA *rtmp = NULL; 491 EVP_PKEY *res = NULL; 492 unsigned char *keyToken = NULL; 493 long keyTokenLength = MAX_CCA_PKA_TOKEN_SIZE; 494 long returnCode; 495 long reasonCode; 496 long exitDataLength = 0; 497 long ruleArrayLength = 0; 498 unsigned char exitData[8]; 499 unsigned char ruleArray[8]; 500 unsigned char keyLabel[64]; 501 unsigned long keyLabelLength = strlen(key_id); 502 unsigned char modulus[512]; 503 long modulusFieldLength = sizeof(modulus); 504 long modulusLength = 0; 505 unsigned char exponent[512]; 506 long exponentLength = sizeof(exponent); 507 508 if (keyLabelLength > sizeof(keyLabel)) { 509 CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, 510 CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL); 511 return NULL; 512 } 513 514 memset(keyLabel, ' ', sizeof(keyLabel)); 515 memcpy(keyLabel, key_id, keyLabelLength); 516 517 keyToken = OPENSSL_malloc(MAX_CCA_PKA_TOKEN_SIZE + sizeof(long)); 518 if (!keyToken) { 519 CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE); 520 goto err; 521 } 522 523 keyRecordRead(&returnCode, &reasonCode, &exitDataLength, exitData, 524 &ruleArrayLength, ruleArray, keyLabel, &keyTokenLength, 525 keyToken + sizeof(long)); 526 527 if (returnCode) { 528 CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, ERR_R_MALLOC_FAILURE); 529 goto err; 530 } 531 532 if (!getModulusAndExponent(keyToken + sizeof(long), &exponentLength, 533 exponent, &modulusLength, &modulusFieldLength, 534 modulus)) { 535 CCA4758err(CCA4758_F_IBM_4758_LOAD_PUBKEY, 536 CCA4758_R_FAILED_LOADING_PUBLIC_KEY); 537 goto err; 538 } 539 540 (*(long *)keyToken) = keyTokenLength; 541 rtmp = RSA_new_method(e); 542 RSA_set_ex_data(rtmp, hndidx, (char *)keyToken); 543 rtmp->e = BN_bin2bn(exponent, exponentLength, NULL); 544 rtmp->n = BN_bin2bn(modulus, modulusFieldLength, NULL); 545 rtmp->flags |= RSA_FLAG_EXT_PKEY; 546 res = EVP_PKEY_new(); 547 EVP_PKEY_assign_RSA(res, rtmp); 548 549 return res; 550 err: 551 if (keyToken) 552 OPENSSL_free(keyToken); 553 if (res) 554 EVP_PKEY_free(res); 555 if (rtmp) 556 RSA_free(rtmp); 557 return NULL; 558} 559 560static int cca_rsa_pub_enc(int flen, const unsigned char *from, 561 unsigned char *to, RSA *rsa, int padding) 562{ 563 long returnCode; 564 long reasonCode; 565 long lflen = flen; 566 long exitDataLength = 0; 567 unsigned char exitData[8]; 568 long ruleArrayLength = 1; 569 unsigned char ruleArray[8] = "PKCS-1.2"; 570 long dataStructureLength = 0; 571 unsigned char dataStructure[8]; 572 long outputLength = RSA_size(rsa); 573 long keyTokenLength; 574 unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx); 575 576 keyTokenLength = *(long *)keyToken; 577 keyToken += sizeof(long); 578 579 pkaEncrypt(&returnCode, &reasonCode, &exitDataLength, exitData, 580 &ruleArrayLength, ruleArray, &lflen, (unsigned char *)from, 581 &dataStructureLength, dataStructure, &keyTokenLength, 582 keyToken, &outputLength, to); 583 584 if (returnCode || reasonCode) 585 return -(returnCode << 16 | reasonCode); 586 return outputLength; 587} 588 589static int cca_rsa_priv_dec(int flen, const unsigned char *from, 590 unsigned char *to, RSA *rsa, int padding) 591{ 592 long returnCode; 593 long reasonCode; 594 long lflen = flen; 595 long exitDataLength = 0; 596 unsigned char exitData[8]; 597 long ruleArrayLength = 1; 598 unsigned char ruleArray[8] = "PKCS-1.2"; 599 long dataStructureLength = 0; 600 unsigned char dataStructure[8]; 601 long outputLength = RSA_size(rsa); 602 long keyTokenLength; 603 unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx); 604 605 keyTokenLength = *(long *)keyToken; 606 keyToken += sizeof(long); 607 608 pkaDecrypt(&returnCode, &reasonCode, &exitDataLength, exitData, 609 &ruleArrayLength, ruleArray, &lflen, (unsigned char *)from, 610 &dataStructureLength, dataStructure, &keyTokenLength, 611 keyToken, &outputLength, to); 612 613 return (returnCode | reasonCode) ? 0 : 1; 614} 615 616# define SSL_SIG_LEN 36 617 618static int cca_rsa_verify(int type, const unsigned char *m, 619 unsigned int m_len, unsigned char *sigbuf, 620 unsigned int siglen, const RSA *rsa) 621{ 622 long returnCode; 623 long reasonCode; 624 long lsiglen = siglen; 625 long exitDataLength = 0; 626 unsigned char exitData[8]; 627 long ruleArrayLength = 1; 628 unsigned char ruleArray[8] = "PKCS-1.1"; 629 long keyTokenLength; 630 unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx); 631 long length = SSL_SIG_LEN; 632 long keyLength; 633 unsigned char *hashBuffer = NULL; 634 X509_SIG sig; 635 ASN1_TYPE parameter; 636 X509_ALGOR algorithm; 637 ASN1_OCTET_STRING digest; 638 639 keyTokenLength = *(long *)keyToken; 640 keyToken += sizeof(long); 641 642 if (type == NID_md5 || type == NID_sha1) { 643 sig.algor = &algorithm; 644 algorithm.algorithm = OBJ_nid2obj(type); 645 646 if (!algorithm.algorithm) { 647 CCA4758err(CCA4758_F_CCA_RSA_VERIFY, 648 CCA4758_R_UNKNOWN_ALGORITHM_TYPE); 649 return 0; 650 } 651 652 if (!algorithm.algorithm->length) { 653 CCA4758err(CCA4758_F_CCA_RSA_VERIFY, 654 CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD); 655 return 0; 656 } 657 658 parameter.type = V_ASN1_NULL; 659 parameter.value.ptr = NULL; 660 algorithm.parameter = ¶meter; 661 662 sig.digest = &digest; 663 sig.digest->data = (unsigned char *)m; 664 sig.digest->length = m_len; 665 666 length = i2d_X509_SIG(&sig, NULL); 667 } 668 669 keyLength = RSA_size(rsa); 670 671 if (length - RSA_PKCS1_PADDING > keyLength) { 672 CCA4758err(CCA4758_F_CCA_RSA_VERIFY, 673 CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL); 674 return 0; 675 } 676 677 switch (type) { 678 case NID_md5_sha1: 679 if (m_len != SSL_SIG_LEN) { 680 CCA4758err(CCA4758_F_CCA_RSA_VERIFY, 681 CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL); 682 return 0; 683 } 684 685 hashBuffer = (unsigned char *)m; 686 length = m_len; 687 break; 688 case NID_md5: 689 { 690 unsigned char *ptr; 691 ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1); 692 if (!hashBuffer) { 693 CCA4758err(CCA4758_F_CCA_RSA_VERIFY, ERR_R_MALLOC_FAILURE); 694 return 0; 695 } 696 697 i2d_X509_SIG(&sig, &ptr); 698 } 699 break; 700 case NID_sha1: 701 { 702 unsigned char *ptr; 703 ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1); 704 if (!hashBuffer) { 705 CCA4758err(CCA4758_F_CCA_RSA_VERIFY, ERR_R_MALLOC_FAILURE); 706 return 0; 707 } 708 i2d_X509_SIG(&sig, &ptr); 709 } 710 break; 711 default: 712 return 0; 713 } 714 715 digitalSignatureVerify(&returnCode, &reasonCode, &exitDataLength, 716 exitData, &ruleArrayLength, ruleArray, 717 &keyTokenLength, keyToken, &length, hashBuffer, 718 &lsiglen, sigbuf); 719 720 if (type == NID_sha1 || type == NID_md5) { 721 OPENSSL_cleanse(hashBuffer, keyLength + 1); 722 OPENSSL_free(hashBuffer); 723 } 724 725 return ((returnCode || reasonCode) ? 0 : 1); 726} 727 728# define SSL_SIG_LEN 36 729 730static int cca_rsa_sign(int type, const unsigned char *m, unsigned int m_len, 731 unsigned char *sigret, unsigned int *siglen, 732 const RSA *rsa) 733{ 734 long returnCode; 735 long reasonCode; 736 long exitDataLength = 0; 737 unsigned char exitData[8]; 738 long ruleArrayLength = 1; 739 unsigned char ruleArray[8] = "PKCS-1.1"; 740 long outputLength = 256; 741 long outputBitLength; 742 long keyTokenLength; 743 unsigned char *hashBuffer = NULL; 744 unsigned char *keyToken = (unsigned char *)RSA_get_ex_data(rsa, hndidx); 745 long length = SSL_SIG_LEN; 746 long keyLength; 747 X509_SIG sig; 748 ASN1_TYPE parameter; 749 X509_ALGOR algorithm; 750 ASN1_OCTET_STRING digest; 751 752 keyTokenLength = *(long *)keyToken; 753 keyToken += sizeof(long); 754 755 if (type == NID_md5 || type == NID_sha1) { 756 sig.algor = &algorithm; 757 algorithm.algorithm = OBJ_nid2obj(type); 758 759 if (!algorithm.algorithm) { 760 CCA4758err(CCA4758_F_CCA_RSA_SIGN, 761 CCA4758_R_UNKNOWN_ALGORITHM_TYPE); 762 return 0; 763 } 764 765 if (!algorithm.algorithm->length) { 766 CCA4758err(CCA4758_F_CCA_RSA_SIGN, 767 CCA4758_R_ASN1_OID_UNKNOWN_FOR_MD); 768 return 0; 769 } 770 771 parameter.type = V_ASN1_NULL; 772 parameter.value.ptr = NULL; 773 algorithm.parameter = ¶meter; 774 775 sig.digest = &digest; 776 sig.digest->data = (unsigned char *)m; 777 sig.digest->length = m_len; 778 779 length = i2d_X509_SIG(&sig, NULL); 780 } 781 782 keyLength = RSA_size(rsa); 783 784 if (length - RSA_PKCS1_PADDING > keyLength) { 785 CCA4758err(CCA4758_F_CCA_RSA_SIGN, 786 CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL); 787 return 0; 788 } 789 790 switch (type) { 791 case NID_md5_sha1: 792 if (m_len != SSL_SIG_LEN) { 793 CCA4758err(CCA4758_F_CCA_RSA_SIGN, 794 CCA4758_R_SIZE_TOO_LARGE_OR_TOO_SMALL); 795 return 0; 796 } 797 hashBuffer = (unsigned char *)m; 798 length = m_len; 799 break; 800 case NID_md5: 801 { 802 unsigned char *ptr; 803 ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1); 804 if (!hashBuffer) { 805 CCA4758err(CCA4758_F_CCA_RSA_SIGN, ERR_R_MALLOC_FAILURE); 806 return 0; 807 } 808 i2d_X509_SIG(&sig, &ptr); 809 } 810 break; 811 case NID_sha1: 812 { 813 unsigned char *ptr; 814 ptr = hashBuffer = OPENSSL_malloc((unsigned int)keyLength + 1); 815 if (!hashBuffer) { 816 CCA4758err(CCA4758_F_CCA_RSA_SIGN, ERR_R_MALLOC_FAILURE); 817 return 0; 818 } 819 i2d_X509_SIG(&sig, &ptr); 820 } 821 break; 822 default: 823 return 0; 824 } 825 826 digitalSignatureGenerate(&returnCode, &reasonCode, &exitDataLength, 827 exitData, &ruleArrayLength, ruleArray, 828 &keyTokenLength, keyToken, &length, hashBuffer, 829 &outputLength, &outputBitLength, sigret); 830 831 if (type == NID_sha1 || type == NID_md5) { 832 OPENSSL_cleanse(hashBuffer, keyLength + 1); 833 OPENSSL_free(hashBuffer); 834 } 835 836 *siglen = outputLength; 837 838 return ((returnCode || reasonCode) ? 0 : 1); 839} 840 841static int getModulusAndExponent(const unsigned char *token, 842 long *exponentLength, 843 unsigned char *exponent, long *modulusLength, 844 long *modulusFieldLength, 845 unsigned char *modulus) 846{ 847 unsigned long len; 848 849 if (*token++ != (char)0x1E) /* internal PKA token? */ 850 return 0; 851 852 if (*token++) /* token version must be zero */ 853 return 0; 854 855 len = *token++; 856 len = len << 8; 857 len |= (unsigned char)*token++; 858 859 token += 4; /* skip reserved bytes */ 860 861 if (*token++ == (char)0x04) { 862 if (*token++) /* token version must be zero */ 863 return 0; 864 865 len = *token++; 866 len = len << 8; 867 len |= (unsigned char)*token++; 868 869 token += 2; /* skip reserved section */ 870 871 len = *token++; 872 len = len << 8; 873 len |= (unsigned char)*token++; 874 875 *exponentLength = len; 876 877 len = *token++; 878 len = len << 8; 879 len |= (unsigned char)*token++; 880 881 *modulusLength = len; 882 883 len = *token++; 884 len = len << 8; 885 len |= (unsigned char)*token++; 886 887 *modulusFieldLength = len; 888 889 memcpy(exponent, token, *exponentLength); 890 token += *exponentLength; 891 892 memcpy(modulus, token, *modulusFieldLength); 893 return 1; 894 } 895 return 0; 896} 897 898# endif /* OPENSSL_NO_RSA */ 899 900static int cca_random_status(void) 901{ 902 return 1; 903} 904 905static int cca_get_random_bytes(unsigned char *buf, int num) 906{ 907 long ret_code; 908 long reason_code; 909 long exit_data_length; 910 unsigned char exit_data[4]; 911 unsigned char form[] = "RANDOM "; 912 unsigned char rand_buf[8]; 913 914 while (num >= (int)sizeof(rand_buf)) { 915 randomNumberGenerate(&ret_code, &reason_code, &exit_data_length, 916 exit_data, form, rand_buf); 917 if (ret_code) 918 return 0; 919 num -= sizeof(rand_buf); 920 memcpy(buf, rand_buf, sizeof(rand_buf)); 921 buf += sizeof(rand_buf); 922 } 923 924 if (num) { 925 randomNumberGenerate(&ret_code, &reason_code, NULL, NULL, 926 form, rand_buf); 927 if (ret_code) 928 return 0; 929 memcpy(buf, rand_buf, num); 930 } 931 932 return 1; 933} 934 935# ifndef OPENSSL_NO_RSA 936static void cca_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad, int idx, 937 long argl, void *argp) 938{ 939 if (item) 940 OPENSSL_free(item); 941} 942# endif 943 944/* Goo to handle building as a dynamic engine */ 945# ifndef OPENSSL_NO_DYNAMIC_ENGINE 946static int bind_fn(ENGINE *e, const char *id) 947{ 948 if (id && (strcmp(id, engine_4758_cca_id) != 0) && 949 (strcmp(id, engine_4758_cca_id_alt) != 0)) 950 return 0; 951 if (!bind_helper(e)) 952 return 0; 953 return 1; 954} 955 956IMPLEMENT_DYNAMIC_CHECK_FN() 957 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) 958# endif /* OPENSSL_NO_DYNAMIC_ENGINE */ 959# endif /* !OPENSSL_NO_HW_4758_CCA */ 960#endif /* !OPENSSL_NO_HW */ 961