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