1160814Ssimon/* crypto/engine/e_chil.c -*- mode: C; c-file-style: "eay" -*- */ 2296465Sdelphij/* 3296465Sdelphij * Written by Richard Levitte (richard@levitte.org), Geoff Thorpe 4296465Sdelphij * (geoff@geoffthorpe.net) and Dr Stephen N Henson (steve@openssl.org) for 5296465Sdelphij * the OpenSSL project 2000. 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 15296465Sdelphij * 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/pem.h> 65160814Ssimon#include <openssl/dso.h> 66160814Ssimon#include <openssl/engine.h> 67160814Ssimon#include <openssl/ui.h> 68160814Ssimon#include <openssl/rand.h> 69160814Ssimon#ifndef OPENSSL_NO_RSA 70296465Sdelphij# include <openssl/rsa.h> 71160814Ssimon#endif 72160814Ssimon#ifndef OPENSSL_NO_DH 73296465Sdelphij# include <openssl/dh.h> 74160814Ssimon#endif 75160814Ssimon#include <openssl/bn.h> 76160814Ssimon 77160814Ssimon#ifndef OPENSSL_NO_HW 78296465Sdelphij# ifndef OPENSSL_NO_HW_CHIL 79160814Ssimon 80296465Sdelphij/*- 81296465Sdelphij * Attribution notice: nCipher have said several times that it's OK for 82160814Ssimon * us to implement a general interface to their boxes, and recently declared 83160814Ssimon * their HWCryptoHook to be public, and therefore available for us to use. 84160814Ssimon * Thanks, nCipher. 85160814Ssimon * 86160814Ssimon * The hwcryptohook.h included here is from May 2000. 87160814Ssimon * [Richard Levitte] 88160814Ssimon */ 89296465Sdelphij# ifdef FLAT_INC 90296465Sdelphij# include "hwcryptohook.h" 91296465Sdelphij# else 92296465Sdelphij# include "vendor_defns/hwcryptohook.h" 93296465Sdelphij# endif 94160814Ssimon 95296465Sdelphij# define HWCRHK_LIB_NAME "CHIL engine" 96296465Sdelphij# include "e_chil_err.c" 97160814Ssimon 98160814Ssimonstatic int hwcrhk_destroy(ENGINE *e); 99160814Ssimonstatic int hwcrhk_init(ENGINE *e); 100160814Ssimonstatic int hwcrhk_finish(ENGINE *e); 101296465Sdelphijstatic int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)); 102160814Ssimon 103160814Ssimon/* Functions to handle mutexes */ 104296465Sdelphijstatic int hwcrhk_mutex_init(HWCryptoHook_Mutex *, 105296465Sdelphij HWCryptoHook_CallerContext *); 106296465Sdelphijstatic int hwcrhk_mutex_lock(HWCryptoHook_Mutex *); 107296465Sdelphijstatic void hwcrhk_mutex_unlock(HWCryptoHook_Mutex *); 108296465Sdelphijstatic void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *); 109160814Ssimon 110160814Ssimon/* BIGNUM stuff */ 111160814Ssimonstatic int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 112296465Sdelphij const BIGNUM *m, BN_CTX *ctx); 113160814Ssimon 114296465Sdelphij# ifndef OPENSSL_NO_RSA 115160814Ssimon/* RSA stuff */ 116296465Sdelphijstatic int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, 117296465Sdelphij BN_CTX *ctx); 118160814Ssimon/* This function is aliased to mod_exp (with the mont stuff dropped). */ 119160814Ssimonstatic int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 120296465Sdelphij const BIGNUM *m, BN_CTX *ctx, 121296465Sdelphij BN_MONT_CTX *m_ctx); 122215697Ssimonstatic int hwcrhk_rsa_finish(RSA *rsa); 123296465Sdelphij# endif 124160814Ssimon 125296465Sdelphij# ifndef OPENSSL_NO_DH 126160814Ssimon/* DH stuff */ 127160814Ssimon/* This function is alised to mod_exp (with the DH and mont dropped). */ 128160814Ssimonstatic int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r, 129296465Sdelphij const BIGNUM *a, const BIGNUM *p, 130296465Sdelphij const BIGNUM *m, BN_CTX *ctx, 131296465Sdelphij BN_MONT_CTX *m_ctx); 132296465Sdelphij# endif 133160814Ssimon 134160814Ssimon/* RAND stuff */ 135160814Ssimonstatic int hwcrhk_rand_bytes(unsigned char *buf, int num); 136160814Ssimonstatic int hwcrhk_rand_status(void); 137160814Ssimon 138160814Ssimon/* KM stuff */ 139160814Ssimonstatic EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id, 140296465Sdelphij UI_METHOD *ui_method, 141296465Sdelphij void *callback_data); 142160814Ssimonstatic EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id, 143296465Sdelphij UI_METHOD *ui_method, 144296465Sdelphij void *callback_data); 145160814Ssimon 146160814Ssimon/* Interaction stuff */ 147160814Ssimonstatic int hwcrhk_insert_card(const char *prompt_info, 148296465Sdelphij const char *wrong_info, 149296465Sdelphij HWCryptoHook_PassphraseContext * ppctx, 150296465Sdelphij HWCryptoHook_CallerContext * cactx); 151160814Ssimonstatic int hwcrhk_get_pass(const char *prompt_info, 152296465Sdelphij int *len_io, char *buf, 153296465Sdelphij HWCryptoHook_PassphraseContext * ppctx, 154296465Sdelphij HWCryptoHook_CallerContext * cactx); 155160814Ssimonstatic void hwcrhk_log_message(void *logstr, const char *message); 156160814Ssimon 157160814Ssimon/* The definitions for control commands specific to this engine */ 158296465Sdelphij# define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE 159296465Sdelphij# define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1) 160296465Sdelphij# define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2) 161296465Sdelphij# define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3) 162296465Sdelphij# define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4) 163160814Ssimonstatic const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = { 164296465Sdelphij {HWCRHK_CMD_SO_PATH, 165296465Sdelphij "SO_PATH", 166296465Sdelphij "Specifies the path to the 'hwcrhk' shared library", 167296465Sdelphij ENGINE_CMD_FLAG_STRING}, 168296465Sdelphij {HWCRHK_CMD_FORK_CHECK, 169296465Sdelphij "FORK_CHECK", 170296465Sdelphij "Turns fork() checking on (non-zero) or off (zero)", 171296465Sdelphij ENGINE_CMD_FLAG_NUMERIC}, 172296465Sdelphij {HWCRHK_CMD_THREAD_LOCKING, 173296465Sdelphij "THREAD_LOCKING", 174296465Sdelphij "Turns thread-safe locking on (zero) or off (non-zero)", 175296465Sdelphij ENGINE_CMD_FLAG_NUMERIC}, 176296465Sdelphij {HWCRHK_CMD_SET_USER_INTERFACE, 177296465Sdelphij "SET_USER_INTERFACE", 178296465Sdelphij "Set the global user interface (internal)", 179296465Sdelphij ENGINE_CMD_FLAG_INTERNAL}, 180296465Sdelphij {HWCRHK_CMD_SET_CALLBACK_DATA, 181296465Sdelphij "SET_CALLBACK_DATA", 182296465Sdelphij "Set the global user interface extra data (internal)", 183296465Sdelphij ENGINE_CMD_FLAG_INTERNAL}, 184296465Sdelphij {0, NULL, NULL, 0} 185296465Sdelphij}; 186160814Ssimon 187296465Sdelphij# ifndef OPENSSL_NO_RSA 188160814Ssimon/* Our internal RSA_METHOD that we provide pointers to */ 189296465Sdelphijstatic RSA_METHOD hwcrhk_rsa = { 190296465Sdelphij "CHIL RSA method", 191296465Sdelphij NULL, 192296465Sdelphij NULL, 193296465Sdelphij NULL, 194296465Sdelphij NULL, 195296465Sdelphij hwcrhk_rsa_mod_exp, 196296465Sdelphij hwcrhk_mod_exp_mont, 197296465Sdelphij NULL, 198296465Sdelphij hwcrhk_rsa_finish, 199296465Sdelphij 0, 200296465Sdelphij NULL, 201296465Sdelphij NULL, 202296465Sdelphij NULL, 203296465Sdelphij NULL 204296465Sdelphij}; 205296465Sdelphij# endif 206160814Ssimon 207296465Sdelphij# ifndef OPENSSL_NO_DH 208160814Ssimon/* Our internal DH_METHOD that we provide pointers to */ 209296465Sdelphijstatic DH_METHOD hwcrhk_dh = { 210296465Sdelphij "CHIL DH method", 211296465Sdelphij NULL, 212296465Sdelphij NULL, 213296465Sdelphij hwcrhk_mod_exp_dh, 214296465Sdelphij NULL, 215296465Sdelphij NULL, 216296465Sdelphij 0, 217296465Sdelphij NULL, 218296465Sdelphij NULL 219296465Sdelphij}; 220296465Sdelphij# endif 221160814Ssimon 222296465Sdelphijstatic RAND_METHOD hwcrhk_rand = { 223296465Sdelphij /* "CHIL RAND method", */ 224296465Sdelphij NULL, 225296465Sdelphij hwcrhk_rand_bytes, 226296465Sdelphij NULL, 227296465Sdelphij NULL, 228296465Sdelphij hwcrhk_rand_bytes, 229296465Sdelphij hwcrhk_rand_status, 230296465Sdelphij}; 231160814Ssimon 232160814Ssimon/* Constants used when creating the ENGINE */ 233160814Ssimonstatic const char *engine_hwcrhk_id = "chil"; 234160814Ssimonstatic const char *engine_hwcrhk_name = "CHIL hardware engine support"; 235160814Ssimon 236296465Sdelphij# ifndef OPENSSL_NO_DYNAMIC_ENGINE 237160814Ssimon/* Compatibility hack, the dynamic library uses this form in the path */ 238160814Ssimonstatic const char *engine_hwcrhk_id_alt = "ncipher"; 239296465Sdelphij# endif 240160814Ssimon 241160814Ssimon/* Internal stuff for HWCryptoHook */ 242160814Ssimon 243160814Ssimon/* Some structures needed for proper use of thread locks */ 244296465Sdelphij/* 245296465Sdelphij * hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue 246296465Sdelphij * into HWCryptoHook_Mutex 247296465Sdelphij */ 248296465Sdelphijstruct HWCryptoHook_MutexValue { 249296465Sdelphij int lockid; 250296465Sdelphij}; 251160814Ssimon 252296465Sdelphij/* 253296465Sdelphij * hwcryptohook.h has some typedefs that turn struct 254296465Sdelphij * HWCryptoHook_PassphraseContextValue into HWCryptoHook_PassphraseContext 255296465Sdelphij */ 256296465Sdelphijstruct HWCryptoHook_PassphraseContextValue { 257296465Sdelphij UI_METHOD *ui_method; 258296465Sdelphij void *callback_data; 259296465Sdelphij}; 260160814Ssimon 261296465Sdelphij/* 262296465Sdelphij * hwcryptohook.h has some typedefs that turn struct 263296465Sdelphij * HWCryptoHook_CallerContextValue into HWCryptoHook_CallerContext 264296465Sdelphij */ 265296465Sdelphijstruct HWCryptoHook_CallerContextValue { 266296465Sdelphij pem_password_cb *password_callback; /* Deprecated! Only present for 267296465Sdelphij * backward compatibility! */ 268296465Sdelphij UI_METHOD *ui_method; 269296465Sdelphij void *callback_data; 270296465Sdelphij}; 271160814Ssimon 272296465Sdelphij/* 273296465Sdelphij * The MPI structure in HWCryptoHook is pretty compatible with OpenSSL 274296465Sdelphij * BIGNUM's, so lets define a couple of conversion macros 275296465Sdelphij */ 276296465Sdelphij# define BN2MPI(mp, bn) \ 277160814Ssimon {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;} 278296465Sdelphij# define MPI2BN(bn, mp) \ 279160814Ssimon {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;} 280160814Ssimon 281160814Ssimonstatic BIO *logstream = NULL; 282160814Ssimonstatic int disable_mutex_callbacks = 0; 283160814Ssimon 284296465Sdelphij/* 285296465Sdelphij * One might wonder why these are needed, since one can pass down at least a 286296465Sdelphij * UI_METHOD and a pointer to callback data to the key-loading functions. The 287296465Sdelphij * thing is that the ModExp and RSAImmed functions can load keys as well, if 288296465Sdelphij * the data they get is in a special, nCipher-defined format (hint: if you 289296465Sdelphij * look at the private exponent of the RSA data as a string, you'll see this 290296465Sdelphij * string: "nCipher KM tool key id", followed by some bytes, followed a key 291296465Sdelphij * identity string, followed by more bytes. This happens when you use 292296465Sdelphij * "embed" keys instead of "hwcrhk" keys). Unfortunately, those functions do 293296465Sdelphij * not take any passphrase or caller context, and our functions can't really 294296465Sdelphij * take any callback data either. Still, the "insert_card" and 295296465Sdelphij * "get_passphrase" callbacks may be called down the line, and will need to 296296465Sdelphij * know what user interface callbacks to call, and having callback data from 297296465Sdelphij * the application may be a nice thing as well, so we need to keep track of 298296465Sdelphij * that globally. 299296465Sdelphij */ 300160814Ssimonstatic HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL }; 301160814Ssimon 302160814Ssimon/* Stuff to pass to the HWCryptoHook library */ 303160814Ssimonstatic HWCryptoHook_InitInfo hwcrhk_globals = { 304296465Sdelphij HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */ 305296465Sdelphij &logstream, /* logstream */ 306296465Sdelphij sizeof(BN_ULONG), /* limbsize */ 307296465Sdelphij 0, /* mslimb first: false for BNs */ 308296465Sdelphij -1, /* msbyte first: use native */ 309296465Sdelphij 0, /* Max mutexes, 0 = no small limit */ 310296465Sdelphij 0, /* Max simultaneous, 0 = default */ 311160814Ssimon 312296465Sdelphij /* 313296465Sdelphij * The next few are mutex stuff: we write wrapper functions around the OS 314296465Sdelphij * mutex functions. We initialise them to 0 here, and change that to 315296465Sdelphij * actual function pointers in hwcrhk_init() if dynamic locks are 316296465Sdelphij * supported (that is, if the application programmer has made sure of 317296465Sdelphij * setting up callbacks bafore starting this engine) *and* if 318296465Sdelphij * disable_mutex_callbacks hasn't been set by a call to 319296465Sdelphij * ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). 320296465Sdelphij */ 321296465Sdelphij sizeof(HWCryptoHook_Mutex), 322296465Sdelphij 0, 323296465Sdelphij 0, 324296465Sdelphij 0, 325296465Sdelphij 0, 326160814Ssimon 327296465Sdelphij /* 328296465Sdelphij * The next few are condvar stuff: we write wrapper functions round the 329296465Sdelphij * OS functions. Currently not implemented and not and absolute 330296465Sdelphij * necessity even in threaded programs, therefore 0'ed. Will hopefully 331296465Sdelphij * be implemented some day, since it enhances the efficiency of 332296465Sdelphij * HWCryptoHook. 333296465Sdelphij */ 334296465Sdelphij 0, /* sizeof(HWCryptoHook_CondVar), */ 335296465Sdelphij 0, /* hwcrhk_cv_init, */ 336296465Sdelphij 0, /* hwcrhk_cv_wait, */ 337296465Sdelphij 0, /* hwcrhk_cv_signal, */ 338296465Sdelphij 0, /* hwcrhk_cv_broadcast, */ 339296465Sdelphij 0, /* hwcrhk_cv_destroy, */ 340160814Ssimon 341296465Sdelphij hwcrhk_get_pass, /* pass phrase */ 342296465Sdelphij hwcrhk_insert_card, /* insert a card */ 343296465Sdelphij hwcrhk_log_message /* Log message */ 344160814Ssimon}; 345160814Ssimon 346160814Ssimon/* Now, to our own code */ 347160814Ssimon 348296465Sdelphij/* 349296465Sdelphij * This internal function is used by ENGINE_chil() and possibly by the 350296465Sdelphij * "dynamic" ENGINE support too 351296465Sdelphij */ 352160814Ssimonstatic int bind_helper(ENGINE *e) 353296465Sdelphij{ 354296465Sdelphij# ifndef OPENSSL_NO_RSA 355296465Sdelphij const RSA_METHOD *meth1; 356296465Sdelphij# endif 357296465Sdelphij# ifndef OPENSSL_NO_DH 358296465Sdelphij const DH_METHOD *meth2; 359296465Sdelphij# endif 360296465Sdelphij if (!ENGINE_set_id(e, engine_hwcrhk_id) || 361296465Sdelphij !ENGINE_set_name(e, engine_hwcrhk_name) || 362296465Sdelphij# ifndef OPENSSL_NO_RSA 363296465Sdelphij !ENGINE_set_RSA(e, &hwcrhk_rsa) || 364296465Sdelphij# endif 365296465Sdelphij# ifndef OPENSSL_NO_DH 366296465Sdelphij !ENGINE_set_DH(e, &hwcrhk_dh) || 367296465Sdelphij# endif 368296465Sdelphij !ENGINE_set_RAND(e, &hwcrhk_rand) || 369296465Sdelphij !ENGINE_set_destroy_function(e, hwcrhk_destroy) || 370296465Sdelphij !ENGINE_set_init_function(e, hwcrhk_init) || 371296465Sdelphij !ENGINE_set_finish_function(e, hwcrhk_finish) || 372296465Sdelphij !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) || 373296465Sdelphij !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) || 374296465Sdelphij !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) || 375296465Sdelphij !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns)) 376296465Sdelphij return 0; 377160814Ssimon 378296465Sdelphij# ifndef OPENSSL_NO_RSA 379296465Sdelphij /* 380296465Sdelphij * We know that the "PKCS1_SSLeay()" functions hook properly to the 381296465Sdelphij * cswift-specific mod_exp and mod_exp_crt so we use those functions. NB: 382296465Sdelphij * We don't use ENGINE_openssl() or anything "more generic" because 383296465Sdelphij * something like the RSAref code may not hook properly, and if you own 384296465Sdelphij * one of these cards then you have the right to do RSA operations on it 385296465Sdelphij * anyway! 386296465Sdelphij */ 387296465Sdelphij meth1 = RSA_PKCS1_SSLeay(); 388296465Sdelphij hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc; 389296465Sdelphij hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec; 390296465Sdelphij hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc; 391296465Sdelphij hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec; 392296465Sdelphij# endif 393160814Ssimon 394296465Sdelphij# ifndef OPENSSL_NO_DH 395296465Sdelphij /* Much the same for Diffie-Hellman */ 396296465Sdelphij meth2 = DH_OpenSSL(); 397296465Sdelphij hwcrhk_dh.generate_key = meth2->generate_key; 398296465Sdelphij hwcrhk_dh.compute_key = meth2->compute_key; 399296465Sdelphij# endif 400160814Ssimon 401296465Sdelphij /* Ensure the hwcrhk error handling is set up */ 402296465Sdelphij ERR_load_HWCRHK_strings(); 403296465Sdelphij return 1; 404296465Sdelphij} 405160814Ssimon 406296465Sdelphij# ifdef OPENSSL_NO_DYNAMIC_ENGINE 407160814Ssimonstatic ENGINE *engine_chil(void) 408296465Sdelphij{ 409296465Sdelphij ENGINE *ret = ENGINE_new(); 410296465Sdelphij if (!ret) 411296465Sdelphij return NULL; 412296465Sdelphij if (!bind_helper(ret)) { 413296465Sdelphij ENGINE_free(ret); 414296465Sdelphij return NULL; 415296465Sdelphij } 416296465Sdelphij return ret; 417296465Sdelphij} 418160814Ssimon 419160814Ssimonvoid ENGINE_load_chil(void) 420296465Sdelphij{ 421296465Sdelphij /* Copied from eng_[openssl|dyn].c */ 422296465Sdelphij ENGINE *toadd = engine_chil(); 423296465Sdelphij if (!toadd) 424296465Sdelphij return; 425296465Sdelphij ENGINE_add(toadd); 426296465Sdelphij ENGINE_free(toadd); 427296465Sdelphij ERR_clear_error(); 428296465Sdelphij} 429296465Sdelphij# endif 430160814Ssimon 431296465Sdelphij/* 432296465Sdelphij * This is a process-global DSO handle used for loading and unloading the 433296465Sdelphij * HWCryptoHook library. NB: This is only set (or unset) during an init() or 434296465Sdelphij * finish() call (reference counts permitting) and they're operating with 435296465Sdelphij * global locks, so this should be thread-safe implicitly. 436296465Sdelphij */ 437160814Ssimonstatic DSO *hwcrhk_dso = NULL; 438160814Ssimonstatic HWCryptoHook_ContextHandle hwcrhk_context = 0; 439296465Sdelphij# ifndef OPENSSL_NO_RSA 440296465Sdelphij/* Index for KM handle. Not really used yet. */ 441296465Sdelphijstatic int hndidx_rsa = -1; 442296465Sdelphij# endif 443160814Ssimon 444296465Sdelphij/* 445296465Sdelphij * These are the function pointers that are (un)set when the library has 446296465Sdelphij * successfully (un)loaded. 447296465Sdelphij */ 448160814Ssimonstatic HWCryptoHook_Init_t *p_hwcrhk_Init = NULL; 449160814Ssimonstatic HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL; 450160814Ssimonstatic HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL; 451296465Sdelphij# ifndef OPENSSL_NO_RSA 452160814Ssimonstatic HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL; 453296465Sdelphij# endif 454160814Ssimonstatic HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL; 455296465Sdelphij# ifndef OPENSSL_NO_RSA 456160814Ssimonstatic HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL; 457160814Ssimonstatic HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL; 458160814Ssimonstatic HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL; 459296465Sdelphij# endif 460160814Ssimonstatic HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL; 461160814Ssimon 462160814Ssimon/* Used in the DSO operations. */ 463160814Ssimonstatic const char *HWCRHK_LIBNAME = NULL; 464160814Ssimonstatic void free_HWCRHK_LIBNAME(void) 465296465Sdelphij{ 466296465Sdelphij if (HWCRHK_LIBNAME) 467296465Sdelphij OPENSSL_free((void *)HWCRHK_LIBNAME); 468296465Sdelphij HWCRHK_LIBNAME = NULL; 469296465Sdelphij} 470296465Sdelphij 471160814Ssimonstatic const char *get_HWCRHK_LIBNAME(void) 472296465Sdelphij{ 473296465Sdelphij if (HWCRHK_LIBNAME) 474296465Sdelphij return HWCRHK_LIBNAME; 475296465Sdelphij return "nfhwcrhk"; 476296465Sdelphij} 477296465Sdelphij 478160814Ssimonstatic long set_HWCRHK_LIBNAME(const char *name) 479296465Sdelphij{ 480296465Sdelphij free_HWCRHK_LIBNAME(); 481296465Sdelphij return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0); 482296465Sdelphij} 483296465Sdelphij 484160814Ssimonstatic const char *n_hwcrhk_Init = "HWCryptoHook_Init"; 485160814Ssimonstatic const char *n_hwcrhk_Finish = "HWCryptoHook_Finish"; 486160814Ssimonstatic const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp"; 487296465Sdelphij# ifndef OPENSSL_NO_RSA 488160814Ssimonstatic const char *n_hwcrhk_RSA = "HWCryptoHook_RSA"; 489296465Sdelphij# endif 490160814Ssimonstatic const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes"; 491296465Sdelphij# ifndef OPENSSL_NO_RSA 492160814Ssimonstatic const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey"; 493160814Ssimonstatic const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey"; 494160814Ssimonstatic const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey"; 495296465Sdelphij# endif 496160814Ssimonstatic const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT"; 497160814Ssimon 498296465Sdelphij/* 499296465Sdelphij * HWCryptoHook library functions and mechanics - these are used by the 500296465Sdelphij * higher-level functions further down. NB: As and where there's no error 501296465Sdelphij * checking, take a look lower down where these functions are called, the 502296465Sdelphij * checking and error handling is probably down there. 503296465Sdelphij */ 504160814Ssimon 505160814Ssimon/* utility function to obtain a context */ 506296465Sdelphijstatic int get_context(HWCryptoHook_ContextHandle * hac, 507296465Sdelphij HWCryptoHook_CallerContext * cac) 508296465Sdelphij{ 509296465Sdelphij char tempbuf[1024]; 510296465Sdelphij HWCryptoHook_ErrMsgBuf rmsg; 511160814Ssimon 512296465Sdelphij rmsg.buf = tempbuf; 513296465Sdelphij rmsg.size = sizeof(tempbuf); 514160814Ssimon 515296465Sdelphij *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg, cac); 516296465Sdelphij if (!*hac) 517296465Sdelphij return 0; 518296465Sdelphij return 1; 519296465Sdelphij} 520296465Sdelphij 521160814Ssimon/* similarly to release one. */ 522160814Ssimonstatic void release_context(HWCryptoHook_ContextHandle hac) 523296465Sdelphij{ 524296465Sdelphij p_hwcrhk_Finish(hac); 525296465Sdelphij} 526160814Ssimon 527160814Ssimon/* Destructor (complements the "ENGINE_chil()" constructor) */ 528160814Ssimonstatic int hwcrhk_destroy(ENGINE *e) 529296465Sdelphij{ 530296465Sdelphij free_HWCRHK_LIBNAME(); 531296465Sdelphij ERR_unload_HWCRHK_strings(); 532296465Sdelphij return 1; 533296465Sdelphij} 534160814Ssimon 535160814Ssimon/* (de)initialisation functions. */ 536160814Ssimonstatic int hwcrhk_init(ENGINE *e) 537296465Sdelphij{ 538296465Sdelphij HWCryptoHook_Init_t *p1; 539296465Sdelphij HWCryptoHook_Finish_t *p2; 540296465Sdelphij HWCryptoHook_ModExp_t *p3; 541296465Sdelphij# ifndef OPENSSL_NO_RSA 542296465Sdelphij HWCryptoHook_RSA_t *p4; 543296465Sdelphij HWCryptoHook_RSALoadKey_t *p5; 544296465Sdelphij HWCryptoHook_RSAGetPublicKey_t *p6; 545296465Sdelphij HWCryptoHook_RSAUnloadKey_t *p7; 546296465Sdelphij# endif 547296465Sdelphij HWCryptoHook_RandomBytes_t *p8; 548296465Sdelphij HWCryptoHook_ModExpCRT_t *p9; 549160814Ssimon 550296465Sdelphij if (hwcrhk_dso != NULL) { 551296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_ALREADY_LOADED); 552296465Sdelphij goto err; 553296465Sdelphij } 554296465Sdelphij /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */ 555296465Sdelphij hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0); 556296465Sdelphij if (hwcrhk_dso == NULL) { 557296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE); 558296465Sdelphij goto err; 559296465Sdelphij } 560296465Sdelphij if (!(p1 = (HWCryptoHook_Init_t *) 561296465Sdelphij DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) || 562296465Sdelphij !(p2 = (HWCryptoHook_Finish_t *) 563296465Sdelphij DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) || 564296465Sdelphij !(p3 = (HWCryptoHook_ModExp_t *) 565296465Sdelphij DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) || 566296465Sdelphij# ifndef OPENSSL_NO_RSA 567296465Sdelphij !(p4 = (HWCryptoHook_RSA_t *) 568296465Sdelphij DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) || 569296465Sdelphij !(p5 = (HWCryptoHook_RSALoadKey_t *) 570296465Sdelphij DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) || 571296465Sdelphij !(p6 = (HWCryptoHook_RSAGetPublicKey_t *) 572296465Sdelphij DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) || 573296465Sdelphij !(p7 = (HWCryptoHook_RSAUnloadKey_t *) 574296465Sdelphij DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) || 575296465Sdelphij# endif 576296465Sdelphij !(p8 = (HWCryptoHook_RandomBytes_t *) 577296465Sdelphij DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) || 578296465Sdelphij !(p9 = (HWCryptoHook_ModExpCRT_t *) 579296465Sdelphij DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT))) { 580296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE); 581296465Sdelphij goto err; 582296465Sdelphij } 583296465Sdelphij /* Copy the pointers */ 584296465Sdelphij p_hwcrhk_Init = p1; 585296465Sdelphij p_hwcrhk_Finish = p2; 586296465Sdelphij p_hwcrhk_ModExp = p3; 587296465Sdelphij# ifndef OPENSSL_NO_RSA 588296465Sdelphij p_hwcrhk_RSA = p4; 589296465Sdelphij p_hwcrhk_RSALoadKey = p5; 590296465Sdelphij p_hwcrhk_RSAGetPublicKey = p6; 591296465Sdelphij p_hwcrhk_RSAUnloadKey = p7; 592296465Sdelphij# endif 593296465Sdelphij p_hwcrhk_RandomBytes = p8; 594296465Sdelphij p_hwcrhk_ModExpCRT = p9; 595160814Ssimon 596296465Sdelphij /* 597296465Sdelphij * Check if the application decided to support dynamic locks, and if it 598296465Sdelphij * does, use them. 599296465Sdelphij */ 600296465Sdelphij if (disable_mutex_callbacks == 0) { 601296465Sdelphij if (CRYPTO_get_dynlock_create_callback() != NULL && 602296465Sdelphij CRYPTO_get_dynlock_lock_callback() != NULL && 603296465Sdelphij CRYPTO_get_dynlock_destroy_callback() != NULL) { 604296465Sdelphij hwcrhk_globals.mutex_init = hwcrhk_mutex_init; 605296465Sdelphij hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock; 606296465Sdelphij hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock; 607296465Sdelphij hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy; 608296465Sdelphij } 609296465Sdelphij } 610160814Ssimon 611296465Sdelphij /* 612296465Sdelphij * Try and get a context - if not, we may have a DSO but no accelerator! 613296465Sdelphij */ 614296465Sdelphij if (!get_context(&hwcrhk_context, &password_context)) { 615296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_UNIT_FAILURE); 616296465Sdelphij goto err; 617296465Sdelphij } 618296465Sdelphij /* Everything's fine. */ 619296465Sdelphij# ifndef OPENSSL_NO_RSA 620296465Sdelphij if (hndidx_rsa == -1) 621296465Sdelphij hndidx_rsa = RSA_get_ex_new_index(0, 622296465Sdelphij "nFast HWCryptoHook RSA key handle", 623296465Sdelphij NULL, NULL, NULL); 624296465Sdelphij# endif 625296465Sdelphij return 1; 626296465Sdelphij err: 627296465Sdelphij if (hwcrhk_dso) 628296465Sdelphij DSO_free(hwcrhk_dso); 629296465Sdelphij hwcrhk_dso = NULL; 630296465Sdelphij p_hwcrhk_Init = NULL; 631296465Sdelphij p_hwcrhk_Finish = NULL; 632296465Sdelphij p_hwcrhk_ModExp = NULL; 633296465Sdelphij# ifndef OPENSSL_NO_RSA 634296465Sdelphij p_hwcrhk_RSA = NULL; 635296465Sdelphij p_hwcrhk_RSALoadKey = NULL; 636296465Sdelphij p_hwcrhk_RSAGetPublicKey = NULL; 637296465Sdelphij p_hwcrhk_RSAUnloadKey = NULL; 638296465Sdelphij# endif 639296465Sdelphij p_hwcrhk_ModExpCRT = NULL; 640296465Sdelphij p_hwcrhk_RandomBytes = NULL; 641296465Sdelphij return 0; 642296465Sdelphij} 643160814Ssimon 644160814Ssimonstatic int hwcrhk_finish(ENGINE *e) 645296465Sdelphij{ 646296465Sdelphij int to_return = 1; 647296465Sdelphij free_HWCRHK_LIBNAME(); 648296465Sdelphij if (hwcrhk_dso == NULL) { 649296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_NOT_LOADED); 650296465Sdelphij to_return = 0; 651296465Sdelphij goto err; 652296465Sdelphij } 653296465Sdelphij release_context(hwcrhk_context); 654296465Sdelphij if (!DSO_free(hwcrhk_dso)) { 655296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_DSO_FAILURE); 656296465Sdelphij to_return = 0; 657296465Sdelphij goto err; 658296465Sdelphij } 659160814Ssimon err: 660296465Sdelphij if (logstream) 661296465Sdelphij BIO_free(logstream); 662296465Sdelphij hwcrhk_dso = NULL; 663296465Sdelphij p_hwcrhk_Init = NULL; 664296465Sdelphij p_hwcrhk_Finish = NULL; 665296465Sdelphij p_hwcrhk_ModExp = NULL; 666296465Sdelphij# ifndef OPENSSL_NO_RSA 667296465Sdelphij p_hwcrhk_RSA = NULL; 668296465Sdelphij p_hwcrhk_RSALoadKey = NULL; 669296465Sdelphij p_hwcrhk_RSAGetPublicKey = NULL; 670296465Sdelphij p_hwcrhk_RSAUnloadKey = NULL; 671296465Sdelphij# endif 672296465Sdelphij p_hwcrhk_ModExpCRT = NULL; 673296465Sdelphij p_hwcrhk_RandomBytes = NULL; 674296465Sdelphij return to_return; 675296465Sdelphij} 676160814Ssimon 677296465Sdelphijstatic int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) 678296465Sdelphij{ 679296465Sdelphij int to_return = 1; 680160814Ssimon 681296465Sdelphij switch (cmd) { 682296465Sdelphij case HWCRHK_CMD_SO_PATH: 683296465Sdelphij if (hwcrhk_dso) { 684296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_ALREADY_LOADED); 685296465Sdelphij return 0; 686296465Sdelphij } 687296465Sdelphij if (p == NULL) { 688296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, ERR_R_PASSED_NULL_PARAMETER); 689296465Sdelphij return 0; 690296465Sdelphij } 691296465Sdelphij return set_HWCRHK_LIBNAME((const char *)p); 692296465Sdelphij case ENGINE_CTRL_SET_LOGSTREAM: 693296465Sdelphij { 694296465Sdelphij BIO *bio = (BIO *)p; 695160814Ssimon 696296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 697296465Sdelphij if (logstream) { 698296465Sdelphij BIO_free(logstream); 699296465Sdelphij logstream = NULL; 700296465Sdelphij } 701296465Sdelphij if (CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO) > 1) 702296465Sdelphij logstream = bio; 703296465Sdelphij else 704296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_BIO_WAS_FREED); 705296465Sdelphij } 706296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 707296465Sdelphij break; 708296465Sdelphij case ENGINE_CTRL_SET_PASSWORD_CALLBACK: 709296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 710296465Sdelphij password_context.password_callback = (pem_password_cb *)f; 711296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 712296465Sdelphij break; 713296465Sdelphij case ENGINE_CTRL_SET_USER_INTERFACE: 714296465Sdelphij case HWCRHK_CMD_SET_USER_INTERFACE: 715296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 716296465Sdelphij password_context.ui_method = (UI_METHOD *)p; 717296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 718296465Sdelphij break; 719296465Sdelphij case ENGINE_CTRL_SET_CALLBACK_DATA: 720296465Sdelphij case HWCRHK_CMD_SET_CALLBACK_DATA: 721296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 722296465Sdelphij password_context.callback_data = p; 723296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 724296465Sdelphij break; 725296465Sdelphij /* 726296465Sdelphij * this enables or disables the "SimpleForkCheck" flag used in the 727296465Sdelphij * initialisation structure. 728296465Sdelphij */ 729296465Sdelphij case ENGINE_CTRL_CHIL_SET_FORKCHECK: 730296465Sdelphij case HWCRHK_CMD_FORK_CHECK: 731296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 732296465Sdelphij if (i) 733296465Sdelphij hwcrhk_globals.flags |= HWCryptoHook_InitFlags_SimpleForkCheck; 734296465Sdelphij else 735296465Sdelphij hwcrhk_globals.flags &= ~HWCryptoHook_InitFlags_SimpleForkCheck; 736296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 737296465Sdelphij break; 738296465Sdelphij /* 739296465Sdelphij * This will prevent the initialisation function from "installing" 740296465Sdelphij * the mutex-handling callbacks, even if they are available from 741296465Sdelphij * within the library (or were provided to the library from the 742296465Sdelphij * calling application). This is to remove any baggage for 743296465Sdelphij * applications not using multithreading. 744296465Sdelphij */ 745296465Sdelphij case ENGINE_CTRL_CHIL_NO_LOCKING: 746296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 747296465Sdelphij disable_mutex_callbacks = 1; 748296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 749296465Sdelphij break; 750296465Sdelphij case HWCRHK_CMD_THREAD_LOCKING: 751296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 752296465Sdelphij disable_mutex_callbacks = ((i == 0) ? 0 : 1); 753296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 754296465Sdelphij break; 755160814Ssimon 756296465Sdelphij /* The command isn't understood by this engine */ 757296465Sdelphij default: 758296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, 759296465Sdelphij HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED); 760296465Sdelphij to_return = 0; 761296465Sdelphij break; 762296465Sdelphij } 763160814Ssimon 764296465Sdelphij return to_return; 765296465Sdelphij} 766160814Ssimon 767160814Ssimonstatic EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id, 768296465Sdelphij UI_METHOD *ui_method, 769296465Sdelphij void *callback_data) 770296465Sdelphij{ 771296465Sdelphij# ifndef OPENSSL_NO_RSA 772296465Sdelphij RSA *rtmp = NULL; 773296465Sdelphij# endif 774296465Sdelphij EVP_PKEY *res = NULL; 775296465Sdelphij# ifndef OPENSSL_NO_RSA 776296465Sdelphij HWCryptoHook_MPI e, n; 777296465Sdelphij HWCryptoHook_RSAKeyHandle *hptr; 778296465Sdelphij# endif 779296465Sdelphij# if !defined(OPENSSL_NO_RSA) 780296465Sdelphij char tempbuf[1024]; 781296465Sdelphij HWCryptoHook_ErrMsgBuf rmsg; 782296465Sdelphij HWCryptoHook_PassphraseContext ppctx; 783296465Sdelphij# endif 784160814Ssimon 785296465Sdelphij# if !defined(OPENSSL_NO_RSA) 786296465Sdelphij rmsg.buf = tempbuf; 787296465Sdelphij rmsg.size = sizeof(tempbuf); 788296465Sdelphij# endif 789160814Ssimon 790296465Sdelphij if (!hwcrhk_context) { 791296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NOT_INITIALISED); 792296465Sdelphij goto err; 793296465Sdelphij } 794296465Sdelphij# ifndef OPENSSL_NO_RSA 795296465Sdelphij hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle)); 796296465Sdelphij if (!hptr) { 797296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, ERR_R_MALLOC_FAILURE); 798296465Sdelphij goto err; 799296465Sdelphij } 800296465Sdelphij ppctx.ui_method = ui_method; 801296465Sdelphij ppctx.callback_data = callback_data; 802296465Sdelphij if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr, &rmsg, &ppctx)) { 803296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR); 804296465Sdelphij ERR_add_error_data(1, rmsg.buf); 805296465Sdelphij goto err; 806296465Sdelphij } 807296465Sdelphij if (!*hptr) { 808296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NO_KEY); 809296465Sdelphij goto err; 810296465Sdelphij } 811296465Sdelphij# endif 812296465Sdelphij# ifndef OPENSSL_NO_RSA 813296465Sdelphij rtmp = RSA_new_method(eng); 814296465Sdelphij RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr); 815296465Sdelphij rtmp->e = BN_new(); 816296465Sdelphij rtmp->n = BN_new(); 817296465Sdelphij rtmp->flags |= RSA_FLAG_EXT_PKEY; 818296465Sdelphij MPI2BN(rtmp->e, e); 819296465Sdelphij MPI2BN(rtmp->n, n); 820296465Sdelphij if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg) 821296465Sdelphij != HWCRYPTOHOOK_ERROR_MPISIZE) { 822296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR); 823296465Sdelphij ERR_add_error_data(1, rmsg.buf); 824296465Sdelphij goto err; 825296465Sdelphij } 826160814Ssimon 827296465Sdelphij bn_expand2(rtmp->e, e.size / sizeof(BN_ULONG)); 828296465Sdelphij bn_expand2(rtmp->n, n.size / sizeof(BN_ULONG)); 829296465Sdelphij MPI2BN(rtmp->e, e); 830296465Sdelphij MPI2BN(rtmp->n, n); 831160814Ssimon 832296465Sdelphij if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)) { 833296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR); 834296465Sdelphij ERR_add_error_data(1, rmsg.buf); 835296465Sdelphij goto err; 836296465Sdelphij } 837296465Sdelphij rtmp->e->top = e.size / sizeof(BN_ULONG); 838296465Sdelphij bn_fix_top(rtmp->e); 839296465Sdelphij rtmp->n->top = n.size / sizeof(BN_ULONG); 840296465Sdelphij bn_fix_top(rtmp->n); 841160814Ssimon 842296465Sdelphij res = EVP_PKEY_new(); 843296465Sdelphij EVP_PKEY_assign_RSA(res, rtmp); 844296465Sdelphij# endif 845160814Ssimon 846296465Sdelphij if (!res) 847296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, 848296465Sdelphij HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED); 849160814Ssimon 850296465Sdelphij return res; 851160814Ssimon err: 852296465Sdelphij if (res) 853296465Sdelphij EVP_PKEY_free(res); 854296465Sdelphij# ifndef OPENSSL_NO_RSA 855296465Sdelphij if (rtmp) 856296465Sdelphij RSA_free(rtmp); 857296465Sdelphij# endif 858296465Sdelphij return NULL; 859296465Sdelphij} 860160814Ssimon 861160814Ssimonstatic EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id, 862296465Sdelphij UI_METHOD *ui_method, void *callback_data) 863296465Sdelphij{ 864296465Sdelphij EVP_PKEY *res = NULL; 865160814Ssimon 866296465Sdelphij# ifndef OPENSSL_NO_RSA 867296465Sdelphij res = hwcrhk_load_privkey(eng, key_id, ui_method, callback_data); 868296465Sdelphij# endif 869160814Ssimon 870296465Sdelphij if (res) 871296465Sdelphij switch (res->type) { 872296465Sdelphij# ifndef OPENSSL_NO_RSA 873296465Sdelphij case EVP_PKEY_RSA: 874296465Sdelphij { 875296465Sdelphij RSA *rsa = NULL; 876160814Ssimon 877296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); 878296465Sdelphij rsa = res->pkey.rsa; 879296465Sdelphij res->pkey.rsa = RSA_new(); 880296465Sdelphij res->pkey.rsa->n = rsa->n; 881296465Sdelphij res->pkey.rsa->e = rsa->e; 882296465Sdelphij rsa->n = NULL; 883296465Sdelphij rsa->e = NULL; 884296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); 885296465Sdelphij RSA_free(rsa); 886296465Sdelphij } 887296465Sdelphij break; 888296465Sdelphij# endif 889296465Sdelphij default: 890296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY, 891296465Sdelphij HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED); 892296465Sdelphij goto err; 893296465Sdelphij } 894160814Ssimon 895296465Sdelphij return res; 896160814Ssimon err: 897296465Sdelphij if (res) 898296465Sdelphij EVP_PKEY_free(res); 899296465Sdelphij return NULL; 900296465Sdelphij} 901160814Ssimon 902160814Ssimon/* A little mod_exp */ 903160814Ssimonstatic int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 904296465Sdelphij const BIGNUM *m, BN_CTX *ctx) 905296465Sdelphij{ 906296465Sdelphij char tempbuf[1024]; 907296465Sdelphij HWCryptoHook_ErrMsgBuf rmsg; 908296465Sdelphij /* 909296465Sdelphij * Since HWCryptoHook_MPI is pretty compatible with BIGNUM's, we use them 910296465Sdelphij * directly, plus a little macro magic. We only thing we need to make 911296465Sdelphij * sure of is that enough space is allocated. 912296465Sdelphij */ 913296465Sdelphij HWCryptoHook_MPI m_a, m_p, m_n, m_r; 914296465Sdelphij int to_return, ret; 915160814Ssimon 916296465Sdelphij to_return = 0; /* expect failure */ 917296465Sdelphij rmsg.buf = tempbuf; 918296465Sdelphij rmsg.size = sizeof(tempbuf); 919160814Ssimon 920296465Sdelphij if (!hwcrhk_context) { 921296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_NOT_INITIALISED); 922296465Sdelphij goto err; 923296465Sdelphij } 924296465Sdelphij /* Prepare the params */ 925296465Sdelphij bn_expand2(r, m->top); /* Check for error !! */ 926296465Sdelphij BN2MPI(m_a, a); 927296465Sdelphij BN2MPI(m_p, p); 928296465Sdelphij BN2MPI(m_n, m); 929296465Sdelphij MPI2BN(r, m_r); 930160814Ssimon 931296465Sdelphij /* Perform the operation */ 932296465Sdelphij ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg); 933160814Ssimon 934296465Sdelphij /* Convert the response */ 935296465Sdelphij r->top = m_r.size / sizeof(BN_ULONG); 936296465Sdelphij bn_fix_top(r); 937160814Ssimon 938296465Sdelphij if (ret < 0) { 939296465Sdelphij /* 940296465Sdelphij * FIXME: When this error is returned, HWCryptoHook is telling us 941296465Sdelphij * that falling back to software computation might be a good thing. 942296465Sdelphij */ 943296465Sdelphij if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 944296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FALLBACK); 945296465Sdelphij } else { 946296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FAILED); 947296465Sdelphij } 948296465Sdelphij ERR_add_error_data(1, rmsg.buf); 949296465Sdelphij goto err; 950296465Sdelphij } 951160814Ssimon 952296465Sdelphij to_return = 1; 953296465Sdelphij err: 954296465Sdelphij return to_return; 955296465Sdelphij} 956160814Ssimon 957296465Sdelphij# ifndef OPENSSL_NO_RSA 958296465Sdelphijstatic int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, 959296465Sdelphij BN_CTX *ctx) 960296465Sdelphij{ 961296465Sdelphij char tempbuf[1024]; 962296465Sdelphij HWCryptoHook_ErrMsgBuf rmsg; 963296465Sdelphij HWCryptoHook_RSAKeyHandle *hptr; 964296465Sdelphij int to_return = 0, ret; 965160814Ssimon 966296465Sdelphij rmsg.buf = tempbuf; 967296465Sdelphij rmsg.size = sizeof(tempbuf); 968160814Ssimon 969296465Sdelphij if (!hwcrhk_context) { 970296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, HWCRHK_R_NOT_INITIALISED); 971296465Sdelphij goto err; 972296465Sdelphij } 973160814Ssimon 974296465Sdelphij /* 975296465Sdelphij * This provides support for nForce keys. Since that's opaque data all 976296465Sdelphij * we do is provide a handle to the proper key and let HWCryptoHook take 977296465Sdelphij * care of the rest. 978296465Sdelphij */ 979296465Sdelphij if ((hptr = 980296465Sdelphij (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa)) 981296465Sdelphij != NULL) { 982296465Sdelphij HWCryptoHook_MPI m_a, m_r; 983160814Ssimon 984296465Sdelphij if (!rsa->n) { 985296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 986296465Sdelphij HWCRHK_R_MISSING_KEY_COMPONENTS); 987296465Sdelphij goto err; 988296465Sdelphij } 989160814Ssimon 990296465Sdelphij /* Prepare the params */ 991296465Sdelphij bn_expand2(r, rsa->n->top); /* Check for error !! */ 992296465Sdelphij BN2MPI(m_a, I); 993296465Sdelphij MPI2BN(r, m_r); 994160814Ssimon 995296465Sdelphij /* Perform the operation */ 996296465Sdelphij ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg); 997160814Ssimon 998296465Sdelphij /* Convert the response */ 999296465Sdelphij r->top = m_r.size / sizeof(BN_ULONG); 1000296465Sdelphij bn_fix_top(r); 1001160814Ssimon 1002296465Sdelphij if (ret < 0) { 1003296465Sdelphij /* 1004296465Sdelphij * FIXME: When this error is returned, HWCryptoHook is telling us 1005296465Sdelphij * that falling back to software computation might be a good 1006296465Sdelphij * thing. 1007296465Sdelphij */ 1008296465Sdelphij if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 1009296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1010296465Sdelphij HWCRHK_R_REQUEST_FALLBACK); 1011296465Sdelphij } else { 1012296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1013296465Sdelphij HWCRHK_R_REQUEST_FAILED); 1014296465Sdelphij } 1015296465Sdelphij ERR_add_error_data(1, rmsg.buf); 1016296465Sdelphij goto err; 1017296465Sdelphij } 1018296465Sdelphij } else { 1019296465Sdelphij HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r; 1020160814Ssimon 1021296465Sdelphij if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) { 1022296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1023296465Sdelphij HWCRHK_R_MISSING_KEY_COMPONENTS); 1024296465Sdelphij goto err; 1025296465Sdelphij } 1026160814Ssimon 1027296465Sdelphij /* Prepare the params */ 1028296465Sdelphij bn_expand2(r, rsa->n->top); /* Check for error !! */ 1029296465Sdelphij BN2MPI(m_a, I); 1030296465Sdelphij BN2MPI(m_p, rsa->p); 1031296465Sdelphij BN2MPI(m_q, rsa->q); 1032296465Sdelphij BN2MPI(m_dmp1, rsa->dmp1); 1033296465Sdelphij BN2MPI(m_dmq1, rsa->dmq1); 1034296465Sdelphij BN2MPI(m_iqmp, rsa->iqmp); 1035296465Sdelphij MPI2BN(r, m_r); 1036160814Ssimon 1037296465Sdelphij /* Perform the operation */ 1038296465Sdelphij ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q, 1039296465Sdelphij m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg); 1040160814Ssimon 1041296465Sdelphij /* Convert the response */ 1042296465Sdelphij r->top = m_r.size / sizeof(BN_ULONG); 1043296465Sdelphij bn_fix_top(r); 1044160814Ssimon 1045296465Sdelphij if (ret < 0) { 1046296465Sdelphij /* 1047296465Sdelphij * FIXME: When this error is returned, HWCryptoHook is telling us 1048296465Sdelphij * that falling back to software computation might be a good 1049296465Sdelphij * thing. 1050296465Sdelphij */ 1051296465Sdelphij if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 1052296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1053296465Sdelphij HWCRHK_R_REQUEST_FALLBACK); 1054296465Sdelphij } else { 1055296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, 1056296465Sdelphij HWCRHK_R_REQUEST_FAILED); 1057296465Sdelphij } 1058296465Sdelphij ERR_add_error_data(1, rmsg.buf); 1059296465Sdelphij goto err; 1060296465Sdelphij } 1061296465Sdelphij } 1062296465Sdelphij /* 1063296465Sdelphij * If we're here, we must be here with some semblance of success :-) 1064296465Sdelphij */ 1065296465Sdelphij to_return = 1; 1066296465Sdelphij err: 1067296465Sdelphij return to_return; 1068296465Sdelphij} 1069296465Sdelphij# endif 1070296465Sdelphij 1071296465Sdelphij# ifndef OPENSSL_NO_RSA 1072160814Ssimon/* This function is aliased to mod_exp (with the mont stuff dropped). */ 1073160814Ssimonstatic int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, 1074296465Sdelphij const BIGNUM *m, BN_CTX *ctx, 1075296465Sdelphij BN_MONT_CTX *m_ctx) 1076296465Sdelphij{ 1077296465Sdelphij return hwcrhk_mod_exp(r, a, p, m, ctx); 1078296465Sdelphij} 1079215697Ssimon 1080215697Ssimonstatic int hwcrhk_rsa_finish(RSA *rsa) 1081296465Sdelphij{ 1082296465Sdelphij HWCryptoHook_RSAKeyHandle *hptr; 1083215697Ssimon 1084296465Sdelphij hptr = RSA_get_ex_data(rsa, hndidx_rsa); 1085296465Sdelphij if (hptr) { 1086296465Sdelphij p_hwcrhk_RSAUnloadKey(*hptr, NULL); 1087296465Sdelphij OPENSSL_free(hptr); 1088296465Sdelphij RSA_set_ex_data(rsa, hndidx_rsa, NULL); 1089296465Sdelphij } 1090296465Sdelphij return 1; 1091296465Sdelphij} 1092215697Ssimon 1093296465Sdelphij# endif 1094160814Ssimon 1095296465Sdelphij# ifndef OPENSSL_NO_DH 1096160814Ssimon/* This function is aliased to mod_exp (with the dh and mont dropped). */ 1097160814Ssimonstatic int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r, 1098296465Sdelphij const BIGNUM *a, const BIGNUM *p, 1099296465Sdelphij const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) 1100296465Sdelphij{ 1101296465Sdelphij return hwcrhk_mod_exp(r, a, p, m, ctx); 1102296465Sdelphij} 1103296465Sdelphij# endif 1104160814Ssimon 1105160814Ssimon/* Random bytes are good */ 1106160814Ssimonstatic int hwcrhk_rand_bytes(unsigned char *buf, int num) 1107296465Sdelphij{ 1108296465Sdelphij char tempbuf[1024]; 1109296465Sdelphij HWCryptoHook_ErrMsgBuf rmsg; 1110296465Sdelphij int to_return = 0; /* assume failure */ 1111296465Sdelphij int ret; 1112160814Ssimon 1113296465Sdelphij rmsg.buf = tempbuf; 1114296465Sdelphij rmsg.size = sizeof(tempbuf); 1115160814Ssimon 1116296465Sdelphij if (!hwcrhk_context) { 1117296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_NOT_INITIALISED); 1118296465Sdelphij goto err; 1119296465Sdelphij } 1120160814Ssimon 1121296465Sdelphij ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg); 1122296465Sdelphij if (ret < 0) { 1123296465Sdelphij /* 1124296465Sdelphij * FIXME: When this error is returned, HWCryptoHook is telling us 1125296465Sdelphij * that falling back to software computation might be a good thing. 1126296465Sdelphij */ 1127296465Sdelphij if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) { 1128296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FALLBACK); 1129296465Sdelphij } else { 1130296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FAILED); 1131296465Sdelphij } 1132296465Sdelphij ERR_add_error_data(1, rmsg.buf); 1133296465Sdelphij goto err; 1134296465Sdelphij } 1135296465Sdelphij to_return = 1; 1136160814Ssimon err: 1137296465Sdelphij return to_return; 1138296465Sdelphij} 1139160814Ssimon 1140160814Ssimonstatic int hwcrhk_rand_status(void) 1141296465Sdelphij{ 1142296465Sdelphij return 1; 1143296465Sdelphij} 1144160814Ssimon 1145296465Sdelphij/* 1146296465Sdelphij * Mutex calls: since the HWCryptoHook model closely follows the POSIX model 1147160814Ssimon * these just wrap the POSIX functions and add some logging. 1148160814Ssimon */ 1149160814Ssimon 1150296465Sdelphijstatic int hwcrhk_mutex_init(HWCryptoHook_Mutex * mt, 1151296465Sdelphij HWCryptoHook_CallerContext * cactx) 1152296465Sdelphij{ 1153296465Sdelphij mt->lockid = CRYPTO_get_new_dynlockid(); 1154296465Sdelphij if (mt->lockid == 0) 1155296465Sdelphij return 1; /* failure */ 1156296465Sdelphij return 0; /* success */ 1157296465Sdelphij} 1158160814Ssimon 1159296465Sdelphijstatic int hwcrhk_mutex_lock(HWCryptoHook_Mutex * mt) 1160296465Sdelphij{ 1161296465Sdelphij CRYPTO_w_lock(mt->lockid); 1162296465Sdelphij return 0; 1163296465Sdelphij} 1164160814Ssimon 1165160814Ssimonstatic void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt) 1166296465Sdelphij{ 1167296465Sdelphij CRYPTO_w_unlock(mt->lockid); 1168296465Sdelphij} 1169160814Ssimon 1170296465Sdelphijstatic void hwcrhk_mutex_destroy(HWCryptoHook_Mutex * mt) 1171296465Sdelphij{ 1172296465Sdelphij CRYPTO_destroy_dynlockid(mt->lockid); 1173296465Sdelphij} 1174160814Ssimon 1175160814Ssimonstatic int hwcrhk_get_pass(const char *prompt_info, 1176296465Sdelphij int *len_io, char *buf, 1177296465Sdelphij HWCryptoHook_PassphraseContext * ppctx, 1178296465Sdelphij HWCryptoHook_CallerContext * cactx) 1179296465Sdelphij{ 1180296465Sdelphij pem_password_cb *callback = NULL; 1181296465Sdelphij void *callback_data = NULL; 1182296465Sdelphij UI_METHOD *ui_method = NULL; 1183296465Sdelphij /* 1184296465Sdelphij * Despite what the documentation says prompt_info can be an empty 1185296465Sdelphij * string. 1186296465Sdelphij */ 1187296465Sdelphij if (prompt_info && !*prompt_info) 1188296465Sdelphij prompt_info = NULL; 1189160814Ssimon 1190296465Sdelphij if (cactx) { 1191296465Sdelphij if (cactx->ui_method) 1192296465Sdelphij ui_method = cactx->ui_method; 1193296465Sdelphij if (cactx->password_callback) 1194296465Sdelphij callback = cactx->password_callback; 1195296465Sdelphij if (cactx->callback_data) 1196296465Sdelphij callback_data = cactx->callback_data; 1197296465Sdelphij } 1198296465Sdelphij if (ppctx) { 1199296465Sdelphij if (ppctx->ui_method) { 1200296465Sdelphij ui_method = ppctx->ui_method; 1201296465Sdelphij callback = NULL; 1202296465Sdelphij } 1203296465Sdelphij if (ppctx->callback_data) 1204296465Sdelphij callback_data = ppctx->callback_data; 1205296465Sdelphij } 1206296465Sdelphij if (callback == NULL && ui_method == NULL) { 1207296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS, HWCRHK_R_NO_CALLBACK); 1208296465Sdelphij return -1; 1209296465Sdelphij } 1210160814Ssimon 1211296465Sdelphij if (ui_method) { 1212296465Sdelphij UI *ui = UI_new_method(ui_method); 1213296465Sdelphij if (ui) { 1214296465Sdelphij int ok; 1215296465Sdelphij char *prompt = UI_construct_prompt(ui, 1216296465Sdelphij "pass phrase", prompt_info); 1217160814Ssimon 1218296465Sdelphij ok = UI_add_input_string(ui, prompt, 1219296465Sdelphij UI_INPUT_FLAG_DEFAULT_PWD, 1220296465Sdelphij buf, 0, (*len_io) - 1); 1221296465Sdelphij UI_add_user_data(ui, callback_data); 1222296465Sdelphij UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0); 1223160814Ssimon 1224296465Sdelphij if (ok >= 0) 1225296465Sdelphij do { 1226296465Sdelphij ok = UI_process(ui); 1227296465Sdelphij } 1228296465Sdelphij while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0)); 1229160814Ssimon 1230296465Sdelphij if (ok >= 0) 1231296465Sdelphij *len_io = strlen(buf); 1232160814Ssimon 1233296465Sdelphij UI_free(ui); 1234296465Sdelphij OPENSSL_free(prompt); 1235296465Sdelphij } 1236296465Sdelphij } else { 1237296465Sdelphij *len_io = callback(buf, *len_io, 0, callback_data); 1238296465Sdelphij } 1239296465Sdelphij if (!*len_io) 1240296465Sdelphij return -1; 1241296465Sdelphij return 0; 1242296465Sdelphij} 1243160814Ssimon 1244160814Ssimonstatic int hwcrhk_insert_card(const char *prompt_info, 1245296465Sdelphij const char *wrong_info, 1246296465Sdelphij HWCryptoHook_PassphraseContext * ppctx, 1247296465Sdelphij HWCryptoHook_CallerContext * cactx) 1248296465Sdelphij{ 1249296465Sdelphij int ok = -1; 1250296465Sdelphij UI *ui; 1251296465Sdelphij void *callback_data = NULL; 1252296465Sdelphij UI_METHOD *ui_method = NULL; 1253160814Ssimon 1254296465Sdelphij if (cactx) { 1255296465Sdelphij if (cactx->ui_method) 1256296465Sdelphij ui_method = cactx->ui_method; 1257296465Sdelphij if (cactx->callback_data) 1258296465Sdelphij callback_data = cactx->callback_data; 1259296465Sdelphij } 1260296465Sdelphij if (ppctx) { 1261296465Sdelphij if (ppctx->ui_method) 1262296465Sdelphij ui_method = ppctx->ui_method; 1263296465Sdelphij if (ppctx->callback_data) 1264296465Sdelphij callback_data = ppctx->callback_data; 1265296465Sdelphij } 1266296465Sdelphij if (ui_method == NULL) { 1267296465Sdelphij HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD, HWCRHK_R_NO_CALLBACK); 1268296465Sdelphij return -1; 1269296465Sdelphij } 1270160814Ssimon 1271296465Sdelphij ui = UI_new_method(ui_method); 1272160814Ssimon 1273296465Sdelphij if (ui) { 1274296465Sdelphij char answer; 1275296465Sdelphij char buf[BUFSIZ]; 1276296465Sdelphij /* 1277296465Sdelphij * Despite what the documentation says wrong_info can be an empty 1278296465Sdelphij * string. 1279296465Sdelphij */ 1280296465Sdelphij if (wrong_info && *wrong_info) 1281296465Sdelphij BIO_snprintf(buf, sizeof(buf) - 1, 1282296465Sdelphij "Current card: \"%s\"\n", wrong_info); 1283296465Sdelphij else 1284296465Sdelphij buf[0] = 0; 1285296465Sdelphij ok = UI_dup_info_string(ui, buf); 1286296465Sdelphij if (ok >= 0 && prompt_info) { 1287296465Sdelphij BIO_snprintf(buf, sizeof(buf) - 1, 1288296465Sdelphij "Insert card \"%s\"", prompt_info); 1289296465Sdelphij ok = UI_dup_input_boolean(ui, buf, 1290296465Sdelphij "\n then hit <enter> or C<enter> to cancel\n", 1291296465Sdelphij "\r\n", "Cc", UI_INPUT_FLAG_ECHO, 1292296465Sdelphij &answer); 1293296465Sdelphij } 1294296465Sdelphij UI_add_user_data(ui, callback_data); 1295160814Ssimon 1296296465Sdelphij if (ok >= 0) 1297296465Sdelphij ok = UI_process(ui); 1298296465Sdelphij UI_free(ui); 1299160814Ssimon 1300296465Sdelphij if (ok == -2 || (ok >= 0 && answer == 'C')) 1301296465Sdelphij ok = 1; 1302296465Sdelphij else if (ok < 0) 1303296465Sdelphij ok = -1; 1304296465Sdelphij else 1305296465Sdelphij ok = 0; 1306296465Sdelphij } 1307296465Sdelphij return ok; 1308296465Sdelphij} 1309160814Ssimon 1310160814Ssimonstatic void hwcrhk_log_message(void *logstr, const char *message) 1311296465Sdelphij{ 1312296465Sdelphij BIO *lstream = NULL; 1313160814Ssimon 1314296465Sdelphij CRYPTO_w_lock(CRYPTO_LOCK_BIO); 1315296465Sdelphij if (logstr) 1316296465Sdelphij lstream = *(BIO **)logstr; 1317296465Sdelphij if (lstream) { 1318296465Sdelphij BIO_printf(lstream, "%s\n", message); 1319296465Sdelphij } 1320296465Sdelphij CRYPTO_w_unlock(CRYPTO_LOCK_BIO); 1321296465Sdelphij} 1322160814Ssimon 1323296465Sdelphij/* 1324296465Sdelphij * This stuff is needed if this ENGINE is being compiled into a 1325296465Sdelphij * self-contained shared-library. 1326296465Sdelphij */ 1327296465Sdelphij# ifndef OPENSSL_NO_DYNAMIC_ENGINE 1328160814Ssimonstatic int bind_fn(ENGINE *e, const char *id) 1329296465Sdelphij{ 1330296465Sdelphij if (id && (strcmp(id, engine_hwcrhk_id) != 0) && 1331296465Sdelphij (strcmp(id, engine_hwcrhk_id_alt) != 0)) 1332296465Sdelphij return 0; 1333296465Sdelphij if (!bind_helper(e)) 1334296465Sdelphij return 0; 1335296465Sdelphij return 1; 1336296465Sdelphij} 1337296465Sdelphij 1338160814SsimonIMPLEMENT_DYNAMIC_CHECK_FN() 1339296465Sdelphij IMPLEMENT_DYNAMIC_BIND_FN(bind_fn) 1340296465Sdelphij# endif /* OPENSSL_NO_DYNAMIC_ENGINE */ 1341296465Sdelphij# endif /* !OPENSSL_NO_HW_CHIL */ 1342296465Sdelphij#endif /* !OPENSSL_NO_HW */ 1343