1/* crypto/engine/hw_ubsec.c */ 2/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL 3 * project 2000. 4 * 5 * Cloned shamelessly by Joe Tardo. 6 */ 7/* ==================================================================== 8 * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in 19 * the documentation and/or other materials provided with the 20 * distribution. 21 * 22 * 3. All advertising materials mentioning features or use of this 23 * software must display the following acknowledgment: 24 * "This product includes software developed by the OpenSSL Project 25 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 26 * 27 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 28 * endorse or promote products derived from this software without 29 * prior written permission. For written permission, please contact 30 * licensing@OpenSSL.org. 31 * 32 * 5. Products derived from this software may not be called "OpenSSL" 33 * nor may "OpenSSL" appear in their names without prior written 34 * permission of the OpenSSL Project. 35 * 36 * 6. Redistributions of any form whatsoever must retain the following 37 * acknowledgment: 38 * "This product includes software developed by the OpenSSL Project 39 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 42 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 44 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 48 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 50 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 51 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 52 * OF THE POSSIBILITY OF SUCH DAMAGE. 53 * ==================================================================== 54 * 55 * This product includes cryptographic software written by Eric Young 56 * (eay@cryptsoft.com). This product includes software written by Tim 57 * Hudson (tjh@cryptsoft.com). 58 * 59 */ 60 61#include <stdio.h> 62#include <string.h> 63#include <openssl/crypto.h> 64#include <openssl/buffer.h> 65#include <openssl/dso.h> 66#include <openssl/engine.h> 67#ifndef OPENSSL_NO_RSA 68#include <openssl/rsa.h> 69#endif 70#ifndef OPENSSL_NO_DSA 71#include <openssl/dsa.h> 72#endif 73#ifndef OPENSSL_NO_DH 74#include <openssl/dh.h> 75#endif 76#include <openssl/bn.h> 77 78#ifndef OPENSSL_NO_HW 79#ifndef OPENSSL_NO_HW_UBSEC 80 81#ifdef FLAT_INC 82#include "hw_ubsec.h" 83#else 84#include "vendor_defns/hw_ubsec.h" 85#endif 86 87#define UBSEC_LIB_NAME "ubsec engine" 88#include "e_ubsec_err.c" 89 90#define FAIL_TO_SOFTWARE -15 91 92static int ubsec_destroy(ENGINE *e); 93static int ubsec_init(ENGINE *e); 94static int ubsec_finish(ENGINE *e); 95static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); 96static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 97 const BIGNUM *m, BN_CTX *ctx); 98static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 99 const BIGNUM *q, const BIGNUM *dp, 100 const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx); 101#ifndef OPENSSL_NO_RSA 102static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx); 103#endif 104static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 105 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); 106#ifndef OPENSSL_NO_DSA 107#ifdef NOT_USED 108static int ubsec_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, 109 BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, 110 BN_CTX *ctx, BN_MONT_CTX *in_mont); 111static int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, 112 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 113 BN_MONT_CTX *m_ctx); 114#endif 115static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa); 116static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len, 117 DSA_SIG *sig, DSA *dsa); 118#endif 119#ifndef OPENSSL_NO_DH 120static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, 121 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 122 BN_MONT_CTX *m_ctx); 123static int ubsec_dh_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh); 124static int ubsec_dh_generate_key(DH *dh); 125#endif 126 127#ifdef NOT_USED 128static int ubsec_rand_bytes(unsigned char *buf, int num); 129static int ubsec_rand_status(void); 130#endif 131 132#define UBSEC_CMD_SO_PATH ENGINE_CMD_BASE 133static const ENGINE_CMD_DEFN ubsec_cmd_defns[] = { 134 {UBSEC_CMD_SO_PATH, 135 "SO_PATH", 136 "Specifies the path to the 'ubsec' shared library", 137 ENGINE_CMD_FLAG_STRING}, 138 {0, NULL, NULL, 0} 139 }; 140 141#ifndef OPENSSL_NO_RSA 142/* Our internal RSA_METHOD that we provide pointers to */ 143static RSA_METHOD ubsec_rsa = 144 { 145 "UBSEC RSA method", 146 NULL, 147 NULL, 148 NULL, 149 NULL, 150 ubsec_rsa_mod_exp, 151 ubsec_mod_exp_mont, 152 NULL, 153 NULL, 154 0, 155 NULL, 156 NULL, 157 NULL, 158 NULL 159 }; 160#endif 161 162#ifndef OPENSSL_NO_DSA 163/* Our internal DSA_METHOD that we provide pointers to */ 164static DSA_METHOD ubsec_dsa = 165 { 166 "UBSEC DSA method", 167 ubsec_dsa_do_sign, /* dsa_do_sign */ 168 NULL, /* dsa_sign_setup */ 169 ubsec_dsa_verify, /* dsa_do_verify */ 170 NULL, /* ubsec_dsa_mod_exp */ /* dsa_mod_exp */ 171 NULL, /* ubsec_mod_exp_dsa */ /* bn_mod_exp */ 172 NULL, /* init */ 173 NULL, /* finish */ 174 0, /* flags */ 175 NULL, /* app_data */ 176 NULL, /* dsa_paramgen */ 177 NULL /* dsa_keygen */ 178 }; 179#endif 180 181#ifndef OPENSSL_NO_DH 182/* Our internal DH_METHOD that we provide pointers to */ 183static DH_METHOD ubsec_dh = 184 { 185 "UBSEC DH method", 186 ubsec_dh_generate_key, 187 ubsec_dh_compute_key, 188 ubsec_mod_exp_dh, 189 NULL, 190 NULL, 191 0, 192 NULL, 193 NULL 194 }; 195#endif 196 197/* Constants used when creating the ENGINE */ 198static const char *engine_ubsec_id = "ubsec"; 199static const char *engine_ubsec_name = "UBSEC hardware engine support"; 200 201/* This internal function is used by ENGINE_ubsec() and possibly by the 202 * "dynamic" ENGINE support too */ 203static int bind_helper(ENGINE *e) 204 { 205#ifndef OPENSSL_NO_RSA 206 const RSA_METHOD *meth1; 207#endif 208#ifndef OPENSSL_NO_DH 209#ifndef HAVE_UBSEC_DH 210 const DH_METHOD *meth3; 211#endif /* HAVE_UBSEC_DH */ 212#endif 213 if(!ENGINE_set_id(e, engine_ubsec_id) || 214 !ENGINE_set_name(e, engine_ubsec_name) || 215#ifndef OPENSSL_NO_RSA 216 !ENGINE_set_RSA(e, &ubsec_rsa) || 217#endif 218#ifndef OPENSSL_NO_DSA 219 !ENGINE_set_DSA(e, &ubsec_dsa) || 220#endif 221#ifndef OPENSSL_NO_DH 222 !ENGINE_set_DH(e, &ubsec_dh) || 223#endif 224 !ENGINE_set_destroy_function(e, ubsec_destroy) || 225 !ENGINE_set_init_function(e, ubsec_init) || 226 !ENGINE_set_finish_function(e, ubsec_finish) || 227 !ENGINE_set_ctrl_function(e, ubsec_ctrl) || 228 !ENGINE_set_cmd_defns(e, ubsec_cmd_defns)) 229 return 0; 230 231#ifndef OPENSSL_NO_RSA 232 /* We know that the "PKCS1_SSLeay()" functions hook properly 233 * to the Broadcom-specific mod_exp and mod_exp_crt so we use 234 * those functions. NB: We don't use ENGINE_openssl() or 235 * anything "more generic" because something like the RSAref 236 * code may not hook properly, and if you own one of these 237 * cards then you have the right to do RSA operations on it 238 * anyway! */ 239 meth1 = RSA_PKCS1_SSLeay(); 240 ubsec_rsa.rsa_pub_enc = meth1->rsa_pub_enc; 241 ubsec_rsa.rsa_pub_dec = meth1->rsa_pub_dec; 242 ubsec_rsa.rsa_priv_enc = meth1->rsa_priv_enc; 243 ubsec_rsa.rsa_priv_dec = meth1->rsa_priv_dec; 244#endif 245 246#ifndef OPENSSL_NO_DH 247#ifndef HAVE_UBSEC_DH 248 /* Much the same for Diffie-Hellman */ 249 meth3 = DH_OpenSSL(); 250 ubsec_dh.generate_key = meth3->generate_key; 251 ubsec_dh.compute_key = meth3->compute_key; 252#endif /* HAVE_UBSEC_DH */ 253#endif 254 255 /* Ensure the ubsec error handling is set up */ 256 ERR_load_UBSEC_strings(); 257 return 1; 258 } 259 260#ifdef OPENSSL_NO_DYNAMIC_ENGINE 261static ENGINE *engine_ubsec(void) 262 { 263 ENGINE *ret = ENGINE_new(); 264 if(!ret) 265 return NULL; 266 if(!bind_helper(ret)) 267 { 268 ENGINE_free(ret); 269 return NULL; 270 } 271 return ret; 272 } 273 274void ENGINE_load_ubsec(void) 275 { 276 /* Copied from eng_[openssl|dyn].c */ 277 ENGINE *toadd = engine_ubsec(); 278 if(!toadd) return; 279 ENGINE_add(toadd); 280 ENGINE_free(toadd); 281 ERR_clear_error(); 282 } 283#endif 284 285/* This is a process-global DSO handle used for loading and unloading 286 * the UBSEC library. NB: This is only set (or unset) during an 287 * init() or finish() call (reference counts permitting) and they're 288 * operating with global locks, so this should be thread-safe 289 * implicitly. */ 290 291static DSO *ubsec_dso = NULL; 292 293/* These are the function pointers that are (un)set when the library has 294 * successfully (un)loaded. */ 295 296static t_UBSEC_ubsec_bytes_to_bits *p_UBSEC_ubsec_bytes_to_bits = NULL; 297static t_UBSEC_ubsec_bits_to_bytes *p_UBSEC_ubsec_bits_to_bytes = NULL; 298static t_UBSEC_ubsec_open *p_UBSEC_ubsec_open = NULL; 299static t_UBSEC_ubsec_close *p_UBSEC_ubsec_close = NULL; 300#ifndef OPENSSL_NO_DH 301static t_UBSEC_diffie_hellman_generate_ioctl 302 *p_UBSEC_diffie_hellman_generate_ioctl = NULL; 303static t_UBSEC_diffie_hellman_agree_ioctl *p_UBSEC_diffie_hellman_agree_ioctl = NULL; 304#endif 305/* #ifndef OPENSSL_NO_RSA */ 306static t_UBSEC_rsa_mod_exp_ioctl *p_UBSEC_rsa_mod_exp_ioctl = NULL; 307static t_UBSEC_rsa_mod_exp_crt_ioctl *p_UBSEC_rsa_mod_exp_crt_ioctl = NULL; 308/* #endif */ 309#ifndef OPENSSL_NO_DSA 310static t_UBSEC_dsa_sign_ioctl *p_UBSEC_dsa_sign_ioctl = NULL; 311static t_UBSEC_dsa_verify_ioctl *p_UBSEC_dsa_verify_ioctl = NULL; 312#endif 313static t_UBSEC_math_accelerate_ioctl *p_UBSEC_math_accelerate_ioctl = NULL; 314static t_UBSEC_rng_ioctl *p_UBSEC_rng_ioctl = NULL; 315static t_UBSEC_max_key_len_ioctl *p_UBSEC_max_key_len_ioctl = NULL; 316 317static int max_key_len = 1024; /* ??? */ 318 319/* 320 * These are the static string constants for the DSO file name and the function 321 * symbol names to bind to. 322 */ 323 324static const char *UBSEC_LIBNAME = NULL; 325static const char *get_UBSEC_LIBNAME(void) 326 { 327 if(UBSEC_LIBNAME) 328 return UBSEC_LIBNAME; 329 return "ubsec"; 330 } 331static void free_UBSEC_LIBNAME(void) 332 { 333 if(UBSEC_LIBNAME) 334 OPENSSL_free((void*)UBSEC_LIBNAME); 335 UBSEC_LIBNAME = NULL; 336 } 337static long set_UBSEC_LIBNAME(const char *name) 338 { 339 free_UBSEC_LIBNAME(); 340 return (((UBSEC_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0); 341 } 342static const char *UBSEC_F1 = "ubsec_bytes_to_bits"; 343static const char *UBSEC_F2 = "ubsec_bits_to_bytes"; 344static const char *UBSEC_F3 = "ubsec_open"; 345static const char *UBSEC_F4 = "ubsec_close"; 346#ifndef OPENSSL_NO_DH 347static const char *UBSEC_F5 = "diffie_hellman_generate_ioctl"; 348static const char *UBSEC_F6 = "diffie_hellman_agree_ioctl"; 349#endif 350/* #ifndef OPENSSL_NO_RSA */ 351static const char *UBSEC_F7 = "rsa_mod_exp_ioctl"; 352static const char *UBSEC_F8 = "rsa_mod_exp_crt_ioctl"; 353/* #endif */ 354#ifndef OPENSSL_NO_DSA 355static const char *UBSEC_F9 = "dsa_sign_ioctl"; 356static const char *UBSEC_F10 = "dsa_verify_ioctl"; 357#endif 358static const char *UBSEC_F11 = "math_accelerate_ioctl"; 359static const char *UBSEC_F12 = "rng_ioctl"; 360static const char *UBSEC_F13 = "ubsec_max_key_len_ioctl"; 361 362/* Destructor (complements the "ENGINE_ubsec()" constructor) */ 363static int ubsec_destroy(ENGINE *e) 364 { 365 free_UBSEC_LIBNAME(); 366 ERR_unload_UBSEC_strings(); 367 return 1; 368 } 369 370/* (de)initialisation functions. */ 371static int ubsec_init(ENGINE *e) 372 { 373 t_UBSEC_ubsec_bytes_to_bits *p1; 374 t_UBSEC_ubsec_bits_to_bytes *p2; 375 t_UBSEC_ubsec_open *p3; 376 t_UBSEC_ubsec_close *p4; 377#ifndef OPENSSL_NO_DH 378 t_UBSEC_diffie_hellman_generate_ioctl *p5; 379 t_UBSEC_diffie_hellman_agree_ioctl *p6; 380#endif 381/* #ifndef OPENSSL_NO_RSA */ 382 t_UBSEC_rsa_mod_exp_ioctl *p7; 383 t_UBSEC_rsa_mod_exp_crt_ioctl *p8; 384/* #endif */ 385#ifndef OPENSSL_NO_DSA 386 t_UBSEC_dsa_sign_ioctl *p9; 387 t_UBSEC_dsa_verify_ioctl *p10; 388#endif 389 t_UBSEC_math_accelerate_ioctl *p11; 390 t_UBSEC_rng_ioctl *p12; 391 t_UBSEC_max_key_len_ioctl *p13; 392 int fd = 0; 393 394 if(ubsec_dso != NULL) 395 { 396 UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_ALREADY_LOADED); 397 goto err; 398 } 399 /* 400 * Attempt to load libubsec.so/ubsec.dll/whatever. 401 */ 402 ubsec_dso = DSO_load(NULL, get_UBSEC_LIBNAME(), NULL, 0); 403 if(ubsec_dso == NULL) 404 { 405 UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE); 406 goto err; 407 } 408 409 if ( 410 !(p1 = (t_UBSEC_ubsec_bytes_to_bits *) DSO_bind_func(ubsec_dso, UBSEC_F1)) || 411 !(p2 = (t_UBSEC_ubsec_bits_to_bytes *) DSO_bind_func(ubsec_dso, UBSEC_F2)) || 412 !(p3 = (t_UBSEC_ubsec_open *) DSO_bind_func(ubsec_dso, UBSEC_F3)) || 413 !(p4 = (t_UBSEC_ubsec_close *) DSO_bind_func(ubsec_dso, UBSEC_F4)) || 414#ifndef OPENSSL_NO_DH 415 !(p5 = (t_UBSEC_diffie_hellman_generate_ioctl *) 416 DSO_bind_func(ubsec_dso, UBSEC_F5)) || 417 !(p6 = (t_UBSEC_diffie_hellman_agree_ioctl *) 418 DSO_bind_func(ubsec_dso, UBSEC_F6)) || 419#endif 420/* #ifndef OPENSSL_NO_RSA */ 421 !(p7 = (t_UBSEC_rsa_mod_exp_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F7)) || 422 !(p8 = (t_UBSEC_rsa_mod_exp_crt_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F8)) || 423/* #endif */ 424#ifndef OPENSSL_NO_DSA 425 !(p9 = (t_UBSEC_dsa_sign_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F9)) || 426 !(p10 = (t_UBSEC_dsa_verify_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F10)) || 427#endif 428 !(p11 = (t_UBSEC_math_accelerate_ioctl *) 429 DSO_bind_func(ubsec_dso, UBSEC_F11)) || 430 !(p12 = (t_UBSEC_rng_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F12)) || 431 !(p13 = (t_UBSEC_max_key_len_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F13))) 432 { 433 UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE); 434 goto err; 435 } 436 437 /* Copy the pointers */ 438 p_UBSEC_ubsec_bytes_to_bits = p1; 439 p_UBSEC_ubsec_bits_to_bytes = p2; 440 p_UBSEC_ubsec_open = p3; 441 p_UBSEC_ubsec_close = p4; 442#ifndef OPENSSL_NO_DH 443 p_UBSEC_diffie_hellman_generate_ioctl = p5; 444 p_UBSEC_diffie_hellman_agree_ioctl = p6; 445#endif 446#ifndef OPENSSL_NO_RSA 447 p_UBSEC_rsa_mod_exp_ioctl = p7; 448 p_UBSEC_rsa_mod_exp_crt_ioctl = p8; 449#endif 450#ifndef OPENSSL_NO_DSA 451 p_UBSEC_dsa_sign_ioctl = p9; 452 p_UBSEC_dsa_verify_ioctl = p10; 453#endif 454 p_UBSEC_math_accelerate_ioctl = p11; 455 p_UBSEC_rng_ioctl = p12; 456 p_UBSEC_max_key_len_ioctl = p13; 457 458 /* Perform an open to see if there's actually any unit running. */ 459 if (((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) > 0) && (p_UBSEC_max_key_len_ioctl(fd, &max_key_len) == 0)) 460 { 461 p_UBSEC_ubsec_close(fd); 462 return 1; 463 } 464 else 465 { 466 UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); 467 } 468 469err: 470 if(ubsec_dso) 471 DSO_free(ubsec_dso); 472 ubsec_dso = NULL; 473 p_UBSEC_ubsec_bytes_to_bits = NULL; 474 p_UBSEC_ubsec_bits_to_bytes = NULL; 475 p_UBSEC_ubsec_open = NULL; 476 p_UBSEC_ubsec_close = NULL; 477#ifndef OPENSSL_NO_DH 478 p_UBSEC_diffie_hellman_generate_ioctl = NULL; 479 p_UBSEC_diffie_hellman_agree_ioctl = NULL; 480#endif 481#ifndef OPENSSL_NO_RSA 482 p_UBSEC_rsa_mod_exp_ioctl = NULL; 483 p_UBSEC_rsa_mod_exp_crt_ioctl = NULL; 484#endif 485#ifndef OPENSSL_NO_DSA 486 p_UBSEC_dsa_sign_ioctl = NULL; 487 p_UBSEC_dsa_verify_ioctl = NULL; 488#endif 489 p_UBSEC_math_accelerate_ioctl = NULL; 490 p_UBSEC_rng_ioctl = NULL; 491 p_UBSEC_max_key_len_ioctl = NULL; 492 493 return 0; 494 } 495 496static int ubsec_finish(ENGINE *e) 497 { 498 free_UBSEC_LIBNAME(); 499 if(ubsec_dso == NULL) 500 { 501 UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_NOT_LOADED); 502 return 0; 503 } 504 if(!DSO_free(ubsec_dso)) 505 { 506 UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_DSO_FAILURE); 507 return 0; 508 } 509 ubsec_dso = NULL; 510 p_UBSEC_ubsec_bytes_to_bits = NULL; 511 p_UBSEC_ubsec_bits_to_bytes = NULL; 512 p_UBSEC_ubsec_open = NULL; 513 p_UBSEC_ubsec_close = NULL; 514#ifndef OPENSSL_NO_DH 515 p_UBSEC_diffie_hellman_generate_ioctl = NULL; 516 p_UBSEC_diffie_hellman_agree_ioctl = NULL; 517#endif 518#ifndef OPENSSL_NO_RSA 519 p_UBSEC_rsa_mod_exp_ioctl = NULL; 520 p_UBSEC_rsa_mod_exp_crt_ioctl = NULL; 521#endif 522#ifndef OPENSSL_NO_DSA 523 p_UBSEC_dsa_sign_ioctl = NULL; 524 p_UBSEC_dsa_verify_ioctl = NULL; 525#endif 526 p_UBSEC_math_accelerate_ioctl = NULL; 527 p_UBSEC_rng_ioctl = NULL; 528 p_UBSEC_max_key_len_ioctl = NULL; 529 return 1; 530 } 531 532static int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) 533 { 534 int initialised = ((ubsec_dso == NULL) ? 0 : 1); 535 switch(cmd) 536 { 537 case UBSEC_CMD_SO_PATH: 538 if(p == NULL) 539 { 540 UBSECerr(UBSEC_F_UBSEC_CTRL,ERR_R_PASSED_NULL_PARAMETER); 541 return 0; 542 } 543 if(initialised) 544 { 545 UBSECerr(UBSEC_F_UBSEC_CTRL,UBSEC_R_ALREADY_LOADED); 546 return 0; 547 } 548 return set_UBSEC_LIBNAME((const char *)p); 549 default: 550 break; 551 } 552 UBSECerr(UBSEC_F_UBSEC_CTRL,UBSEC_R_CTRL_COMMAND_NOT_IMPLEMENTED); 553 return 0; 554 } 555 556static int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 557 const BIGNUM *m, BN_CTX *ctx) 558 { 559 int y_len = 0; 560 int fd; 561 562 if(ubsec_dso == NULL) 563 { 564 UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_NOT_LOADED); 565 return 0; 566 } 567 568 /* Check if hardware can't handle this argument. */ 569 y_len = BN_num_bits(m); 570 if (y_len > max_key_len) { 571 UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL); 572 return BN_mod_exp(r, a, p, m, ctx); 573 } 574 575 if(!bn_wexpand(r, m->top)) 576 { 577 UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_BN_EXPAND_FAIL); 578 return 0; 579 } 580 581 if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { 582 fd = 0; 583 UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_UNIT_FAILURE); 584 return BN_mod_exp(r, a, p, m, ctx); 585 } 586 587 if (p_UBSEC_rsa_mod_exp_ioctl(fd, (unsigned char *)a->d, BN_num_bits(a), 588 (unsigned char *)m->d, BN_num_bits(m), (unsigned char *)p->d, 589 BN_num_bits(p), (unsigned char *)r->d, &y_len) != 0) 590 { 591 UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED); 592 p_UBSEC_ubsec_close(fd); 593 594 return BN_mod_exp(r, a, p, m, ctx); 595 } 596 597 p_UBSEC_ubsec_close(fd); 598 599 r->top = (BN_num_bits(m)+BN_BITS2-1)/BN_BITS2; 600 return 1; 601 } 602 603#ifndef OPENSSL_NO_RSA 604static int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) 605 { 606 int to_return = 0; 607 608 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) 609 { 610 UBSECerr(UBSEC_F_UBSEC_RSA_MOD_EXP, UBSEC_R_MISSING_KEY_COMPONENTS); 611 goto err; 612 } 613 614 to_return = ubsec_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1, 615 rsa->dmq1, rsa->iqmp, ctx); 616 if (to_return == FAIL_TO_SOFTWARE) 617 { 618 /* 619 * Do in software as hardware failed. 620 */ 621 const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); 622 to_return = (*meth->rsa_mod_exp)(r0, I, rsa, ctx); 623 } 624err: 625 return to_return; 626 } 627#endif 628 629static int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 630 const BIGNUM *q, const BIGNUM *dp, 631 const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx) 632 { 633 int y_len, 634 m_len, 635 fd; 636 637 m_len = BN_num_bytes(p) + BN_num_bytes(q) + 1; 638 y_len = BN_num_bits(p) + BN_num_bits(q); 639 640 /* Check if hardware can't handle this argument. */ 641 if (y_len > max_key_len) { 642 UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL); 643 return FAIL_TO_SOFTWARE; 644 } 645 646 if (!bn_wexpand(r, p->top + q->top + 1)) { 647 UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_BN_EXPAND_FAIL); 648 return 0; 649 } 650 651 if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { 652 fd = 0; 653 UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_UNIT_FAILURE); 654 return FAIL_TO_SOFTWARE; 655 } 656 657 if (p_UBSEC_rsa_mod_exp_crt_ioctl(fd, 658 (unsigned char *)a->d, BN_num_bits(a), 659 (unsigned char *)qinv->d, BN_num_bits(qinv), 660 (unsigned char *)dp->d, BN_num_bits(dp), 661 (unsigned char *)p->d, BN_num_bits(p), 662 (unsigned char *)dq->d, BN_num_bits(dq), 663 (unsigned char *)q->d, BN_num_bits(q), 664 (unsigned char *)r->d, &y_len) != 0) { 665 UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_REQUEST_FAILED); 666 p_UBSEC_ubsec_close(fd); 667 return FAIL_TO_SOFTWARE; 668 } 669 670 p_UBSEC_ubsec_close(fd); 671 672 r->top = (BN_num_bits(p) + BN_num_bits(q) + BN_BITS2 - 1)/BN_BITS2; 673 return 1; 674} 675 676#ifndef OPENSSL_NO_DSA 677#ifdef NOT_USED 678static int ubsec_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, 679 BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, 680 BN_CTX *ctx, BN_MONT_CTX *in_mont) 681 { 682 BIGNUM t; 683 int to_return = 0; 684 685 BN_init(&t); 686 /* let rr = a1 ^ p1 mod m */ 687 if (!ubsec_mod_exp(rr,a1,p1,m,ctx)) goto end; 688 /* let t = a2 ^ p2 mod m */ 689 if (!ubsec_mod_exp(&t,a2,p2,m,ctx)) goto end; 690 /* let rr = rr * t mod m */ 691 if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end; 692 to_return = 1; 693end: 694 BN_free(&t); 695 return to_return; 696 } 697 698static int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, 699 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 700 BN_MONT_CTX *m_ctx) 701 { 702 return ubsec_mod_exp(r, a, p, m, ctx); 703 } 704#endif 705#endif 706 707/* 708 * This function is aliased to mod_exp (with the mont stuff dropped). 709 */ 710static int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 711 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) 712 { 713 int ret = 0; 714 715#ifndef OPENSSL_NO_RSA 716 /* Do in software if the key is too large for the hardware. */ 717 if (BN_num_bits(m) > max_key_len) 718 { 719 const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); 720 ret = (*meth->bn_mod_exp)(r, a, p, m, ctx, m_ctx); 721 } 722 else 723#endif 724 { 725 ret = ubsec_mod_exp(r, a, p, m, ctx); 726 } 727 728 return ret; 729 } 730 731#ifndef OPENSSL_NO_DH 732/* This function is aliased to mod_exp (with the dh and mont dropped). */ 733static int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, 734 const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 735 BN_MONT_CTX *m_ctx) 736 { 737 return ubsec_mod_exp(r, a, p, m, ctx); 738 } 739#endif 740 741#ifndef OPENSSL_NO_DSA 742static DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) 743 { 744 DSA_SIG *to_return = NULL; 745 int s_len = 160, r_len = 160, d_len, fd; 746 BIGNUM m, *r=NULL, *s=NULL; 747 748 BN_init(&m); 749 750 s = BN_new(); 751 r = BN_new(); 752 if ((s == NULL) || (r==NULL)) 753 goto err; 754 755 d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dlen); 756 757 if(!bn_wexpand(r, (160+BN_BITS2-1)/BN_BITS2) || 758 (!bn_wexpand(s, (160+BN_BITS2-1)/BN_BITS2))) { 759 UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL); 760 goto err; 761 } 762 763 if (BN_bin2bn(dgst,dlen,&m) == NULL) { 764 UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL); 765 goto err; 766 } 767 768 if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { 769 const DSA_METHOD *meth; 770 fd = 0; 771 UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_UNIT_FAILURE); 772 meth = DSA_OpenSSL(); 773 to_return = meth->dsa_do_sign(dgst, dlen, dsa); 774 goto err; 775 } 776 777 if (p_UBSEC_dsa_sign_ioctl(fd, 0, /* compute hash before signing */ 778 (unsigned char *)dgst, d_len, 779 NULL, 0, /* compute random value */ 780 (unsigned char *)dsa->p->d, BN_num_bits(dsa->p), 781 (unsigned char *)dsa->q->d, BN_num_bits(dsa->q), 782 (unsigned char *)dsa->g->d, BN_num_bits(dsa->g), 783 (unsigned char *)dsa->priv_key->d, BN_num_bits(dsa->priv_key), 784 (unsigned char *)r->d, &r_len, 785 (unsigned char *)s->d, &s_len ) != 0) { 786 const DSA_METHOD *meth; 787 788 UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_REQUEST_FAILED); 789 p_UBSEC_ubsec_close(fd); 790 meth = DSA_OpenSSL(); 791 to_return = meth->dsa_do_sign(dgst, dlen, dsa); 792 793 goto err; 794 } 795 796 p_UBSEC_ubsec_close(fd); 797 798 r->top = (160+BN_BITS2-1)/BN_BITS2; 799 s->top = (160+BN_BITS2-1)/BN_BITS2; 800 801 to_return = DSA_SIG_new(); 802 if(to_return == NULL) { 803 UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL); 804 goto err; 805 } 806 807 to_return->r = r; 808 to_return->s = s; 809 810err: 811 if (!to_return) { 812 if (r) BN_free(r); 813 if (s) BN_free(s); 814 } 815 BN_clear_free(&m); 816 return to_return; 817} 818 819static int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len, 820 DSA_SIG *sig, DSA *dsa) 821 { 822 int v_len, d_len; 823 int to_return = 0; 824 int fd; 825 BIGNUM v; 826 827 BN_init(&v); 828 829 if(!bn_wexpand(&v, dsa->p->top)) { 830 UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_BN_EXPAND_FAIL); 831 goto err; 832 } 833 834 v_len = BN_num_bits(dsa->p); 835 836 d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dgst_len); 837 838 if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { 839 const DSA_METHOD *meth; 840 fd = 0; 841 UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_UNIT_FAILURE); 842 meth = DSA_OpenSSL(); 843 to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa); 844 goto err; 845 } 846 847 if (p_UBSEC_dsa_verify_ioctl(fd, 0, /* compute hash before signing */ 848 (unsigned char *)dgst, d_len, 849 (unsigned char *)dsa->p->d, BN_num_bits(dsa->p), 850 (unsigned char *)dsa->q->d, BN_num_bits(dsa->q), 851 (unsigned char *)dsa->g->d, BN_num_bits(dsa->g), 852 (unsigned char *)dsa->pub_key->d, BN_num_bits(dsa->pub_key), 853 (unsigned char *)sig->r->d, BN_num_bits(sig->r), 854 (unsigned char *)sig->s->d, BN_num_bits(sig->s), 855 (unsigned char *)v.d, &v_len) != 0) { 856 const DSA_METHOD *meth; 857 UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_REQUEST_FAILED); 858 p_UBSEC_ubsec_close(fd); 859 860 meth = DSA_OpenSSL(); 861 to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa); 862 863 goto err; 864 } 865 866 p_UBSEC_ubsec_close(fd); 867 868 to_return = 1; 869err: 870 BN_clear_free(&v); 871 return to_return; 872 } 873#endif 874 875#ifndef OPENSSL_NO_DH 876static int ubsec_dh_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh) 877 { 878 int ret = -1, 879 k_len, 880 fd; 881 882 k_len = BN_num_bits(dh->p); 883 884 if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) 885 { 886 const DH_METHOD *meth; 887 UBSECerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, UBSEC_R_UNIT_FAILURE); 888 meth = DH_OpenSSL(); 889 ret = meth->compute_key(key, pub_key, dh); 890 goto err; 891 } 892 893 if (p_UBSEC_diffie_hellman_agree_ioctl(fd, 894 (unsigned char *)dh->priv_key->d, BN_num_bits(dh->priv_key), 895 (unsigned char *)pub_key->d, BN_num_bits(pub_key), 896 (unsigned char *)dh->p->d, BN_num_bits(dh->p), 897 key, &k_len) != 0) 898 { 899 /* Hardware's a no go, failover to software */ 900 const DH_METHOD *meth; 901 UBSECerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, UBSEC_R_REQUEST_FAILED); 902 p_UBSEC_ubsec_close(fd); 903 904 meth = DH_OpenSSL(); 905 ret = meth->compute_key(key, pub_key, dh); 906 907 goto err; 908 } 909 910 p_UBSEC_ubsec_close(fd); 911 912 ret = p_UBSEC_ubsec_bits_to_bytes(k_len); 913err: 914 return ret; 915 } 916 917static int ubsec_dh_generate_key(DH *dh) 918 { 919 int ret = 0, 920 random_bits = 0, 921 pub_key_len = 0, 922 priv_key_len = 0, 923 fd; 924 BIGNUM *pub_key = NULL; 925 BIGNUM *priv_key = NULL; 926 927 /* 928 * How many bits should Random x be? dh_key.c 929 * sets the range from 0 to num_bits(modulus) ??? 930 */ 931 932 if (dh->priv_key == NULL) 933 { 934 priv_key = BN_new(); 935 if (priv_key == NULL) goto err; 936 priv_key_len = BN_num_bits(dh->p); 937 bn_wexpand(priv_key, dh->p->top); 938 do 939 if (!BN_rand_range(priv_key, dh->p)) goto err; 940 while (BN_is_zero(priv_key)); 941 random_bits = BN_num_bits(priv_key); 942 } 943 else 944 { 945 priv_key = dh->priv_key; 946 } 947 948 if (dh->pub_key == NULL) 949 { 950 pub_key = BN_new(); 951 pub_key_len = BN_num_bits(dh->p); 952 bn_wexpand(pub_key, dh->p->top); 953 if(pub_key == NULL) goto err; 954 } 955 else 956 { 957 pub_key = dh->pub_key; 958 } 959 960 if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) 961 { 962 const DH_METHOD *meth; 963 UBSECerr(UBSEC_F_UBSEC_DH_GENERATE_KEY, UBSEC_R_UNIT_FAILURE); 964 meth = DH_OpenSSL(); 965 ret = meth->generate_key(dh); 966 goto err; 967 } 968 969 if (p_UBSEC_diffie_hellman_generate_ioctl(fd, 970 (unsigned char *)priv_key->d, &priv_key_len, 971 (unsigned char *)pub_key->d, &pub_key_len, 972 (unsigned char *)dh->g->d, BN_num_bits(dh->g), 973 (unsigned char *)dh->p->d, BN_num_bits(dh->p), 974 0, 0, random_bits) != 0) 975 { 976 /* Hardware's a no go, failover to software */ 977 const DH_METHOD *meth; 978 979 UBSECerr(UBSEC_F_UBSEC_DH_GENERATE_KEY, UBSEC_R_REQUEST_FAILED); 980 p_UBSEC_ubsec_close(fd); 981 982 meth = DH_OpenSSL(); 983 ret = meth->generate_key(dh); 984 985 goto err; 986 } 987 988 p_UBSEC_ubsec_close(fd); 989 990 dh->pub_key = pub_key; 991 dh->pub_key->top = (pub_key_len + BN_BITS2-1) / BN_BITS2; 992 dh->priv_key = priv_key; 993 dh->priv_key->top = (priv_key_len + BN_BITS2-1) / BN_BITS2; 994 995 ret = 1; 996err: 997 return ret; 998 } 999#endif 1000 1001#ifdef NOT_USED 1002static int ubsec_rand_bytes(unsigned char * buf, 1003 int num) 1004 { 1005 int ret = 0, 1006 fd; 1007 1008 if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) 1009 { 1010 const RAND_METHOD *meth; 1011 UBSECerr(UBSEC_F_UBSEC_RAND_BYTES, UBSEC_R_UNIT_FAILURE); 1012 num = p_UBSEC_ubsec_bits_to_bytes(num); 1013 meth = RAND_SSLeay(); 1014 meth->seed(buf, num); 1015 ret = meth->bytes(buf, num); 1016 goto err; 1017 } 1018 1019 num *= 8; /* bytes to bits */ 1020 1021 if (p_UBSEC_rng_ioctl(fd, 1022 UBSEC_RNG_DIRECT, 1023 buf, 1024 &num) != 0) 1025 { 1026 /* Hardware's a no go, failover to software */ 1027 const RAND_METHOD *meth; 1028 1029 UBSECerr(UBSEC_F_UBSEC_RAND_BYTES, UBSEC_R_REQUEST_FAILED); 1030 p_UBSEC_ubsec_close(fd); 1031 1032 num = p_UBSEC_ubsec_bits_to_bytes(num); 1033 meth = RAND_SSLeay(); 1034 meth->seed(buf, num); 1035 ret = meth->bytes(buf, num); 1036 1037 goto err; 1038 } 1039 1040 p_UBSEC_ubsec_close(fd); 1041 1042 ret = 1; 1043err: 1044 return(ret); 1045 } 1046 1047 1048static int ubsec_rand_status(void) 1049 { 1050 return 0; 1051 } 1052#endif 1053 1054/* This stuff is needed if this ENGINE is being compiled into a self-contained 1055 * shared-library. */ 1056#ifndef OPENSSL_NO_DYNAMIC_ENGINE 1057static int bind_fn(ENGINE *e, const char *id) 1058 { 1059 if(id && (strcmp(id, engine_ubsec_id) != 0)) 1060 return 0; 1061 if(!bind_helper(e)) 1062 return 0; 1063 return 1; 1064 } 1065IMPLEMENT_DYNAMIC_CHECK_FN() 1066IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) 1067#endif /* OPENSSL_NO_DYNAMIC_ENGINE */ 1068 1069#endif /* !OPENSSL_NO_HW_UBSEC */ 1070#endif /* !OPENSSL_NO_HW */ 1071