1 /* crypto/engine/hw_ncipher.c -*- mode: C; c-file-style: "eay" -*- */
2 /* Written by Richard Levitte (richard@levitte.org), Geoff Thorpe
3 * (geoff@geoffthorpe.net) and Dr Stephen N Henson (shenson@bigfoot.com)
4 * for the OpenSSL project 2000.
6 /* ====================================================================
7 * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
21 * 3. All advertising materials mentioning features or use of this
22 * software must display the following acknowledgment:
23 * "This product includes software developed by the OpenSSL Project
24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For written permission, please contact
29 * licensing@OpenSSL.org.
31 * 5. Products derived from this software may not be called "OpenSSL"
32 * nor may "OpenSSL" appear in their names without prior written
33 * permission of the OpenSSL Project.
35 * 6. Redistributions of any form whatsoever must retain the following
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com). This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com).
62 #include <openssl/crypto.h>
63 #include <openssl/pem.h>
64 #include <openssl/dso.h>
65 #include <openssl/engine.h>
66 #include <openssl/ui.h>
69 #ifndef OPENSSL_NO_HW_NCIPHER
71 /* Attribution notice: nCipher have said several times that it's OK for
72 * us to implement a general interface to their boxes, and recently declared
73 * their HWCryptoHook to be public, and therefore available for us to use.
76 * The hwcryptohook.h included here is from May 2000.
80 #include "hwcryptohook.h"
82 #include "vendor_defns/hwcryptohook.h"
85 #define HWCRHK_LIB_NAME "hwcrhk engine"
86 #include "e_ncipher_err.c"
88 static int hwcrhk_destroy(ENGINE *e);
89 static int hwcrhk_init(ENGINE *e);
90 static int hwcrhk_finish(ENGINE *e);
91 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
93 /* Functions to handle mutexes */
94 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
95 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
96 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
97 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
100 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
101 const BIGNUM *m, BN_CTX *ctx);
103 #ifndef OPENSSL_NO_RSA
105 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa);
107 /* This function is aliased to mod_exp (with the mont stuff dropped). */
108 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
109 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
111 #ifndef OPENSSL_NO_DH
113 /* This function is alised to mod_exp (with the DH and mont dropped). */
114 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
115 const BIGNUM *a, const BIGNUM *p,
116 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
120 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
121 static int hwcrhk_rand_status(void);
124 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
125 UI_METHOD *ui_method, void *callback_data);
126 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
127 UI_METHOD *ui_method, void *callback_data);
128 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
129 int ind,long argl, void *argp);
131 /* Interaction stuff */
132 static int hwcrhk_insert_card(const char *prompt_info,
133 const char *wrong_info,
134 HWCryptoHook_PassphraseContext *ppctx,
135 HWCryptoHook_CallerContext *cactx);
136 static int hwcrhk_get_pass(const char *prompt_info,
137 int *len_io, char *buf,
138 HWCryptoHook_PassphraseContext *ppctx,
139 HWCryptoHook_CallerContext *cactx);
140 static void hwcrhk_log_message(void *logstr, const char *message);
142 /* The definitions for control commands specific to this engine */
143 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
144 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
145 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
146 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
147 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
148 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
151 "Specifies the path to the 'hwcrhk' shared library",
152 ENGINE_CMD_FLAG_STRING},
153 {HWCRHK_CMD_FORK_CHECK,
155 "Turns fork() checking on or off (boolean)",
156 ENGINE_CMD_FLAG_NUMERIC},
157 {HWCRHK_CMD_THREAD_LOCKING,
159 "Turns thread-safe locking on or off (boolean)",
160 ENGINE_CMD_FLAG_NUMERIC},
161 {HWCRHK_CMD_SET_USER_INTERFACE,
162 "SET_USER_INTERFACE",
163 "Set the global user interface (internal)",
164 ENGINE_CMD_FLAG_INTERNAL},
165 {HWCRHK_CMD_SET_CALLBACK_DATA,
167 "Set the global user interface extra data (internal)",
168 ENGINE_CMD_FLAG_INTERNAL},
172 #ifndef OPENSSL_NO_RSA
173 /* Our internal RSA_METHOD that we provide pointers to */
174 static RSA_METHOD hwcrhk_rsa =
176 "nCipher RSA method",
193 #ifndef OPENSSL_NO_DH
194 /* Our internal DH_METHOD that we provide pointers to */
195 static DH_METHOD hwcrhk_dh =
208 static RAND_METHOD hwcrhk_rand =
210 /* "nCipher RAND method", */
219 /* Constants used when creating the ENGINE */
220 static const char *engine_hwcrhk_id = "chil";
221 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
223 /* Internal stuff for HWCryptoHook */
225 /* Some structures needed for proper use of thread locks */
226 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
227 into HWCryptoHook_Mutex */
228 struct HWCryptoHook_MutexValue
233 /* hwcryptohook.h has some typedefs that turn
234 struct HWCryptoHook_PassphraseContextValue
235 into HWCryptoHook_PassphraseContext */
236 struct HWCryptoHook_PassphraseContextValue
238 UI_METHOD *ui_method;
242 /* hwcryptohook.h has some typedefs that turn
243 struct HWCryptoHook_CallerContextValue
244 into HWCryptoHook_CallerContext */
245 struct HWCryptoHook_CallerContextValue
247 pem_password_cb *password_callback; /* Deprecated! Only present for
248 backward compatibility! */
249 UI_METHOD *ui_method;
253 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
254 BIGNUM's, so lets define a couple of conversion macros */
255 #define BN2MPI(mp, bn) \
256 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
257 #define MPI2BN(bn, mp) \
258 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
260 static BIO *logstream = NULL;
261 static int disable_mutex_callbacks = 0;
263 /* One might wonder why these are needed, since one can pass down at least
264 a UI_METHOD and a pointer to callback data to the key-loading functions.
265 The thing is that the ModExp and RSAImmed functions can load keys as well,
266 if the data they get is in a special, nCipher-defined format (hint: if you
267 look at the private exponent of the RSA data as a string, you'll see this
268 string: "nCipher KM tool key id", followed by some bytes, followed a key
269 identity string, followed by more bytes. This happens when you use "embed"
270 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
271 any passphrase or caller context, and our functions can't really take any
272 callback data either. Still, the "insert_card" and "get_passphrase"
273 callbacks may be called down the line, and will need to know what user
274 interface callbacks to call, and having callback data from the application
275 may be a nice thing as well, so we need to keep track of that globally. */
276 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
278 /* Stuff to pass to the HWCryptoHook library */
279 static HWCryptoHook_InitInfo hwcrhk_globals = {
280 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
281 &logstream, /* logstream */
282 sizeof(BN_ULONG), /* limbsize */
283 0, /* mslimb first: false for BNs */
284 -1, /* msbyte first: use native */
285 0, /* Max mutexes, 0 = no small limit */
286 0, /* Max simultaneous, 0 = default */
288 /* The next few are mutex stuff: we write wrapper functions
289 around the OS mutex functions. We initialise them to 0
290 here, and change that to actual function pointers in hwcrhk_init()
291 if dynamic locks are supported (that is, if the application
292 programmer has made sure of setting up callbacks bafore starting
293 this engine) *and* if disable_mutex_callbacks hasn't been set by
294 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
295 sizeof(HWCryptoHook_Mutex),
301 /* The next few are condvar stuff: we write wrapper functions
302 round the OS functions. Currently not implemented and not
303 and absolute necessity even in threaded programs, therefore
304 0'ed. Will hopefully be implemented some day, since it
305 enhances the efficiency of HWCryptoHook. */
306 0, /* sizeof(HWCryptoHook_CondVar), */
307 0, /* hwcrhk_cv_init, */
308 0, /* hwcrhk_cv_wait, */
309 0, /* hwcrhk_cv_signal, */
310 0, /* hwcrhk_cv_broadcast, */
311 0, /* hwcrhk_cv_destroy, */
313 hwcrhk_get_pass, /* pass phrase */
314 hwcrhk_insert_card, /* insert a card */
315 hwcrhk_log_message /* Log message */
319 /* Now, to our own code */
321 /* This internal function is used by ENGINE_ncipher() and possibly by the
322 * "dynamic" ENGINE support too */
323 static int bind_helper(ENGINE *e)
325 #ifndef OPENSSL_NO_RSA
326 const RSA_METHOD *meth1;
328 #ifndef OPENSSL_NO_DH
329 const DH_METHOD *meth2;
331 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
332 !ENGINE_set_name(e, engine_hwcrhk_name) ||
333 #ifndef OPENSSL_NO_RSA
334 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
336 #ifndef OPENSSL_NO_DH
337 !ENGINE_set_DH(e, &hwcrhk_dh) ||
339 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
340 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
341 !ENGINE_set_init_function(e, hwcrhk_init) ||
342 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
343 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
344 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
345 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
346 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
349 #ifndef OPENSSL_NO_RSA
350 /* We know that the "PKCS1_SSLeay()" functions hook properly
351 * to the cswift-specific mod_exp and mod_exp_crt so we use
352 * those functions. NB: We don't use ENGINE_openssl() or
353 * anything "more generic" because something like the RSAref
354 * code may not hook properly, and if you own one of these
355 * cards then you have the right to do RSA operations on it
357 meth1 = RSA_PKCS1_SSLeay();
358 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
359 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
360 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
361 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
364 #ifndef OPENSSL_NO_DH
365 /* Much the same for Diffie-Hellman */
366 meth2 = DH_OpenSSL();
367 hwcrhk_dh.generate_key = meth2->generate_key;
368 hwcrhk_dh.compute_key = meth2->compute_key;
371 /* Ensure the hwcrhk error handling is set up */
372 ERR_load_HWCRHK_strings();
376 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
377 static ENGINE *engine_ncipher(void)
379 ENGINE *ret = ENGINE_new();
382 if(!bind_helper(ret))
390 void ENGINE_load_chil(void)
392 /* Copied from eng_[openssl|dyn].c */
393 ENGINE *toadd = engine_ncipher();
401 /* This is a process-global DSO handle used for loading and unloading
402 * the HWCryptoHook library. NB: This is only set (or unset) during an
403 * init() or finish() call (reference counts permitting) and they're
404 * operating with global locks, so this should be thread-safe
406 static DSO *hwcrhk_dso = NULL;
407 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
408 #ifndef OPENSSL_NO_RSA
409 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
412 /* These are the function pointers that are (un)set when the library has
413 * successfully (un)loaded. */
414 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
415 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
416 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
417 #ifndef OPENSSL_NO_RSA
418 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
420 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
421 #ifndef OPENSSL_NO_RSA
422 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
423 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
424 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
426 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
428 /* Used in the DSO operations. */
429 static const char *HWCRHK_LIBNAME = NULL;
430 static void free_HWCRHK_LIBNAME(void)
433 OPENSSL_free((void*)HWCRHK_LIBNAME);
434 HWCRHK_LIBNAME = NULL;
436 static const char *get_HWCRHK_LIBNAME(void)
439 return HWCRHK_LIBNAME;
442 static long set_HWCRHK_LIBNAME(const char *name)
444 free_HWCRHK_LIBNAME();
445 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
447 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
448 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
449 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
450 #ifndef OPENSSL_NO_RSA
451 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
453 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
454 #ifndef OPENSSL_NO_RSA
455 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
456 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
457 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
459 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
461 /* HWCryptoHook library functions and mechanics - these are used by the
462 * higher-level functions further down. NB: As and where there's no
463 * error checking, take a look lower down where these functions are
464 * called, the checking and error handling is probably down there. */
466 /* utility function to obtain a context */
467 static int get_context(HWCryptoHook_ContextHandle *hac,
468 HWCryptoHook_CallerContext *cac)
471 HWCryptoHook_ErrMsgBuf rmsg;
474 rmsg.size = sizeof(tempbuf);
476 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
483 /* similarly to release one. */
484 static void release_context(HWCryptoHook_ContextHandle hac)
486 p_hwcrhk_Finish(hac);
489 /* Destructor (complements the "ENGINE_ncipher()" constructor) */
490 static int hwcrhk_destroy(ENGINE *e)
492 free_HWCRHK_LIBNAME();
493 ERR_unload_HWCRHK_strings();
497 /* (de)initialisation functions. */
498 static int hwcrhk_init(ENGINE *e)
500 HWCryptoHook_Init_t *p1;
501 HWCryptoHook_Finish_t *p2;
502 HWCryptoHook_ModExp_t *p3;
503 #ifndef OPENSSL_NO_RSA
504 HWCryptoHook_RSA_t *p4;
505 HWCryptoHook_RSALoadKey_t *p5;
506 HWCryptoHook_RSAGetPublicKey_t *p6;
507 HWCryptoHook_RSAUnloadKey_t *p7;
509 HWCryptoHook_RandomBytes_t *p8;
510 HWCryptoHook_ModExpCRT_t *p9;
512 if(hwcrhk_dso != NULL)
514 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
517 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
518 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
519 if(hwcrhk_dso == NULL)
521 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
524 if(!(p1 = (HWCryptoHook_Init_t *)
525 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
526 !(p2 = (HWCryptoHook_Finish_t *)
527 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
528 !(p3 = (HWCryptoHook_ModExp_t *)
529 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
530 #ifndef OPENSSL_NO_RSA
531 !(p4 = (HWCryptoHook_RSA_t *)
532 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
533 !(p5 = (HWCryptoHook_RSALoadKey_t *)
534 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
535 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
536 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
537 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
538 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
540 !(p8 = (HWCryptoHook_RandomBytes_t *)
541 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
542 !(p9 = (HWCryptoHook_ModExpCRT_t *)
543 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
545 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
548 /* Copy the pointers */
550 p_hwcrhk_Finish = p2;
551 p_hwcrhk_ModExp = p3;
552 #ifndef OPENSSL_NO_RSA
554 p_hwcrhk_RSALoadKey = p5;
555 p_hwcrhk_RSAGetPublicKey = p6;
556 p_hwcrhk_RSAUnloadKey = p7;
558 p_hwcrhk_RandomBytes = p8;
559 p_hwcrhk_ModExpCRT = p9;
561 /* Check if the application decided to support dynamic locks,
562 and if it does, use them. */
563 if (disable_mutex_callbacks == 0)
565 if (CRYPTO_get_dynlock_create_callback() != NULL &&
566 CRYPTO_get_dynlock_lock_callback() != NULL &&
567 CRYPTO_get_dynlock_destroy_callback() != NULL)
569 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
570 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
571 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
572 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
574 else if (CRYPTO_get_locking_callback() != NULL)
576 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_LOCKING_MISSING);
577 ERR_add_error_data(1,"You HAVE to add dynamic locking callbacks via CRYPTO_set_dynlock_{create,lock,destroy}_callback()");
582 /* Try and get a context - if not, we may have a DSO but no
584 if(!get_context(&hwcrhk_context, &password_context))
586 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
589 /* Everything's fine. */
590 #ifndef OPENSSL_NO_RSA
591 if (hndidx_rsa == -1)
592 hndidx_rsa = RSA_get_ex_new_index(0,
593 "nFast HWCryptoHook RSA key handle",
594 NULL, NULL, hwcrhk_ex_free);
599 DSO_free(hwcrhk_dso);
601 p_hwcrhk_Init = NULL;
602 p_hwcrhk_Finish = NULL;
603 p_hwcrhk_ModExp = NULL;
604 #ifndef OPENSSL_NO_RSA
606 p_hwcrhk_RSALoadKey = NULL;
607 p_hwcrhk_RSAGetPublicKey = NULL;
608 p_hwcrhk_RSAUnloadKey = NULL;
610 p_hwcrhk_ModExpCRT = NULL;
611 p_hwcrhk_RandomBytes = NULL;
615 static int hwcrhk_finish(ENGINE *e)
618 free_HWCRHK_LIBNAME();
619 if(hwcrhk_dso == NULL)
621 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
625 release_context(hwcrhk_context);
626 if(!DSO_free(hwcrhk_dso))
628 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
636 p_hwcrhk_Init = NULL;
637 p_hwcrhk_Finish = NULL;
638 p_hwcrhk_ModExp = NULL;
639 #ifndef OPENSSL_NO_RSA
641 p_hwcrhk_RSALoadKey = NULL;
642 p_hwcrhk_RSAGetPublicKey = NULL;
643 p_hwcrhk_RSAUnloadKey = NULL;
645 p_hwcrhk_ModExpCRT = NULL;
646 p_hwcrhk_RandomBytes = NULL;
650 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
656 case HWCRHK_CMD_SO_PATH:
659 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
664 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
667 return set_HWCRHK_LIBNAME((const char *)p);
668 case ENGINE_CTRL_SET_LOGSTREAM:
672 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
678 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
681 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
683 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
685 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
686 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
687 password_context.password_callback = (pem_password_cb *)f;
688 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
690 case ENGINE_CTRL_SET_USER_INTERFACE:
691 case HWCRHK_CMD_SET_USER_INTERFACE:
692 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
693 password_context.ui_method = (UI_METHOD *)p;
694 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
696 case ENGINE_CTRL_SET_CALLBACK_DATA:
697 case HWCRHK_CMD_SET_CALLBACK_DATA:
698 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
699 password_context.callback_data = p;
700 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
702 /* this enables or disables the "SimpleForkCheck" flag used in the
703 * initialisation structure. */
704 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
705 case HWCRHK_CMD_FORK_CHECK:
706 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
708 hwcrhk_globals.flags |=
709 HWCryptoHook_InitFlags_SimpleForkCheck;
711 hwcrhk_globals.flags &=
712 ~HWCryptoHook_InitFlags_SimpleForkCheck;
713 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
715 /* This will prevent the initialisation function from "installing"
716 * the mutex-handling callbacks, even if they are available from
717 * within the library (or were provided to the library from the
718 * calling application). This is to remove any baggage for
719 * applications not using multithreading. */
720 case ENGINE_CTRL_CHIL_NO_LOCKING:
721 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
722 disable_mutex_callbacks = 1;
723 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
725 case HWCRHK_CMD_THREAD_LOCKING:
726 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
727 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
728 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
731 /* The command isn't understood by this engine */
733 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
734 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
742 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
743 UI_METHOD *ui_method, void *callback_data)
745 #ifndef OPENSSL_NO_RSA
748 EVP_PKEY *res = NULL;
749 #ifndef OPENSSL_NO_RSA
750 HWCryptoHook_MPI e, n;
751 HWCryptoHook_RSAKeyHandle *hptr;
753 #if !defined(OPENSSL_NO_RSA)
755 HWCryptoHook_ErrMsgBuf rmsg;
757 HWCryptoHook_PassphraseContext ppctx;
759 #if !defined(OPENSSL_NO_RSA)
761 rmsg.size = sizeof(tempbuf);
766 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
767 HWCRHK_R_NOT_INITIALISED);
770 #ifndef OPENSSL_NO_RSA
771 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
774 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
775 ERR_R_MALLOC_FAILURE);
778 ppctx.ui_method = ui_method;
779 ppctx.callback_data = callback_data;
780 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
783 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
784 HWCRHK_R_CHIL_ERROR);
785 ERR_add_error_data(1,rmsg.buf);
790 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
795 #ifndef OPENSSL_NO_RSA
796 rtmp = RSA_new_method(eng);
797 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
800 rtmp->flags |= RSA_FLAG_EXT_PKEY;
803 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
804 != HWCRYPTOHOOK_ERROR_MPISIZE)
806 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
807 ERR_add_error_data(1,rmsg.buf);
811 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
812 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
816 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
818 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
819 HWCRHK_R_CHIL_ERROR);
820 ERR_add_error_data(1,rmsg.buf);
823 rtmp->e->top = e.size / sizeof(BN_ULONG);
825 rtmp->n->top = n.size / sizeof(BN_ULONG);
828 res = EVP_PKEY_new();
829 EVP_PKEY_assign_RSA(res, rtmp);
833 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
834 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
840 #ifndef OPENSSL_NO_RSA
847 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
848 UI_METHOD *ui_method, void *callback_data)
850 EVP_PKEY *res = NULL;
852 #ifndef OPENSSL_NO_RSA
853 res = hwcrhk_load_privkey(eng, key_id,
854 ui_method, callback_data);
860 #ifndef OPENSSL_NO_RSA
865 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
867 res->pkey.rsa = RSA_new();
868 res->pkey.rsa->n = rsa->n;
869 res->pkey.rsa->e = rsa->e;
872 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
878 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
879 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
890 /* A little mod_exp */
891 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
892 const BIGNUM *m, BN_CTX *ctx)
895 HWCryptoHook_ErrMsgBuf rmsg;
896 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
897 we use them directly, plus a little macro magic. We only
898 thing we need to make sure of is that enough space is allocated. */
899 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
902 to_return = 0; /* expect failure */
904 rmsg.size = sizeof(tempbuf);
908 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
911 /* Prepare the params */
912 bn_expand2(r, m->top); /* Check for error !! */
918 /* Perform the operation */
919 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
921 /* Convert the response */
922 r->top = m_r.size / sizeof(BN_ULONG);
927 /* FIXME: When this error is returned, HWCryptoHook is
928 telling us that falling back to software computation
929 might be a good thing. */
930 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
932 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
936 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
938 ERR_add_error_data(1,rmsg.buf);
947 #ifndef OPENSSL_NO_RSA
948 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
951 HWCryptoHook_ErrMsgBuf rmsg;
952 HWCryptoHook_RSAKeyHandle *hptr;
953 int to_return = 0, ret;
956 rmsg.size = sizeof(tempbuf);
960 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
964 /* This provides support for nForce keys. Since that's opaque data
965 all we do is provide a handle to the proper key and let HWCryptoHook
966 take care of the rest. */
967 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
970 HWCryptoHook_MPI m_a, m_r;
974 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
975 HWCRHK_R_MISSING_KEY_COMPONENTS);
979 /* Prepare the params */
980 bn_expand2(r, rsa->n->top); /* Check for error !! */
984 /* Perform the operation */
985 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
987 /* Convert the response */
988 r->top = m_r.size / sizeof(BN_ULONG);
993 /* FIXME: When this error is returned, HWCryptoHook is
994 telling us that falling back to software computation
995 might be a good thing. */
996 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
998 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
999 HWCRHK_R_REQUEST_FALLBACK);
1003 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1004 HWCRHK_R_REQUEST_FAILED);
1006 ERR_add_error_data(1,rmsg.buf);
1012 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1014 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1016 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1017 HWCRHK_R_MISSING_KEY_COMPONENTS);
1021 /* Prepare the params */
1022 bn_expand2(r, rsa->n->top); /* Check for error !! */
1024 BN2MPI(m_p, rsa->p);
1025 BN2MPI(m_q, rsa->q);
1026 BN2MPI(m_dmp1, rsa->dmp1);
1027 BN2MPI(m_dmq1, rsa->dmq1);
1028 BN2MPI(m_iqmp, rsa->iqmp);
1031 /* Perform the operation */
1032 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1033 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1035 /* Convert the response */
1036 r->top = m_r.size / sizeof(BN_ULONG);
1041 /* FIXME: When this error is returned, HWCryptoHook is
1042 telling us that falling back to software computation
1043 might be a good thing. */
1044 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1046 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1047 HWCRHK_R_REQUEST_FALLBACK);
1051 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1052 HWCRHK_R_REQUEST_FAILED);
1054 ERR_add_error_data(1,rmsg.buf);
1058 /* If we're here, we must be here with some semblance of success :-) */
1065 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1066 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1067 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1069 return hwcrhk_mod_exp(r, a, p, m, ctx);
1072 #ifndef OPENSSL_NO_DH
1073 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1074 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1075 const BIGNUM *a, const BIGNUM *p,
1076 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1078 return hwcrhk_mod_exp(r, a, p, m, ctx);
1082 /* Random bytes are good */
1083 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1086 HWCryptoHook_ErrMsgBuf rmsg;
1087 int to_return = 0; /* assume failure */
1091 rmsg.size = sizeof(tempbuf);
1095 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1099 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1102 /* FIXME: When this error is returned, HWCryptoHook is
1103 telling us that falling back to software computation
1104 might be a good thing. */
1105 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1107 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1108 HWCRHK_R_REQUEST_FALLBACK);
1112 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1113 HWCRHK_R_REQUEST_FAILED);
1115 ERR_add_error_data(1,rmsg.buf);
1123 static int hwcrhk_rand_status(void)
1128 /* This cleans up an RSA KM key, called when ex_data is freed */
1130 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1131 int ind,long argl, void *argp)
1134 HWCryptoHook_ErrMsgBuf rmsg;
1135 #ifndef OPENSSL_NO_RSA
1136 HWCryptoHook_RSAKeyHandle *hptr;
1138 #if !defined(OPENSSL_NO_RSA)
1143 rmsg.size = sizeof(tempbuf);
1145 #ifndef OPENSSL_NO_RSA
1146 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1149 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1155 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1156 * these just wrap the POSIX functions and add some logging.
1159 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1160 HWCryptoHook_CallerContext *cactx)
1162 mt->lockid = CRYPTO_get_new_dynlockid();
1163 if (mt->lockid == 0)
1164 return 1; /* failure */
1165 return 0; /* success */
1168 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1170 CRYPTO_w_lock(mt->lockid);
1174 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1176 CRYPTO_w_unlock(mt->lockid);
1179 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1181 CRYPTO_destroy_dynlockid(mt->lockid);
1184 static int hwcrhk_get_pass(const char *prompt_info,
1185 int *len_io, char *buf,
1186 HWCryptoHook_PassphraseContext *ppctx,
1187 HWCryptoHook_CallerContext *cactx)
1189 pem_password_cb *callback = NULL;
1190 void *callback_data = NULL;
1191 UI_METHOD *ui_method = NULL;
1195 if (cactx->ui_method)
1196 ui_method = cactx->ui_method;
1197 if (cactx->password_callback)
1198 callback = cactx->password_callback;
1199 if (cactx->callback_data)
1200 callback_data = cactx->callback_data;
1204 if (ppctx->ui_method)
1206 ui_method = ppctx->ui_method;
1209 if (ppctx->callback_data)
1210 callback_data = ppctx->callback_data;
1212 if (callback == NULL && ui_method == NULL)
1214 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1220 UI *ui = UI_new_method(ui_method);
1224 char *prompt = UI_construct_prompt(ui,
1225 "pass phrase", prompt_info);
1227 ok = UI_add_input_string(ui,prompt,
1228 UI_INPUT_FLAG_DEFAULT_PWD,
1229 buf,0,(*len_io) - 1);
1230 UI_add_user_data(ui, callback_data);
1231 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1238 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1241 *len_io = strlen(buf);
1244 OPENSSL_free(prompt);
1249 *len_io = callback(buf, *len_io, 0, callback_data);
1256 static int hwcrhk_insert_card(const char *prompt_info,
1257 const char *wrong_info,
1258 HWCryptoHook_PassphraseContext *ppctx,
1259 HWCryptoHook_CallerContext *cactx)
1263 void *callback_data = NULL;
1264 UI_METHOD *ui_method = NULL;
1268 if (cactx->ui_method)
1269 ui_method = cactx->ui_method;
1270 if (cactx->callback_data)
1271 callback_data = cactx->callback_data;
1275 if (ppctx->ui_method)
1276 ui_method = ppctx->ui_method;
1277 if (ppctx->callback_data)
1278 callback_data = ppctx->callback_data;
1280 if (ui_method == NULL)
1282 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1283 HWCRHK_R_NO_CALLBACK);
1287 ui = UI_new_method(ui_method);
1295 BIO_snprintf(buf, sizeof(buf)-1,
1296 "Current card: \"%s\"\n", wrong_info);
1297 ok = UI_dup_info_string(ui, buf);
1298 if (ok >= 0 && prompt_info)
1300 BIO_snprintf(buf, sizeof(buf)-1,
1301 "Insert card \"%s\"", prompt_info);
1302 ok = UI_dup_input_boolean(ui, buf,
1303 "\n then hit <enter> or C<enter> to cancel\n",
1304 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1306 UI_add_user_data(ui, callback_data);
1309 ok = UI_process(ui);
1312 if (ok == -2 || (ok >= 0 && answer == 'C'))
1322 static void hwcrhk_log_message(void *logstr, const char *message)
1324 BIO *lstream = NULL;
1326 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1328 lstream=*(BIO **)logstr;
1331 BIO_printf(lstream, "%s\n", message);
1333 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1336 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1337 * shared-library. */
1338 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1339 static int bind_fn(ENGINE *e, const char *id)
1341 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1347 IMPLEMENT_DYNAMIC_CHECK_FN()
1348 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1349 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1351 #endif /* !OPENSSL_NO_HW_NCIPHER */
1352 #endif /* !OPENSSL_NO_HW */