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