1160814Ssimon/* crypto/engine/hw_ubsec.c */ 2160814Ssimon/* Written by Geoff Thorpe (geoff@geoffthorpe.net) for the OpenSSL 3160814Ssimon * project 2000. 4160814Ssimon * 5160814Ssimon * Cloned shamelessly by Joe Tardo. 6160814Ssimon */ 7160814Ssimon/* ==================================================================== 8160814Ssimon * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved. 9160814Ssimon * 10160814Ssimon * Redistribution and use in source and binary forms, with or without 11160814Ssimon * modification, are permitted provided that the following conditions 12160814Ssimon * are met: 13160814Ssimon * 14160814Ssimon * 1. Redistributions of source code must retain the above copyright 15160814Ssimon * notice, this list of conditions and the following disclaimer. 16160814Ssimon * 17160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright 18160814Ssimon * notice, this list of conditions and the following disclaimer in 19160814Ssimon * the documentation and/or other materials provided with the 20160814Ssimon * distribution. 21160814Ssimon * 22160814Ssimon * 3. All advertising materials mentioning features or use of this 23160814Ssimon * software must display the following acknowledgment: 24160814Ssimon * "This product includes software developed by the OpenSSL Project 25160814Ssimon * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 26160814Ssimon * 27160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 28160814Ssimon * endorse or promote products derived from this software without 29160814Ssimon * prior written permission. For written permission, please contact 30160814Ssimon * licensing@OpenSSL.org. 31160814Ssimon * 32160814Ssimon * 5. Products derived from this software may not be called "OpenSSL" 33160814Ssimon * nor may "OpenSSL" appear in their names without prior written 34160814Ssimon * permission of the OpenSSL Project. 35160814Ssimon * 36160814Ssimon * 6. Redistributions of any form whatsoever must retain the following 37160814Ssimon * acknowledgment: 38160814Ssimon * "This product includes software developed by the OpenSSL Project 39160814Ssimon * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 40160814Ssimon * 41160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 42160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 44160814Ssimon * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 45160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 46160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 47160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 48160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 50160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 51160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 52160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE. 53160814Ssimon * ==================================================================== 54160814Ssimon * 55160814Ssimon * This product includes cryptographic software written by Eric Young 56160814Ssimon * (eay@cryptsoft.com). This product includes software written by Tim 57160814Ssimon * Hudson (tjh@cryptsoft.com). 58160814Ssimon * 59160814Ssimon */ 60160814Ssimon 61160814Ssimon#include <stdio.h> 62160814Ssimon#include <string.h> 63160814Ssimon#include <openssl/crypto.h> 64160814Ssimon#include <openssl/buffer.h> 65160814Ssimon#include <openssl/dso.h> 66160814Ssimon#include <openssl/engine.h> 67160814Ssimon#ifndef OPENSSL_NO_RSA 68160814Ssimon#include <openssl/rsa.h> 69160814Ssimon#endif 70160814Ssimon#ifndef OPENSSL_NO_DSA 71160814Ssimon#include <openssl/dsa.h> 72160814Ssimon#endif 73160814Ssimon#ifndef OPENSSL_NO_DH 74160814Ssimon#include <openssl/dh.h> 75160814Ssimon#endif 76160814Ssimon#include <openssl/bn.h> 77160814Ssimon 78160814Ssimon#ifndef OPENSSL_NO_HW 79160814Ssimon#ifndef OPENSSL_NO_HW_UBSEC 80160814Ssimon 81160814Ssimon#ifdef FLAT_INC 82160814Ssimon#include "hw_ubsec.h" 83160814Ssimon#else 84160814Ssimon#include "vendor_defns/hw_ubsec.h" 85160814Ssimon#endif 86160814Ssimon 87160814Ssimon#define UBSEC_LIB_NAME "ubsec engine" 88160814Ssimon#include "e_ubsec_err.c" 89160814Ssimon 90160814Ssimon#define FAIL_TO_SOFTWARE -15 91160814Ssimon 92160814Ssimonstatic int ubsec_destroy(ENGINE *e); 93160814Ssimonstatic int ubsec_init(ENGINE *e); 94160814Ssimonstatic int ubsec_finish(ENGINE *e); 95160814Ssimonstatic int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)); 96160814Ssimonstatic int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 97160814Ssimon const BIGNUM *m, BN_CTX *ctx); 98238405Sjkim#ifndef OPENSSL_NO_RSA 99160814Ssimonstatic int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 100160814Ssimon const BIGNUM *q, const BIGNUM *dp, 101160814Ssimon const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx); 102160814Ssimonstatic int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx); 103160814Ssimonstatic int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 104160814Ssimon const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); 105238405Sjkim#endif 106160814Ssimon#ifndef OPENSSL_NO_DSA 107160814Ssimon#ifdef NOT_USED 108160814Ssimonstatic int ubsec_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, 109160814Ssimon BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, 110160814Ssimon BN_CTX *ctx, BN_MONT_CTX *in_mont); 111160814Ssimonstatic int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, 112160814Ssimon const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 113160814Ssimon BN_MONT_CTX *m_ctx); 114160814Ssimon#endif 115160814Ssimonstatic DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa); 116160814Ssimonstatic int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len, 117160814Ssimon DSA_SIG *sig, DSA *dsa); 118160814Ssimon#endif 119160814Ssimon#ifndef OPENSSL_NO_DH 120160814Ssimonstatic int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, 121160814Ssimon const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 122160814Ssimon BN_MONT_CTX *m_ctx); 123160814Ssimonstatic int ubsec_dh_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh); 124160814Ssimonstatic int ubsec_dh_generate_key(DH *dh); 125160814Ssimon#endif 126160814Ssimon 127160814Ssimon#ifdef NOT_USED 128160814Ssimonstatic int ubsec_rand_bytes(unsigned char *buf, int num); 129160814Ssimonstatic int ubsec_rand_status(void); 130160814Ssimon#endif 131160814Ssimon 132160814Ssimon#define UBSEC_CMD_SO_PATH ENGINE_CMD_BASE 133160814Ssimonstatic const ENGINE_CMD_DEFN ubsec_cmd_defns[] = { 134160814Ssimon {UBSEC_CMD_SO_PATH, 135160814Ssimon "SO_PATH", 136160814Ssimon "Specifies the path to the 'ubsec' shared library", 137160814Ssimon ENGINE_CMD_FLAG_STRING}, 138160814Ssimon {0, NULL, NULL, 0} 139160814Ssimon }; 140160814Ssimon 141160814Ssimon#ifndef OPENSSL_NO_RSA 142160814Ssimon/* Our internal RSA_METHOD that we provide pointers to */ 143160814Ssimonstatic RSA_METHOD ubsec_rsa = 144160814Ssimon { 145160814Ssimon "UBSEC RSA method", 146160814Ssimon NULL, 147160814Ssimon NULL, 148160814Ssimon NULL, 149160814Ssimon NULL, 150160814Ssimon ubsec_rsa_mod_exp, 151160814Ssimon ubsec_mod_exp_mont, 152160814Ssimon NULL, 153160814Ssimon NULL, 154160814Ssimon 0, 155160814Ssimon NULL, 156160814Ssimon NULL, 157160814Ssimon NULL, 158160814Ssimon NULL 159160814Ssimon }; 160160814Ssimon#endif 161160814Ssimon 162160814Ssimon#ifndef OPENSSL_NO_DSA 163160814Ssimon/* Our internal DSA_METHOD that we provide pointers to */ 164160814Ssimonstatic DSA_METHOD ubsec_dsa = 165160814Ssimon { 166160814Ssimon "UBSEC DSA method", 167160814Ssimon ubsec_dsa_do_sign, /* dsa_do_sign */ 168160814Ssimon NULL, /* dsa_sign_setup */ 169160814Ssimon ubsec_dsa_verify, /* dsa_do_verify */ 170160814Ssimon NULL, /* ubsec_dsa_mod_exp */ /* dsa_mod_exp */ 171160814Ssimon NULL, /* ubsec_mod_exp_dsa */ /* bn_mod_exp */ 172160814Ssimon NULL, /* init */ 173160814Ssimon NULL, /* finish */ 174160814Ssimon 0, /* flags */ 175160814Ssimon NULL, /* app_data */ 176160814Ssimon NULL, /* dsa_paramgen */ 177160814Ssimon NULL /* dsa_keygen */ 178160814Ssimon }; 179160814Ssimon#endif 180160814Ssimon 181160814Ssimon#ifndef OPENSSL_NO_DH 182160814Ssimon/* Our internal DH_METHOD that we provide pointers to */ 183160814Ssimonstatic DH_METHOD ubsec_dh = 184160814Ssimon { 185160814Ssimon "UBSEC DH method", 186160814Ssimon ubsec_dh_generate_key, 187160814Ssimon ubsec_dh_compute_key, 188160814Ssimon ubsec_mod_exp_dh, 189160814Ssimon NULL, 190160814Ssimon NULL, 191160814Ssimon 0, 192160814Ssimon NULL, 193160814Ssimon NULL 194160814Ssimon }; 195160814Ssimon#endif 196160814Ssimon 197160814Ssimon/* Constants used when creating the ENGINE */ 198160814Ssimonstatic const char *engine_ubsec_id = "ubsec"; 199160814Ssimonstatic const char *engine_ubsec_name = "UBSEC hardware engine support"; 200160814Ssimon 201160814Ssimon/* This internal function is used by ENGINE_ubsec() and possibly by the 202160814Ssimon * "dynamic" ENGINE support too */ 203160814Ssimonstatic int bind_helper(ENGINE *e) 204160814Ssimon { 205160814Ssimon#ifndef OPENSSL_NO_RSA 206160814Ssimon const RSA_METHOD *meth1; 207160814Ssimon#endif 208160814Ssimon#ifndef OPENSSL_NO_DH 209160814Ssimon#ifndef HAVE_UBSEC_DH 210160814Ssimon const DH_METHOD *meth3; 211160814Ssimon#endif /* HAVE_UBSEC_DH */ 212160814Ssimon#endif 213160814Ssimon if(!ENGINE_set_id(e, engine_ubsec_id) || 214160814Ssimon !ENGINE_set_name(e, engine_ubsec_name) || 215160814Ssimon#ifndef OPENSSL_NO_RSA 216160814Ssimon !ENGINE_set_RSA(e, &ubsec_rsa) || 217160814Ssimon#endif 218160814Ssimon#ifndef OPENSSL_NO_DSA 219160814Ssimon !ENGINE_set_DSA(e, &ubsec_dsa) || 220160814Ssimon#endif 221160814Ssimon#ifndef OPENSSL_NO_DH 222160814Ssimon !ENGINE_set_DH(e, &ubsec_dh) || 223160814Ssimon#endif 224160814Ssimon !ENGINE_set_destroy_function(e, ubsec_destroy) || 225160814Ssimon !ENGINE_set_init_function(e, ubsec_init) || 226160814Ssimon !ENGINE_set_finish_function(e, ubsec_finish) || 227160814Ssimon !ENGINE_set_ctrl_function(e, ubsec_ctrl) || 228160814Ssimon !ENGINE_set_cmd_defns(e, ubsec_cmd_defns)) 229160814Ssimon return 0; 230160814Ssimon 231160814Ssimon#ifndef OPENSSL_NO_RSA 232160814Ssimon /* We know that the "PKCS1_SSLeay()" functions hook properly 233160814Ssimon * to the Broadcom-specific mod_exp and mod_exp_crt so we use 234160814Ssimon * those functions. NB: We don't use ENGINE_openssl() or 235160814Ssimon * anything "more generic" because something like the RSAref 236160814Ssimon * code may not hook properly, and if you own one of these 237160814Ssimon * cards then you have the right to do RSA operations on it 238160814Ssimon * anyway! */ 239160814Ssimon meth1 = RSA_PKCS1_SSLeay(); 240160814Ssimon ubsec_rsa.rsa_pub_enc = meth1->rsa_pub_enc; 241160814Ssimon ubsec_rsa.rsa_pub_dec = meth1->rsa_pub_dec; 242160814Ssimon ubsec_rsa.rsa_priv_enc = meth1->rsa_priv_enc; 243160814Ssimon ubsec_rsa.rsa_priv_dec = meth1->rsa_priv_dec; 244160814Ssimon#endif 245160814Ssimon 246160814Ssimon#ifndef OPENSSL_NO_DH 247160814Ssimon#ifndef HAVE_UBSEC_DH 248160814Ssimon /* Much the same for Diffie-Hellman */ 249160814Ssimon meth3 = DH_OpenSSL(); 250160814Ssimon ubsec_dh.generate_key = meth3->generate_key; 251160814Ssimon ubsec_dh.compute_key = meth3->compute_key; 252160814Ssimon#endif /* HAVE_UBSEC_DH */ 253160814Ssimon#endif 254160814Ssimon 255160814Ssimon /* Ensure the ubsec error handling is set up */ 256160814Ssimon ERR_load_UBSEC_strings(); 257160814Ssimon return 1; 258160814Ssimon } 259160814Ssimon 260160814Ssimon#ifdef OPENSSL_NO_DYNAMIC_ENGINE 261160814Ssimonstatic ENGINE *engine_ubsec(void) 262160814Ssimon { 263160814Ssimon ENGINE *ret = ENGINE_new(); 264160814Ssimon if(!ret) 265160814Ssimon return NULL; 266160814Ssimon if(!bind_helper(ret)) 267160814Ssimon { 268160814Ssimon ENGINE_free(ret); 269160814Ssimon return NULL; 270160814Ssimon } 271160814Ssimon return ret; 272160814Ssimon } 273160814Ssimon 274160814Ssimonvoid ENGINE_load_ubsec(void) 275160814Ssimon { 276160814Ssimon /* Copied from eng_[openssl|dyn].c */ 277160814Ssimon ENGINE *toadd = engine_ubsec(); 278160814Ssimon if(!toadd) return; 279160814Ssimon ENGINE_add(toadd); 280160814Ssimon ENGINE_free(toadd); 281160814Ssimon ERR_clear_error(); 282160814Ssimon } 283160814Ssimon#endif 284160814Ssimon 285160814Ssimon/* This is a process-global DSO handle used for loading and unloading 286160814Ssimon * the UBSEC library. NB: This is only set (or unset) during an 287160814Ssimon * init() or finish() call (reference counts permitting) and they're 288160814Ssimon * operating with global locks, so this should be thread-safe 289160814Ssimon * implicitly. */ 290160814Ssimon 291160814Ssimonstatic DSO *ubsec_dso = NULL; 292160814Ssimon 293160814Ssimon/* These are the function pointers that are (un)set when the library has 294160814Ssimon * successfully (un)loaded. */ 295160814Ssimon 296160814Ssimonstatic t_UBSEC_ubsec_bytes_to_bits *p_UBSEC_ubsec_bytes_to_bits = NULL; 297160814Ssimonstatic t_UBSEC_ubsec_bits_to_bytes *p_UBSEC_ubsec_bits_to_bytes = NULL; 298160814Ssimonstatic t_UBSEC_ubsec_open *p_UBSEC_ubsec_open = NULL; 299160814Ssimonstatic t_UBSEC_ubsec_close *p_UBSEC_ubsec_close = NULL; 300160814Ssimon#ifndef OPENSSL_NO_DH 301160814Ssimonstatic t_UBSEC_diffie_hellman_generate_ioctl 302160814Ssimon *p_UBSEC_diffie_hellman_generate_ioctl = NULL; 303160814Ssimonstatic t_UBSEC_diffie_hellman_agree_ioctl *p_UBSEC_diffie_hellman_agree_ioctl = NULL; 304160814Ssimon#endif 305238405Sjkim#ifndef OPENSSL_NO_RSA 306160814Ssimonstatic t_UBSEC_rsa_mod_exp_ioctl *p_UBSEC_rsa_mod_exp_ioctl = NULL; 307160814Ssimonstatic t_UBSEC_rsa_mod_exp_crt_ioctl *p_UBSEC_rsa_mod_exp_crt_ioctl = NULL; 308238405Sjkim#endif 309160814Ssimon#ifndef OPENSSL_NO_DSA 310160814Ssimonstatic t_UBSEC_dsa_sign_ioctl *p_UBSEC_dsa_sign_ioctl = NULL; 311160814Ssimonstatic t_UBSEC_dsa_verify_ioctl *p_UBSEC_dsa_verify_ioctl = NULL; 312160814Ssimon#endif 313160814Ssimonstatic t_UBSEC_math_accelerate_ioctl *p_UBSEC_math_accelerate_ioctl = NULL; 314160814Ssimonstatic t_UBSEC_rng_ioctl *p_UBSEC_rng_ioctl = NULL; 315160814Ssimonstatic t_UBSEC_max_key_len_ioctl *p_UBSEC_max_key_len_ioctl = NULL; 316160814Ssimon 317160814Ssimonstatic int max_key_len = 1024; /* ??? */ 318160814Ssimon 319160814Ssimon/* 320160814Ssimon * These are the static string constants for the DSO file name and the function 321160814Ssimon * symbol names to bind to. 322160814Ssimon */ 323160814Ssimon 324160814Ssimonstatic const char *UBSEC_LIBNAME = NULL; 325160814Ssimonstatic const char *get_UBSEC_LIBNAME(void) 326160814Ssimon { 327160814Ssimon if(UBSEC_LIBNAME) 328160814Ssimon return UBSEC_LIBNAME; 329160814Ssimon return "ubsec"; 330160814Ssimon } 331160814Ssimonstatic void free_UBSEC_LIBNAME(void) 332160814Ssimon { 333160814Ssimon if(UBSEC_LIBNAME) 334160814Ssimon OPENSSL_free((void*)UBSEC_LIBNAME); 335160814Ssimon UBSEC_LIBNAME = NULL; 336160814Ssimon } 337160814Ssimonstatic long set_UBSEC_LIBNAME(const char *name) 338160814Ssimon { 339160814Ssimon free_UBSEC_LIBNAME(); 340160814Ssimon return (((UBSEC_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0); 341160814Ssimon } 342160814Ssimonstatic const char *UBSEC_F1 = "ubsec_bytes_to_bits"; 343160814Ssimonstatic const char *UBSEC_F2 = "ubsec_bits_to_bytes"; 344160814Ssimonstatic const char *UBSEC_F3 = "ubsec_open"; 345160814Ssimonstatic const char *UBSEC_F4 = "ubsec_close"; 346160814Ssimon#ifndef OPENSSL_NO_DH 347160814Ssimonstatic const char *UBSEC_F5 = "diffie_hellman_generate_ioctl"; 348160814Ssimonstatic const char *UBSEC_F6 = "diffie_hellman_agree_ioctl"; 349160814Ssimon#endif 350160814Ssimon/* #ifndef OPENSSL_NO_RSA */ 351160814Ssimonstatic const char *UBSEC_F7 = "rsa_mod_exp_ioctl"; 352160814Ssimonstatic const char *UBSEC_F8 = "rsa_mod_exp_crt_ioctl"; 353160814Ssimon/* #endif */ 354160814Ssimon#ifndef OPENSSL_NO_DSA 355160814Ssimonstatic const char *UBSEC_F9 = "dsa_sign_ioctl"; 356160814Ssimonstatic const char *UBSEC_F10 = "dsa_verify_ioctl"; 357160814Ssimon#endif 358160814Ssimonstatic const char *UBSEC_F11 = "math_accelerate_ioctl"; 359160814Ssimonstatic const char *UBSEC_F12 = "rng_ioctl"; 360160814Ssimonstatic const char *UBSEC_F13 = "ubsec_max_key_len_ioctl"; 361160814Ssimon 362160814Ssimon/* Destructor (complements the "ENGINE_ubsec()" constructor) */ 363160814Ssimonstatic int ubsec_destroy(ENGINE *e) 364160814Ssimon { 365160814Ssimon free_UBSEC_LIBNAME(); 366160814Ssimon ERR_unload_UBSEC_strings(); 367160814Ssimon return 1; 368160814Ssimon } 369160814Ssimon 370160814Ssimon/* (de)initialisation functions. */ 371160814Ssimonstatic int ubsec_init(ENGINE *e) 372160814Ssimon { 373160814Ssimon t_UBSEC_ubsec_bytes_to_bits *p1; 374160814Ssimon t_UBSEC_ubsec_bits_to_bytes *p2; 375160814Ssimon t_UBSEC_ubsec_open *p3; 376160814Ssimon t_UBSEC_ubsec_close *p4; 377160814Ssimon#ifndef OPENSSL_NO_DH 378160814Ssimon t_UBSEC_diffie_hellman_generate_ioctl *p5; 379160814Ssimon t_UBSEC_diffie_hellman_agree_ioctl *p6; 380160814Ssimon#endif 381160814Ssimon/* #ifndef OPENSSL_NO_RSA */ 382160814Ssimon t_UBSEC_rsa_mod_exp_ioctl *p7; 383160814Ssimon t_UBSEC_rsa_mod_exp_crt_ioctl *p8; 384160814Ssimon/* #endif */ 385160814Ssimon#ifndef OPENSSL_NO_DSA 386160814Ssimon t_UBSEC_dsa_sign_ioctl *p9; 387160814Ssimon t_UBSEC_dsa_verify_ioctl *p10; 388160814Ssimon#endif 389160814Ssimon t_UBSEC_math_accelerate_ioctl *p11; 390160814Ssimon t_UBSEC_rng_ioctl *p12; 391160814Ssimon t_UBSEC_max_key_len_ioctl *p13; 392160814Ssimon int fd = 0; 393160814Ssimon 394160814Ssimon if(ubsec_dso != NULL) 395160814Ssimon { 396160814Ssimon UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_ALREADY_LOADED); 397160814Ssimon goto err; 398160814Ssimon } 399160814Ssimon /* 400160814Ssimon * Attempt to load libubsec.so/ubsec.dll/whatever. 401160814Ssimon */ 402160814Ssimon ubsec_dso = DSO_load(NULL, get_UBSEC_LIBNAME(), NULL, 0); 403160814Ssimon if(ubsec_dso == NULL) 404160814Ssimon { 405160814Ssimon UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE); 406160814Ssimon goto err; 407160814Ssimon } 408160814Ssimon 409160814Ssimon if ( 410160814Ssimon !(p1 = (t_UBSEC_ubsec_bytes_to_bits *) DSO_bind_func(ubsec_dso, UBSEC_F1)) || 411160814Ssimon !(p2 = (t_UBSEC_ubsec_bits_to_bytes *) DSO_bind_func(ubsec_dso, UBSEC_F2)) || 412160814Ssimon !(p3 = (t_UBSEC_ubsec_open *) DSO_bind_func(ubsec_dso, UBSEC_F3)) || 413160814Ssimon !(p4 = (t_UBSEC_ubsec_close *) DSO_bind_func(ubsec_dso, UBSEC_F4)) || 414160814Ssimon#ifndef OPENSSL_NO_DH 415160814Ssimon !(p5 = (t_UBSEC_diffie_hellman_generate_ioctl *) 416160814Ssimon DSO_bind_func(ubsec_dso, UBSEC_F5)) || 417160814Ssimon !(p6 = (t_UBSEC_diffie_hellman_agree_ioctl *) 418160814Ssimon DSO_bind_func(ubsec_dso, UBSEC_F6)) || 419160814Ssimon#endif 420160814Ssimon/* #ifndef OPENSSL_NO_RSA */ 421160814Ssimon !(p7 = (t_UBSEC_rsa_mod_exp_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F7)) || 422160814Ssimon !(p8 = (t_UBSEC_rsa_mod_exp_crt_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F8)) || 423160814Ssimon/* #endif */ 424160814Ssimon#ifndef OPENSSL_NO_DSA 425160814Ssimon !(p9 = (t_UBSEC_dsa_sign_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F9)) || 426160814Ssimon !(p10 = (t_UBSEC_dsa_verify_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F10)) || 427160814Ssimon#endif 428160814Ssimon !(p11 = (t_UBSEC_math_accelerate_ioctl *) 429160814Ssimon DSO_bind_func(ubsec_dso, UBSEC_F11)) || 430160814Ssimon !(p12 = (t_UBSEC_rng_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F12)) || 431160814Ssimon !(p13 = (t_UBSEC_max_key_len_ioctl *) DSO_bind_func(ubsec_dso, UBSEC_F13))) 432160814Ssimon { 433160814Ssimon UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_DSO_FAILURE); 434160814Ssimon goto err; 435160814Ssimon } 436160814Ssimon 437160814Ssimon /* Copy the pointers */ 438160814Ssimon p_UBSEC_ubsec_bytes_to_bits = p1; 439160814Ssimon p_UBSEC_ubsec_bits_to_bytes = p2; 440160814Ssimon p_UBSEC_ubsec_open = p3; 441160814Ssimon p_UBSEC_ubsec_close = p4; 442160814Ssimon#ifndef OPENSSL_NO_DH 443160814Ssimon p_UBSEC_diffie_hellman_generate_ioctl = p5; 444160814Ssimon p_UBSEC_diffie_hellman_agree_ioctl = p6; 445160814Ssimon#endif 446160814Ssimon#ifndef OPENSSL_NO_RSA 447160814Ssimon p_UBSEC_rsa_mod_exp_ioctl = p7; 448160814Ssimon p_UBSEC_rsa_mod_exp_crt_ioctl = p8; 449160814Ssimon#endif 450160814Ssimon#ifndef OPENSSL_NO_DSA 451160814Ssimon p_UBSEC_dsa_sign_ioctl = p9; 452160814Ssimon p_UBSEC_dsa_verify_ioctl = p10; 453160814Ssimon#endif 454160814Ssimon p_UBSEC_math_accelerate_ioctl = p11; 455160814Ssimon p_UBSEC_rng_ioctl = p12; 456160814Ssimon p_UBSEC_max_key_len_ioctl = p13; 457160814Ssimon 458160814Ssimon /* Perform an open to see if there's actually any unit running. */ 459160814Ssimon if (((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) > 0) && (p_UBSEC_max_key_len_ioctl(fd, &max_key_len) == 0)) 460160814Ssimon { 461160814Ssimon p_UBSEC_ubsec_close(fd); 462160814Ssimon return 1; 463160814Ssimon } 464160814Ssimon else 465160814Ssimon { 466160814Ssimon UBSECerr(UBSEC_F_UBSEC_INIT, UBSEC_R_UNIT_FAILURE); 467160814Ssimon } 468160814Ssimon 469160814Ssimonerr: 470160814Ssimon if(ubsec_dso) 471160814Ssimon DSO_free(ubsec_dso); 472160814Ssimon ubsec_dso = NULL; 473160814Ssimon p_UBSEC_ubsec_bytes_to_bits = NULL; 474160814Ssimon p_UBSEC_ubsec_bits_to_bytes = NULL; 475160814Ssimon p_UBSEC_ubsec_open = NULL; 476160814Ssimon p_UBSEC_ubsec_close = NULL; 477160814Ssimon#ifndef OPENSSL_NO_DH 478160814Ssimon p_UBSEC_diffie_hellman_generate_ioctl = NULL; 479160814Ssimon p_UBSEC_diffie_hellman_agree_ioctl = NULL; 480160814Ssimon#endif 481160814Ssimon#ifndef OPENSSL_NO_RSA 482160814Ssimon p_UBSEC_rsa_mod_exp_ioctl = NULL; 483160814Ssimon p_UBSEC_rsa_mod_exp_crt_ioctl = NULL; 484160814Ssimon#endif 485160814Ssimon#ifndef OPENSSL_NO_DSA 486160814Ssimon p_UBSEC_dsa_sign_ioctl = NULL; 487160814Ssimon p_UBSEC_dsa_verify_ioctl = NULL; 488160814Ssimon#endif 489160814Ssimon p_UBSEC_math_accelerate_ioctl = NULL; 490160814Ssimon p_UBSEC_rng_ioctl = NULL; 491160814Ssimon p_UBSEC_max_key_len_ioctl = NULL; 492160814Ssimon 493160814Ssimon return 0; 494160814Ssimon } 495160814Ssimon 496160814Ssimonstatic int ubsec_finish(ENGINE *e) 497160814Ssimon { 498160814Ssimon free_UBSEC_LIBNAME(); 499160814Ssimon if(ubsec_dso == NULL) 500160814Ssimon { 501160814Ssimon UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_NOT_LOADED); 502160814Ssimon return 0; 503160814Ssimon } 504160814Ssimon if(!DSO_free(ubsec_dso)) 505160814Ssimon { 506160814Ssimon UBSECerr(UBSEC_F_UBSEC_FINISH, UBSEC_R_DSO_FAILURE); 507160814Ssimon return 0; 508160814Ssimon } 509160814Ssimon ubsec_dso = NULL; 510160814Ssimon p_UBSEC_ubsec_bytes_to_bits = NULL; 511160814Ssimon p_UBSEC_ubsec_bits_to_bytes = NULL; 512160814Ssimon p_UBSEC_ubsec_open = NULL; 513160814Ssimon p_UBSEC_ubsec_close = NULL; 514160814Ssimon#ifndef OPENSSL_NO_DH 515160814Ssimon p_UBSEC_diffie_hellman_generate_ioctl = NULL; 516160814Ssimon p_UBSEC_diffie_hellman_agree_ioctl = NULL; 517160814Ssimon#endif 518160814Ssimon#ifndef OPENSSL_NO_RSA 519160814Ssimon p_UBSEC_rsa_mod_exp_ioctl = NULL; 520160814Ssimon p_UBSEC_rsa_mod_exp_crt_ioctl = NULL; 521160814Ssimon#endif 522160814Ssimon#ifndef OPENSSL_NO_DSA 523160814Ssimon p_UBSEC_dsa_sign_ioctl = NULL; 524160814Ssimon p_UBSEC_dsa_verify_ioctl = NULL; 525160814Ssimon#endif 526160814Ssimon p_UBSEC_math_accelerate_ioctl = NULL; 527160814Ssimon p_UBSEC_rng_ioctl = NULL; 528160814Ssimon p_UBSEC_max_key_len_ioctl = NULL; 529160814Ssimon return 1; 530160814Ssimon } 531160814Ssimon 532160814Ssimonstatic int ubsec_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void)) 533160814Ssimon { 534160814Ssimon int initialised = ((ubsec_dso == NULL) ? 0 : 1); 535160814Ssimon switch(cmd) 536160814Ssimon { 537160814Ssimon case UBSEC_CMD_SO_PATH: 538160814Ssimon if(p == NULL) 539160814Ssimon { 540160814Ssimon UBSECerr(UBSEC_F_UBSEC_CTRL,ERR_R_PASSED_NULL_PARAMETER); 541160814Ssimon return 0; 542160814Ssimon } 543160814Ssimon if(initialised) 544160814Ssimon { 545160814Ssimon UBSECerr(UBSEC_F_UBSEC_CTRL,UBSEC_R_ALREADY_LOADED); 546160814Ssimon return 0; 547160814Ssimon } 548160814Ssimon return set_UBSEC_LIBNAME((const char *)p); 549160814Ssimon default: 550160814Ssimon break; 551160814Ssimon } 552160814Ssimon UBSECerr(UBSEC_F_UBSEC_CTRL,UBSEC_R_CTRL_COMMAND_NOT_IMPLEMENTED); 553160814Ssimon return 0; 554160814Ssimon } 555160814Ssimon 556160814Ssimonstatic int ubsec_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 557160814Ssimon const BIGNUM *m, BN_CTX *ctx) 558160814Ssimon { 559160814Ssimon int y_len = 0; 560160814Ssimon int fd; 561160814Ssimon 562160814Ssimon if(ubsec_dso == NULL) 563160814Ssimon { 564160814Ssimon UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_NOT_LOADED); 565160814Ssimon return 0; 566160814Ssimon } 567160814Ssimon 568160814Ssimon /* Check if hardware can't handle this argument. */ 569160814Ssimon y_len = BN_num_bits(m); 570160814Ssimon if (y_len > max_key_len) { 571160814Ssimon UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL); 572160814Ssimon return BN_mod_exp(r, a, p, m, ctx); 573160814Ssimon } 574160814Ssimon 575160814Ssimon if(!bn_wexpand(r, m->top)) 576160814Ssimon { 577160814Ssimon UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_BN_EXPAND_FAIL); 578160814Ssimon return 0; 579160814Ssimon } 580160814Ssimon 581160814Ssimon if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { 582160814Ssimon fd = 0; 583160814Ssimon UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_UNIT_FAILURE); 584160814Ssimon return BN_mod_exp(r, a, p, m, ctx); 585160814Ssimon } 586160814Ssimon 587160814Ssimon if (p_UBSEC_rsa_mod_exp_ioctl(fd, (unsigned char *)a->d, BN_num_bits(a), 588160814Ssimon (unsigned char *)m->d, BN_num_bits(m), (unsigned char *)p->d, 589160814Ssimon BN_num_bits(p), (unsigned char *)r->d, &y_len) != 0) 590160814Ssimon { 591160814Ssimon UBSECerr(UBSEC_F_UBSEC_MOD_EXP, UBSEC_R_REQUEST_FAILED); 592160814Ssimon p_UBSEC_ubsec_close(fd); 593160814Ssimon 594160814Ssimon return BN_mod_exp(r, a, p, m, ctx); 595160814Ssimon } 596160814Ssimon 597160814Ssimon p_UBSEC_ubsec_close(fd); 598160814Ssimon 599160814Ssimon r->top = (BN_num_bits(m)+BN_BITS2-1)/BN_BITS2; 600160814Ssimon return 1; 601160814Ssimon } 602160814Ssimon 603160814Ssimon#ifndef OPENSSL_NO_RSA 604160814Ssimonstatic int ubsec_rsa_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) 605160814Ssimon { 606160814Ssimon int to_return = 0; 607160814Ssimon 608160814Ssimon if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) 609160814Ssimon { 610160814Ssimon UBSECerr(UBSEC_F_UBSEC_RSA_MOD_EXP, UBSEC_R_MISSING_KEY_COMPONENTS); 611160814Ssimon goto err; 612160814Ssimon } 613160814Ssimon 614160814Ssimon to_return = ubsec_mod_exp_crt(r0, I, rsa->p, rsa->q, rsa->dmp1, 615160814Ssimon rsa->dmq1, rsa->iqmp, ctx); 616160814Ssimon if (to_return == FAIL_TO_SOFTWARE) 617160814Ssimon { 618160814Ssimon /* 619160814Ssimon * Do in software as hardware failed. 620160814Ssimon */ 621160814Ssimon const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); 622160814Ssimon to_return = (*meth->rsa_mod_exp)(r0, I, rsa, ctx); 623160814Ssimon } 624160814Ssimonerr: 625160814Ssimon return to_return; 626160814Ssimon } 627160814Ssimon 628160814Ssimonstatic int ubsec_mod_exp_crt(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 629160814Ssimon const BIGNUM *q, const BIGNUM *dp, 630160814Ssimon const BIGNUM *dq, const BIGNUM *qinv, BN_CTX *ctx) 631160814Ssimon { 632160814Ssimon int y_len, 633160814Ssimon fd; 634160814Ssimon 635160814Ssimon y_len = BN_num_bits(p) + BN_num_bits(q); 636160814Ssimon 637160814Ssimon /* Check if hardware can't handle this argument. */ 638160814Ssimon if (y_len > max_key_len) { 639160814Ssimon UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_SIZE_TOO_LARGE_OR_TOO_SMALL); 640160814Ssimon return FAIL_TO_SOFTWARE; 641160814Ssimon } 642160814Ssimon 643160814Ssimon if (!bn_wexpand(r, p->top + q->top + 1)) { 644160814Ssimon UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_BN_EXPAND_FAIL); 645160814Ssimon return 0; 646160814Ssimon } 647160814Ssimon 648160814Ssimon if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { 649160814Ssimon fd = 0; 650160814Ssimon UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_UNIT_FAILURE); 651160814Ssimon return FAIL_TO_SOFTWARE; 652160814Ssimon } 653160814Ssimon 654160814Ssimon if (p_UBSEC_rsa_mod_exp_crt_ioctl(fd, 655160814Ssimon (unsigned char *)a->d, BN_num_bits(a), 656160814Ssimon (unsigned char *)qinv->d, BN_num_bits(qinv), 657160814Ssimon (unsigned char *)dp->d, BN_num_bits(dp), 658160814Ssimon (unsigned char *)p->d, BN_num_bits(p), 659160814Ssimon (unsigned char *)dq->d, BN_num_bits(dq), 660160814Ssimon (unsigned char *)q->d, BN_num_bits(q), 661160814Ssimon (unsigned char *)r->d, &y_len) != 0) { 662160814Ssimon UBSECerr(UBSEC_F_UBSEC_MOD_EXP_CRT, UBSEC_R_REQUEST_FAILED); 663160814Ssimon p_UBSEC_ubsec_close(fd); 664160814Ssimon return FAIL_TO_SOFTWARE; 665160814Ssimon } 666160814Ssimon 667160814Ssimon p_UBSEC_ubsec_close(fd); 668160814Ssimon 669160814Ssimon r->top = (BN_num_bits(p) + BN_num_bits(q) + BN_BITS2 - 1)/BN_BITS2; 670160814Ssimon return 1; 671160814Ssimon} 672238405Sjkim#endif 673160814Ssimon 674160814Ssimon#ifndef OPENSSL_NO_DSA 675160814Ssimon#ifdef NOT_USED 676160814Ssimonstatic int ubsec_dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, 677160814Ssimon BIGNUM *p1, BIGNUM *a2, BIGNUM *p2, BIGNUM *m, 678160814Ssimon BN_CTX *ctx, BN_MONT_CTX *in_mont) 679160814Ssimon { 680160814Ssimon BIGNUM t; 681160814Ssimon int to_return = 0; 682160814Ssimon 683160814Ssimon BN_init(&t); 684160814Ssimon /* let rr = a1 ^ p1 mod m */ 685160814Ssimon if (!ubsec_mod_exp(rr,a1,p1,m,ctx)) goto end; 686160814Ssimon /* let t = a2 ^ p2 mod m */ 687160814Ssimon if (!ubsec_mod_exp(&t,a2,p2,m,ctx)) goto end; 688160814Ssimon /* let rr = rr * t mod m */ 689160814Ssimon if (!BN_mod_mul(rr,rr,&t,m,ctx)) goto end; 690160814Ssimon to_return = 1; 691160814Ssimonend: 692160814Ssimon BN_free(&t); 693160814Ssimon return to_return; 694160814Ssimon } 695160814Ssimon 696160814Ssimonstatic int ubsec_mod_exp_dsa(DSA *dsa, BIGNUM *r, BIGNUM *a, 697160814Ssimon const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 698160814Ssimon BN_MONT_CTX *m_ctx) 699160814Ssimon { 700160814Ssimon return ubsec_mod_exp(r, a, p, m, ctx); 701160814Ssimon } 702160814Ssimon#endif 703160814Ssimon#endif 704160814Ssimon 705238405Sjkim#ifndef OPENSSL_NO_RSA 706238405Sjkim 707160814Ssimon/* 708160814Ssimon * This function is aliased to mod_exp (with the mont stuff dropped). 709160814Ssimon */ 710160814Ssimonstatic int ubsec_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 711160814Ssimon const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) 712160814Ssimon { 713160814Ssimon int ret = 0; 714160814Ssimon 715160814Ssimon /* Do in software if the key is too large for the hardware. */ 716160814Ssimon if (BN_num_bits(m) > max_key_len) 717160814Ssimon { 718160814Ssimon const RSA_METHOD *meth = RSA_PKCS1_SSLeay(); 719160814Ssimon ret = (*meth->bn_mod_exp)(r, a, p, m, ctx, m_ctx); 720160814Ssimon } 721160814Ssimon else 722160814Ssimon { 723160814Ssimon ret = ubsec_mod_exp(r, a, p, m, ctx); 724160814Ssimon } 725160814Ssimon 726160814Ssimon return ret; 727160814Ssimon } 728238405Sjkim#endif 729160814Ssimon 730160814Ssimon#ifndef OPENSSL_NO_DH 731160814Ssimon/* This function is aliased to mod_exp (with the dh and mont dropped). */ 732160814Ssimonstatic int ubsec_mod_exp_dh(const DH *dh, BIGNUM *r, const BIGNUM *a, 733160814Ssimon const BIGNUM *p, const BIGNUM *m, BN_CTX *ctx, 734160814Ssimon BN_MONT_CTX *m_ctx) 735160814Ssimon { 736160814Ssimon return ubsec_mod_exp(r, a, p, m, ctx); 737160814Ssimon } 738160814Ssimon#endif 739160814Ssimon 740160814Ssimon#ifndef OPENSSL_NO_DSA 741160814Ssimonstatic DSA_SIG *ubsec_dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) 742160814Ssimon { 743160814Ssimon DSA_SIG *to_return = NULL; 744160814Ssimon int s_len = 160, r_len = 160, d_len, fd; 745160814Ssimon BIGNUM m, *r=NULL, *s=NULL; 746160814Ssimon 747160814Ssimon BN_init(&m); 748160814Ssimon 749160814Ssimon s = BN_new(); 750160814Ssimon r = BN_new(); 751160814Ssimon if ((s == NULL) || (r==NULL)) 752160814Ssimon goto err; 753160814Ssimon 754160814Ssimon d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dlen); 755160814Ssimon 756160814Ssimon if(!bn_wexpand(r, (160+BN_BITS2-1)/BN_BITS2) || 757160814Ssimon (!bn_wexpand(s, (160+BN_BITS2-1)/BN_BITS2))) { 758160814Ssimon UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL); 759160814Ssimon goto err; 760160814Ssimon } 761160814Ssimon 762160814Ssimon if (BN_bin2bn(dgst,dlen,&m) == NULL) { 763160814Ssimon UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL); 764160814Ssimon goto err; 765160814Ssimon } 766160814Ssimon 767160814Ssimon if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { 768160814Ssimon const DSA_METHOD *meth; 769160814Ssimon fd = 0; 770160814Ssimon UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_UNIT_FAILURE); 771160814Ssimon meth = DSA_OpenSSL(); 772160814Ssimon to_return = meth->dsa_do_sign(dgst, dlen, dsa); 773160814Ssimon goto err; 774160814Ssimon } 775160814Ssimon 776160814Ssimon if (p_UBSEC_dsa_sign_ioctl(fd, 0, /* compute hash before signing */ 777160814Ssimon (unsigned char *)dgst, d_len, 778160814Ssimon NULL, 0, /* compute random value */ 779160814Ssimon (unsigned char *)dsa->p->d, BN_num_bits(dsa->p), 780160814Ssimon (unsigned char *)dsa->q->d, BN_num_bits(dsa->q), 781160814Ssimon (unsigned char *)dsa->g->d, BN_num_bits(dsa->g), 782160814Ssimon (unsigned char *)dsa->priv_key->d, BN_num_bits(dsa->priv_key), 783160814Ssimon (unsigned char *)r->d, &r_len, 784160814Ssimon (unsigned char *)s->d, &s_len ) != 0) { 785160814Ssimon const DSA_METHOD *meth; 786160814Ssimon 787160814Ssimon UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_REQUEST_FAILED); 788160814Ssimon p_UBSEC_ubsec_close(fd); 789160814Ssimon meth = DSA_OpenSSL(); 790160814Ssimon to_return = meth->dsa_do_sign(dgst, dlen, dsa); 791160814Ssimon 792160814Ssimon goto err; 793160814Ssimon } 794160814Ssimon 795160814Ssimon p_UBSEC_ubsec_close(fd); 796160814Ssimon 797160814Ssimon r->top = (160+BN_BITS2-1)/BN_BITS2; 798160814Ssimon s->top = (160+BN_BITS2-1)/BN_BITS2; 799160814Ssimon 800160814Ssimon to_return = DSA_SIG_new(); 801160814Ssimon if(to_return == NULL) { 802160814Ssimon UBSECerr(UBSEC_F_UBSEC_DSA_DO_SIGN, UBSEC_R_BN_EXPAND_FAIL); 803160814Ssimon goto err; 804160814Ssimon } 805160814Ssimon 806160814Ssimon to_return->r = r; 807160814Ssimon to_return->s = s; 808160814Ssimon 809160814Ssimonerr: 810160814Ssimon if (!to_return) { 811160814Ssimon if (r) BN_free(r); 812160814Ssimon if (s) BN_free(s); 813160814Ssimon } 814160814Ssimon BN_clear_free(&m); 815160814Ssimon return to_return; 816160814Ssimon} 817160814Ssimon 818160814Ssimonstatic int ubsec_dsa_verify(const unsigned char *dgst, int dgst_len, 819160814Ssimon DSA_SIG *sig, DSA *dsa) 820160814Ssimon { 821160814Ssimon int v_len, d_len; 822160814Ssimon int to_return = 0; 823160814Ssimon int fd; 824194206Ssimon BIGNUM v, *pv = &v; 825160814Ssimon 826160814Ssimon BN_init(&v); 827160814Ssimon 828194206Ssimon if(!bn_wexpand(pv, dsa->p->top)) { 829160814Ssimon UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_BN_EXPAND_FAIL); 830160814Ssimon goto err; 831160814Ssimon } 832160814Ssimon 833160814Ssimon v_len = BN_num_bits(dsa->p); 834160814Ssimon 835160814Ssimon d_len = p_UBSEC_ubsec_bytes_to_bits((unsigned char *)dgst, dgst_len); 836160814Ssimon 837160814Ssimon if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) { 838160814Ssimon const DSA_METHOD *meth; 839160814Ssimon fd = 0; 840160814Ssimon UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_UNIT_FAILURE); 841160814Ssimon meth = DSA_OpenSSL(); 842160814Ssimon to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa); 843160814Ssimon goto err; 844160814Ssimon } 845160814Ssimon 846160814Ssimon if (p_UBSEC_dsa_verify_ioctl(fd, 0, /* compute hash before signing */ 847160814Ssimon (unsigned char *)dgst, d_len, 848160814Ssimon (unsigned char *)dsa->p->d, BN_num_bits(dsa->p), 849160814Ssimon (unsigned char *)dsa->q->d, BN_num_bits(dsa->q), 850160814Ssimon (unsigned char *)dsa->g->d, BN_num_bits(dsa->g), 851160814Ssimon (unsigned char *)dsa->pub_key->d, BN_num_bits(dsa->pub_key), 852160814Ssimon (unsigned char *)sig->r->d, BN_num_bits(sig->r), 853160814Ssimon (unsigned char *)sig->s->d, BN_num_bits(sig->s), 854160814Ssimon (unsigned char *)v.d, &v_len) != 0) { 855160814Ssimon const DSA_METHOD *meth; 856160814Ssimon UBSECerr(UBSEC_F_UBSEC_DSA_VERIFY, UBSEC_R_REQUEST_FAILED); 857160814Ssimon p_UBSEC_ubsec_close(fd); 858160814Ssimon 859160814Ssimon meth = DSA_OpenSSL(); 860160814Ssimon to_return = meth->dsa_do_verify(dgst, dgst_len, sig, dsa); 861160814Ssimon 862160814Ssimon goto err; 863160814Ssimon } 864160814Ssimon 865160814Ssimon p_UBSEC_ubsec_close(fd); 866160814Ssimon 867160814Ssimon to_return = 1; 868160814Ssimonerr: 869160814Ssimon BN_clear_free(&v); 870160814Ssimon return to_return; 871160814Ssimon } 872160814Ssimon#endif 873160814Ssimon 874160814Ssimon#ifndef OPENSSL_NO_DH 875160814Ssimonstatic int ubsec_dh_compute_key(unsigned char *key,const BIGNUM *pub_key,DH *dh) 876160814Ssimon { 877160814Ssimon int ret = -1, 878160814Ssimon k_len, 879160814Ssimon fd; 880160814Ssimon 881160814Ssimon k_len = BN_num_bits(dh->p); 882160814Ssimon 883160814Ssimon if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) 884160814Ssimon { 885160814Ssimon const DH_METHOD *meth; 886160814Ssimon UBSECerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, UBSEC_R_UNIT_FAILURE); 887160814Ssimon meth = DH_OpenSSL(); 888160814Ssimon ret = meth->compute_key(key, pub_key, dh); 889160814Ssimon goto err; 890160814Ssimon } 891160814Ssimon 892160814Ssimon if (p_UBSEC_diffie_hellman_agree_ioctl(fd, 893160814Ssimon (unsigned char *)dh->priv_key->d, BN_num_bits(dh->priv_key), 894160814Ssimon (unsigned char *)pub_key->d, BN_num_bits(pub_key), 895160814Ssimon (unsigned char *)dh->p->d, BN_num_bits(dh->p), 896160814Ssimon key, &k_len) != 0) 897160814Ssimon { 898160814Ssimon /* Hardware's a no go, failover to software */ 899160814Ssimon const DH_METHOD *meth; 900160814Ssimon UBSECerr(UBSEC_F_UBSEC_DH_COMPUTE_KEY, UBSEC_R_REQUEST_FAILED); 901160814Ssimon p_UBSEC_ubsec_close(fd); 902160814Ssimon 903160814Ssimon meth = DH_OpenSSL(); 904160814Ssimon ret = meth->compute_key(key, pub_key, dh); 905160814Ssimon 906160814Ssimon goto err; 907160814Ssimon } 908160814Ssimon 909160814Ssimon p_UBSEC_ubsec_close(fd); 910160814Ssimon 911160814Ssimon ret = p_UBSEC_ubsec_bits_to_bytes(k_len); 912160814Ssimonerr: 913160814Ssimon return ret; 914160814Ssimon } 915160814Ssimon 916160814Ssimonstatic int ubsec_dh_generate_key(DH *dh) 917160814Ssimon { 918160814Ssimon int ret = 0, 919160814Ssimon random_bits = 0, 920160814Ssimon pub_key_len = 0, 921160814Ssimon priv_key_len = 0, 922160814Ssimon fd; 923160814Ssimon BIGNUM *pub_key = NULL; 924160814Ssimon BIGNUM *priv_key = NULL; 925160814Ssimon 926160814Ssimon /* 927160814Ssimon * How many bits should Random x be? dh_key.c 928160814Ssimon * sets the range from 0 to num_bits(modulus) ??? 929160814Ssimon */ 930160814Ssimon 931160814Ssimon if (dh->priv_key == NULL) 932160814Ssimon { 933160814Ssimon priv_key = BN_new(); 934160814Ssimon if (priv_key == NULL) goto err; 935160814Ssimon priv_key_len = BN_num_bits(dh->p); 936205128Ssimon if(bn_wexpand(priv_key, dh->p->top) == NULL) goto err; 937160814Ssimon do 938160814Ssimon if (!BN_rand_range(priv_key, dh->p)) goto err; 939160814Ssimon while (BN_is_zero(priv_key)); 940160814Ssimon random_bits = BN_num_bits(priv_key); 941160814Ssimon } 942160814Ssimon else 943160814Ssimon { 944160814Ssimon priv_key = dh->priv_key; 945160814Ssimon } 946160814Ssimon 947160814Ssimon if (dh->pub_key == NULL) 948160814Ssimon { 949160814Ssimon pub_key = BN_new(); 950160814Ssimon pub_key_len = BN_num_bits(dh->p); 951205128Ssimon if(bn_wexpand(pub_key, dh->p->top) == NULL) goto err; 952160814Ssimon if(pub_key == NULL) goto err; 953160814Ssimon } 954160814Ssimon else 955160814Ssimon { 956160814Ssimon pub_key = dh->pub_key; 957160814Ssimon } 958160814Ssimon 959160814Ssimon if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) 960160814Ssimon { 961160814Ssimon const DH_METHOD *meth; 962160814Ssimon UBSECerr(UBSEC_F_UBSEC_DH_GENERATE_KEY, UBSEC_R_UNIT_FAILURE); 963160814Ssimon meth = DH_OpenSSL(); 964160814Ssimon ret = meth->generate_key(dh); 965160814Ssimon goto err; 966160814Ssimon } 967160814Ssimon 968160814Ssimon if (p_UBSEC_diffie_hellman_generate_ioctl(fd, 969160814Ssimon (unsigned char *)priv_key->d, &priv_key_len, 970160814Ssimon (unsigned char *)pub_key->d, &pub_key_len, 971160814Ssimon (unsigned char *)dh->g->d, BN_num_bits(dh->g), 972160814Ssimon (unsigned char *)dh->p->d, BN_num_bits(dh->p), 973160814Ssimon 0, 0, random_bits) != 0) 974160814Ssimon { 975160814Ssimon /* Hardware's a no go, failover to software */ 976160814Ssimon const DH_METHOD *meth; 977160814Ssimon 978160814Ssimon UBSECerr(UBSEC_F_UBSEC_DH_GENERATE_KEY, UBSEC_R_REQUEST_FAILED); 979160814Ssimon p_UBSEC_ubsec_close(fd); 980160814Ssimon 981160814Ssimon meth = DH_OpenSSL(); 982160814Ssimon ret = meth->generate_key(dh); 983160814Ssimon 984160814Ssimon goto err; 985160814Ssimon } 986160814Ssimon 987160814Ssimon p_UBSEC_ubsec_close(fd); 988160814Ssimon 989160814Ssimon dh->pub_key = pub_key; 990160814Ssimon dh->pub_key->top = (pub_key_len + BN_BITS2-1) / BN_BITS2; 991160814Ssimon dh->priv_key = priv_key; 992160814Ssimon dh->priv_key->top = (priv_key_len + BN_BITS2-1) / BN_BITS2; 993160814Ssimon 994160814Ssimon ret = 1; 995160814Ssimonerr: 996160814Ssimon return ret; 997160814Ssimon } 998160814Ssimon#endif 999160814Ssimon 1000160814Ssimon#ifdef NOT_USED 1001160814Ssimonstatic int ubsec_rand_bytes(unsigned char * buf, 1002160814Ssimon int num) 1003160814Ssimon { 1004160814Ssimon int ret = 0, 1005160814Ssimon fd; 1006160814Ssimon 1007160814Ssimon if ((fd = p_UBSEC_ubsec_open(UBSEC_KEY_DEVICE_NAME)) <= 0) 1008160814Ssimon { 1009160814Ssimon const RAND_METHOD *meth; 1010160814Ssimon UBSECerr(UBSEC_F_UBSEC_RAND_BYTES, UBSEC_R_UNIT_FAILURE); 1011160814Ssimon num = p_UBSEC_ubsec_bits_to_bytes(num); 1012160814Ssimon meth = RAND_SSLeay(); 1013160814Ssimon meth->seed(buf, num); 1014160814Ssimon ret = meth->bytes(buf, num); 1015160814Ssimon goto err; 1016160814Ssimon } 1017160814Ssimon 1018160814Ssimon num *= 8; /* bytes to bits */ 1019160814Ssimon 1020160814Ssimon if (p_UBSEC_rng_ioctl(fd, 1021160814Ssimon UBSEC_RNG_DIRECT, 1022160814Ssimon buf, 1023160814Ssimon &num) != 0) 1024160814Ssimon { 1025160814Ssimon /* Hardware's a no go, failover to software */ 1026160814Ssimon const RAND_METHOD *meth; 1027160814Ssimon 1028160814Ssimon UBSECerr(UBSEC_F_UBSEC_RAND_BYTES, UBSEC_R_REQUEST_FAILED); 1029160814Ssimon p_UBSEC_ubsec_close(fd); 1030160814Ssimon 1031160814Ssimon num = p_UBSEC_ubsec_bits_to_bytes(num); 1032160814Ssimon meth = RAND_SSLeay(); 1033160814Ssimon meth->seed(buf, num); 1034160814Ssimon ret = meth->bytes(buf, num); 1035160814Ssimon 1036160814Ssimon goto err; 1037160814Ssimon } 1038160814Ssimon 1039160814Ssimon p_UBSEC_ubsec_close(fd); 1040160814Ssimon 1041160814Ssimon ret = 1; 1042160814Ssimonerr: 1043160814Ssimon return(ret); 1044160814Ssimon } 1045160814Ssimon 1046160814Ssimon 1047160814Ssimonstatic int ubsec_rand_status(void) 1048160814Ssimon { 1049160814Ssimon return 0; 1050160814Ssimon } 1051160814Ssimon#endif 1052160814Ssimon 1053160814Ssimon/* This stuff is needed if this ENGINE is being compiled into a self-contained 1054160814Ssimon * shared-library. */ 1055160814Ssimon#ifndef OPENSSL_NO_DYNAMIC_ENGINE 1056160814Ssimonstatic int bind_fn(ENGINE *e, const char *id) 1057160814Ssimon { 1058160814Ssimon if(id && (strcmp(id, engine_ubsec_id) != 0)) 1059160814Ssimon return 0; 1060160814Ssimon if(!bind_helper(e)) 1061160814Ssimon return 0; 1062160814Ssimon return 1; 1063160814Ssimon } 1064160814SsimonIMPLEMENT_DYNAMIC_CHECK_FN() 1065160814SsimonIMPLEMENT_DYNAMIC_BIND_FN(bind_fn) 1066160814Ssimon#endif /* OPENSSL_NO_DYNAMIC_ENGINE */ 1067160814Ssimon 1068160814Ssimon#endif /* !OPENSSL_NO_HW_UBSEC */ 1069160814Ssimon#endif /* !OPENSSL_NO_HW */ 1070