1 /* crypto/engine/e_chil.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 (steve@openssl.org)
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>
67 #include <openssl/rand.h>
68 #ifndef OPENSSL_NO_RSA
69 #include <openssl/rsa.h>
72 #include <openssl/dh.h>
74 #include <openssl/bn.h>
77 #ifndef OPENSSL_NO_HW_CHIL
80 * Attribution notice: nCipher have said several times that it's OK for
81 * us to implement a general interface to their boxes, and recently declared
82 * their HWCryptoHook to be public, and therefore available for us to use.
85 * The hwcryptohook.h included here is from May 2000.
89 #include "hwcryptohook.h"
91 #include "vendor_defns/hwcryptohook.h"
94 #define HWCRHK_LIB_NAME "CHIL engine"
95 #include "e_chil_err.c"
97 static int hwcrhk_destroy(ENGINE *e);
98 static int hwcrhk_init(ENGINE *e);
99 static int hwcrhk_finish(ENGINE *e);
100 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
102 /* Functions to handle mutexes */
103 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
104 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
105 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
106 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
109 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
110 const BIGNUM *m, BN_CTX *ctx);
112 #ifndef OPENSSL_NO_RSA
114 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
115 /* This function is aliased to mod_exp (with the mont stuff dropped). */
116 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
117 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
118 static int hwcrhk_rsa_finish(RSA *rsa);
121 #ifndef OPENSSL_NO_DH
123 /* This function is alised to mod_exp (with the DH and mont dropped). */
124 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
125 const BIGNUM *a, const BIGNUM *p,
126 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
130 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
131 static int hwcrhk_rand_status(void);
134 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
135 UI_METHOD *ui_method, void *callback_data);
136 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
137 UI_METHOD *ui_method, void *callback_data);
139 /* Interaction stuff */
140 static int hwcrhk_insert_card(const char *prompt_info,
141 const char *wrong_info,
142 HWCryptoHook_PassphraseContext *ppctx,
143 HWCryptoHook_CallerContext *cactx);
144 static int hwcrhk_get_pass(const char *prompt_info,
145 int *len_io, char *buf,
146 HWCryptoHook_PassphraseContext *ppctx,
147 HWCryptoHook_CallerContext *cactx);
148 static void hwcrhk_log_message(void *logstr, const char *message);
150 /* The definitions for control commands specific to this engine */
151 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
152 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
153 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
154 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
155 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
156 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
159 "Specifies the path to the 'hwcrhk' shared library",
160 ENGINE_CMD_FLAG_STRING},
161 {HWCRHK_CMD_FORK_CHECK,
163 "Turns fork() checking on (non-zero) or off (zero)",
164 ENGINE_CMD_FLAG_NUMERIC},
165 {HWCRHK_CMD_THREAD_LOCKING,
167 "Turns thread-safe locking on (zero) or off (non-zero)",
168 ENGINE_CMD_FLAG_NUMERIC},
169 {HWCRHK_CMD_SET_USER_INTERFACE,
170 "SET_USER_INTERFACE",
171 "Set the global user interface (internal)",
172 ENGINE_CMD_FLAG_INTERNAL},
173 {HWCRHK_CMD_SET_CALLBACK_DATA,
175 "Set the global user interface extra data (internal)",
176 ENGINE_CMD_FLAG_INTERNAL},
180 #ifndef OPENSSL_NO_RSA
181 /* Our internal RSA_METHOD that we provide pointers to */
182 static RSA_METHOD hwcrhk_rsa =
201 #ifndef OPENSSL_NO_DH
202 /* Our internal DH_METHOD that we provide pointers to */
203 static DH_METHOD hwcrhk_dh =
217 static RAND_METHOD hwcrhk_rand =
219 /* "CHIL RAND method", */
228 /* Constants used when creating the ENGINE */
229 static const char *engine_hwcrhk_id = "chil";
230 static const char *engine_hwcrhk_name = "CHIL hardware engine support";
231 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
232 /* Compatibility hack, the dynamic library uses this form in the path */
233 static const char *engine_hwcrhk_id_alt = "ncipher";
236 /* Internal stuff for HWCryptoHook */
238 /* Some structures needed for proper use of thread locks */
239 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
240 into HWCryptoHook_Mutex */
241 struct HWCryptoHook_MutexValue
246 /* hwcryptohook.h has some typedefs that turn
247 struct HWCryptoHook_PassphraseContextValue
248 into HWCryptoHook_PassphraseContext */
249 struct HWCryptoHook_PassphraseContextValue
251 UI_METHOD *ui_method;
255 /* hwcryptohook.h has some typedefs that turn
256 struct HWCryptoHook_CallerContextValue
257 into HWCryptoHook_CallerContext */
258 struct HWCryptoHook_CallerContextValue
260 pem_password_cb *password_callback; /* Deprecated! Only present for
261 backward compatibility! */
262 UI_METHOD *ui_method;
266 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
267 BIGNUM's, so lets define a couple of conversion macros */
268 #define BN2MPI(mp, bn) \
269 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
270 #define MPI2BN(bn, mp) \
271 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
273 static BIO *logstream = NULL;
274 static int disable_mutex_callbacks = 0;
276 /* One might wonder why these are needed, since one can pass down at least
277 a UI_METHOD and a pointer to callback data to the key-loading functions.
278 The thing is that the ModExp and RSAImmed functions can load keys as well,
279 if the data they get is in a special, nCipher-defined format (hint: if you
280 look at the private exponent of the RSA data as a string, you'll see this
281 string: "nCipher KM tool key id", followed by some bytes, followed a key
282 identity string, followed by more bytes. This happens when you use "embed"
283 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
284 any passphrase or caller context, and our functions can't really take any
285 callback data either. Still, the "insert_card" and "get_passphrase"
286 callbacks may be called down the line, and will need to know what user
287 interface callbacks to call, and having callback data from the application
288 may be a nice thing as well, so we need to keep track of that globally. */
289 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
291 /* Stuff to pass to the HWCryptoHook library */
292 static HWCryptoHook_InitInfo hwcrhk_globals = {
293 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
294 &logstream, /* logstream */
295 sizeof(BN_ULONG), /* limbsize */
296 0, /* mslimb first: false for BNs */
297 -1, /* msbyte first: use native */
298 0, /* Max mutexes, 0 = no small limit */
299 0, /* Max simultaneous, 0 = default */
301 /* The next few are mutex stuff: we write wrapper functions
302 around the OS mutex functions. We initialise them to 0
303 here, and change that to actual function pointers in hwcrhk_init()
304 if dynamic locks are supported (that is, if the application
305 programmer has made sure of setting up callbacks bafore starting
306 this engine) *and* if disable_mutex_callbacks hasn't been set by
307 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
308 sizeof(HWCryptoHook_Mutex),
314 /* The next few are condvar stuff: we write wrapper functions
315 round the OS functions. Currently not implemented and not
316 and absolute necessity even in threaded programs, therefore
317 0'ed. Will hopefully be implemented some day, since it
318 enhances the efficiency of HWCryptoHook. */
319 0, /* sizeof(HWCryptoHook_CondVar), */
320 0, /* hwcrhk_cv_init, */
321 0, /* hwcrhk_cv_wait, */
322 0, /* hwcrhk_cv_signal, */
323 0, /* hwcrhk_cv_broadcast, */
324 0, /* hwcrhk_cv_destroy, */
326 hwcrhk_get_pass, /* pass phrase */
327 hwcrhk_insert_card, /* insert a card */
328 hwcrhk_log_message /* Log message */
332 /* Now, to our own code */
334 /* This internal function is used by ENGINE_chil() and possibly by the
335 * "dynamic" ENGINE support too */
336 static int bind_helper(ENGINE *e)
338 #ifndef OPENSSL_NO_RSA
339 const RSA_METHOD *meth1;
341 #ifndef OPENSSL_NO_DH
342 const DH_METHOD *meth2;
344 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
345 !ENGINE_set_name(e, engine_hwcrhk_name) ||
346 #ifndef OPENSSL_NO_RSA
347 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
349 #ifndef OPENSSL_NO_DH
350 !ENGINE_set_DH(e, &hwcrhk_dh) ||
352 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
353 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
354 !ENGINE_set_init_function(e, hwcrhk_init) ||
355 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
356 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
357 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
358 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
359 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
362 #ifndef OPENSSL_NO_RSA
363 /* We know that the "PKCS1_SSLeay()" functions hook properly
364 * to the cswift-specific mod_exp and mod_exp_crt so we use
365 * those functions. NB: We don't use ENGINE_openssl() or
366 * anything "more generic" because something like the RSAref
367 * code may not hook properly, and if you own one of these
368 * cards then you have the right to do RSA operations on it
370 meth1 = RSA_PKCS1_SSLeay();
371 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
372 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
373 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
374 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
377 #ifndef OPENSSL_NO_DH
378 /* Much the same for Diffie-Hellman */
379 meth2 = DH_OpenSSL();
380 hwcrhk_dh.generate_key = meth2->generate_key;
381 hwcrhk_dh.compute_key = meth2->compute_key;
384 /* Ensure the hwcrhk error handling is set up */
385 ERR_load_HWCRHK_strings();
389 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
390 static ENGINE *engine_chil(void)
392 ENGINE *ret = ENGINE_new();
395 if(!bind_helper(ret))
403 void ENGINE_load_chil(void)
405 /* Copied from eng_[openssl|dyn].c */
406 ENGINE *toadd = engine_chil();
414 /* This is a process-global DSO handle used for loading and unloading
415 * the HWCryptoHook library. NB: This is only set (or unset) during an
416 * init() or finish() call (reference counts permitting) and they're
417 * operating with global locks, so this should be thread-safe
419 static DSO *hwcrhk_dso = NULL;
420 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
421 #ifndef OPENSSL_NO_RSA
422 /* Index for KM handle. Not really used yet. */
423 static int hndidx_rsa = -1;
426 /* These are the function pointers that are (un)set when the library has
427 * successfully (un)loaded. */
428 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
429 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
430 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
431 #ifndef OPENSSL_NO_RSA
432 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
434 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
435 #ifndef OPENSSL_NO_RSA
436 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
437 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
438 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
440 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
442 /* Used in the DSO operations. */
443 static const char *HWCRHK_LIBNAME = NULL;
444 static void free_HWCRHK_LIBNAME(void)
447 OPENSSL_free((void*)HWCRHK_LIBNAME);
448 HWCRHK_LIBNAME = NULL;
450 static const char *get_HWCRHK_LIBNAME(void)
453 return HWCRHK_LIBNAME;
456 static long set_HWCRHK_LIBNAME(const char *name)
458 free_HWCRHK_LIBNAME();
459 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
461 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
462 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
463 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
464 #ifndef OPENSSL_NO_RSA
465 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
467 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
468 #ifndef OPENSSL_NO_RSA
469 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
470 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
471 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
473 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
475 /* HWCryptoHook library functions and mechanics - these are used by the
476 * higher-level functions further down. NB: As and where there's no
477 * error checking, take a look lower down where these functions are
478 * called, the checking and error handling is probably down there. */
480 /* utility function to obtain a context */
481 static int get_context(HWCryptoHook_ContextHandle *hac,
482 HWCryptoHook_CallerContext *cac)
485 HWCryptoHook_ErrMsgBuf rmsg;
488 rmsg.size = sizeof(tempbuf);
490 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
497 /* similarly to release one. */
498 static void release_context(HWCryptoHook_ContextHandle hac)
500 p_hwcrhk_Finish(hac);
503 /* Destructor (complements the "ENGINE_chil()" constructor) */
504 static int hwcrhk_destroy(ENGINE *e)
506 free_HWCRHK_LIBNAME();
507 ERR_unload_HWCRHK_strings();
511 /* (de)initialisation functions. */
512 static int hwcrhk_init(ENGINE *e)
514 HWCryptoHook_Init_t *p1;
515 HWCryptoHook_Finish_t *p2;
516 HWCryptoHook_ModExp_t *p3;
517 #ifndef OPENSSL_NO_RSA
518 HWCryptoHook_RSA_t *p4;
519 HWCryptoHook_RSALoadKey_t *p5;
520 HWCryptoHook_RSAGetPublicKey_t *p6;
521 HWCryptoHook_RSAUnloadKey_t *p7;
523 HWCryptoHook_RandomBytes_t *p8;
524 HWCryptoHook_ModExpCRT_t *p9;
526 if(hwcrhk_dso != NULL)
528 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
531 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
532 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
533 if(hwcrhk_dso == NULL)
535 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
538 if(!(p1 = (HWCryptoHook_Init_t *)
539 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
540 !(p2 = (HWCryptoHook_Finish_t *)
541 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
542 !(p3 = (HWCryptoHook_ModExp_t *)
543 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
544 #ifndef OPENSSL_NO_RSA
545 !(p4 = (HWCryptoHook_RSA_t *)
546 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
547 !(p5 = (HWCryptoHook_RSALoadKey_t *)
548 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
549 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
550 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
551 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
552 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
554 !(p8 = (HWCryptoHook_RandomBytes_t *)
555 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
556 !(p9 = (HWCryptoHook_ModExpCRT_t *)
557 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
559 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
562 /* Copy the pointers */
564 p_hwcrhk_Finish = p2;
565 p_hwcrhk_ModExp = p3;
566 #ifndef OPENSSL_NO_RSA
568 p_hwcrhk_RSALoadKey = p5;
569 p_hwcrhk_RSAGetPublicKey = p6;
570 p_hwcrhk_RSAUnloadKey = p7;
572 p_hwcrhk_RandomBytes = p8;
573 p_hwcrhk_ModExpCRT = p9;
575 /* Check if the application decided to support dynamic locks,
576 and if it does, use them. */
577 if (disable_mutex_callbacks == 0)
579 if (CRYPTO_get_dynlock_create_callback() != NULL &&
580 CRYPTO_get_dynlock_lock_callback() != NULL &&
581 CRYPTO_get_dynlock_destroy_callback() != NULL)
583 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
584 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
585 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
586 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
590 /* Try and get a context - if not, we may have a DSO but no
592 if(!get_context(&hwcrhk_context, &password_context))
594 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
597 /* Everything's fine. */
598 #ifndef OPENSSL_NO_RSA
599 if (hndidx_rsa == -1)
600 hndidx_rsa = RSA_get_ex_new_index(0,
601 "nFast HWCryptoHook RSA key handle",
607 DSO_free(hwcrhk_dso);
609 p_hwcrhk_Init = NULL;
610 p_hwcrhk_Finish = NULL;
611 p_hwcrhk_ModExp = NULL;
612 #ifndef OPENSSL_NO_RSA
614 p_hwcrhk_RSALoadKey = NULL;
615 p_hwcrhk_RSAGetPublicKey = NULL;
616 p_hwcrhk_RSAUnloadKey = NULL;
618 p_hwcrhk_ModExpCRT = NULL;
619 p_hwcrhk_RandomBytes = NULL;
623 static int hwcrhk_finish(ENGINE *e)
626 free_HWCRHK_LIBNAME();
627 if(hwcrhk_dso == NULL)
629 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
633 release_context(hwcrhk_context);
634 if(!DSO_free(hwcrhk_dso))
636 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
644 p_hwcrhk_Init = NULL;
645 p_hwcrhk_Finish = NULL;
646 p_hwcrhk_ModExp = NULL;
647 #ifndef OPENSSL_NO_RSA
649 p_hwcrhk_RSALoadKey = NULL;
650 p_hwcrhk_RSAGetPublicKey = NULL;
651 p_hwcrhk_RSAUnloadKey = NULL;
653 p_hwcrhk_ModExpCRT = NULL;
654 p_hwcrhk_RandomBytes = NULL;
658 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
664 case HWCRHK_CMD_SO_PATH:
667 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
672 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
675 return set_HWCRHK_LIBNAME((const char *)p);
676 case ENGINE_CTRL_SET_LOGSTREAM:
680 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
686 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
689 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
691 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
693 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
694 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
695 password_context.password_callback = (pem_password_cb *)f;
696 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
698 case ENGINE_CTRL_SET_USER_INTERFACE:
699 case HWCRHK_CMD_SET_USER_INTERFACE:
700 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
701 password_context.ui_method = (UI_METHOD *)p;
702 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
704 case ENGINE_CTRL_SET_CALLBACK_DATA:
705 case HWCRHK_CMD_SET_CALLBACK_DATA:
706 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
707 password_context.callback_data = p;
708 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
710 /* this enables or disables the "SimpleForkCheck" flag used in the
711 * initialisation structure. */
712 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
713 case HWCRHK_CMD_FORK_CHECK:
714 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
716 hwcrhk_globals.flags |=
717 HWCryptoHook_InitFlags_SimpleForkCheck;
719 hwcrhk_globals.flags &=
720 ~HWCryptoHook_InitFlags_SimpleForkCheck;
721 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
723 /* This will prevent the initialisation function from "installing"
724 * the mutex-handling callbacks, even if they are available from
725 * within the library (or were provided to the library from the
726 * calling application). This is to remove any baggage for
727 * applications not using multithreading. */
728 case ENGINE_CTRL_CHIL_NO_LOCKING:
729 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
730 disable_mutex_callbacks = 1;
731 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
733 case HWCRHK_CMD_THREAD_LOCKING:
734 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
735 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
736 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
739 /* The command isn't understood by this engine */
741 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
742 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
750 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
751 UI_METHOD *ui_method, void *callback_data)
753 #ifndef OPENSSL_NO_RSA
756 EVP_PKEY *res = NULL;
757 #ifndef OPENSSL_NO_RSA
758 HWCryptoHook_MPI e, n;
759 HWCryptoHook_RSAKeyHandle *hptr;
761 #if !defined(OPENSSL_NO_RSA)
763 HWCryptoHook_ErrMsgBuf rmsg;
764 HWCryptoHook_PassphraseContext ppctx;
767 #if !defined(OPENSSL_NO_RSA)
769 rmsg.size = sizeof(tempbuf);
774 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
775 HWCRHK_R_NOT_INITIALISED);
778 #ifndef OPENSSL_NO_RSA
779 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
782 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
783 ERR_R_MALLOC_FAILURE);
786 ppctx.ui_method = ui_method;
787 ppctx.callback_data = callback_data;
788 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
791 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
792 HWCRHK_R_CHIL_ERROR);
793 ERR_add_error_data(1,rmsg.buf);
798 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
803 #ifndef OPENSSL_NO_RSA
804 rtmp = RSA_new_method(eng);
805 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
808 rtmp->flags |= RSA_FLAG_EXT_PKEY;
811 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
812 != HWCRYPTOHOOK_ERROR_MPISIZE)
814 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,HWCRHK_R_CHIL_ERROR);
815 ERR_add_error_data(1,rmsg.buf);
819 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
820 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
824 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
826 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
827 HWCRHK_R_CHIL_ERROR);
828 ERR_add_error_data(1,rmsg.buf);
831 rtmp->e->top = e.size / sizeof(BN_ULONG);
833 rtmp->n->top = n.size / sizeof(BN_ULONG);
836 res = EVP_PKEY_new();
837 EVP_PKEY_assign_RSA(res, rtmp);
841 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
842 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
846 #ifndef OPENSSL_NO_RSA
853 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
854 UI_METHOD *ui_method, void *callback_data)
856 EVP_PKEY *res = NULL;
858 #ifndef OPENSSL_NO_RSA
859 res = hwcrhk_load_privkey(eng, key_id,
860 ui_method, callback_data);
866 #ifndef OPENSSL_NO_RSA
871 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
873 res->pkey.rsa = RSA_new();
874 res->pkey.rsa->n = rsa->n;
875 res->pkey.rsa->e = rsa->e;
878 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
884 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
885 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
896 /* A little mod_exp */
897 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
898 const BIGNUM *m, BN_CTX *ctx)
901 HWCryptoHook_ErrMsgBuf rmsg;
902 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
903 we use them directly, plus a little macro magic. We only
904 thing we need to make sure of is that enough space is allocated. */
905 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
908 to_return = 0; /* expect failure */
910 rmsg.size = sizeof(tempbuf);
914 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
917 /* Prepare the params */
918 bn_expand2(r, m->top); /* Check for error !! */
924 /* Perform the operation */
925 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
927 /* Convert the response */
928 r->top = m_r.size / sizeof(BN_ULONG);
933 /* FIXME: When this error is returned, HWCryptoHook is
934 telling us that falling back to software computation
935 might be a good thing. */
936 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
938 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
942 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
944 ERR_add_error_data(1,rmsg.buf);
953 #ifndef OPENSSL_NO_RSA
954 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
957 HWCryptoHook_ErrMsgBuf rmsg;
958 HWCryptoHook_RSAKeyHandle *hptr;
959 int to_return = 0, ret;
962 rmsg.size = sizeof(tempbuf);
966 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
970 /* This provides support for nForce keys. Since that's opaque data
971 all we do is provide a handle to the proper key and let HWCryptoHook
972 take care of the rest. */
973 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
976 HWCryptoHook_MPI m_a, m_r;
980 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
981 HWCRHK_R_MISSING_KEY_COMPONENTS);
985 /* Prepare the params */
986 bn_expand2(r, rsa->n->top); /* Check for error !! */
990 /* Perform the operation */
991 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
993 /* Convert the response */
994 r->top = m_r.size / sizeof(BN_ULONG);
999 /* FIXME: When this error is returned, HWCryptoHook is
1000 telling us that falling back to software computation
1001 might be a good thing. */
1002 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1004 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1005 HWCRHK_R_REQUEST_FALLBACK);
1009 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1010 HWCRHK_R_REQUEST_FAILED);
1012 ERR_add_error_data(1,rmsg.buf);
1018 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1020 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1022 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1023 HWCRHK_R_MISSING_KEY_COMPONENTS);
1027 /* Prepare the params */
1028 bn_expand2(r, rsa->n->top); /* Check for error !! */
1030 BN2MPI(m_p, rsa->p);
1031 BN2MPI(m_q, rsa->q);
1032 BN2MPI(m_dmp1, rsa->dmp1);
1033 BN2MPI(m_dmq1, rsa->dmq1);
1034 BN2MPI(m_iqmp, rsa->iqmp);
1037 /* Perform the operation */
1038 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1039 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1041 /* Convert the response */
1042 r->top = m_r.size / sizeof(BN_ULONG);
1047 /* FIXME: When this error is returned, HWCryptoHook is
1048 telling us that falling back to software computation
1049 might be a good thing. */
1050 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1052 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1053 HWCRHK_R_REQUEST_FALLBACK);
1057 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1058 HWCRHK_R_REQUEST_FAILED);
1060 ERR_add_error_data(1,rmsg.buf);
1064 /* If we're here, we must be here with some semblance of success :-) */
1071 #ifndef OPENSSL_NO_RSA
1072 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1073 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1074 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1076 return hwcrhk_mod_exp(r, a, p, m, ctx);
1079 static int hwcrhk_rsa_finish(RSA *rsa)
1081 HWCryptoHook_RSAKeyHandle *hptr;
1083 hptr = RSA_get_ex_data(rsa, hndidx_rsa);
1086 p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1088 RSA_set_ex_data(rsa, hndidx_rsa, NULL);
1095 #ifndef OPENSSL_NO_DH
1096 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1097 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1098 const BIGNUM *a, const BIGNUM *p,
1099 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1101 return hwcrhk_mod_exp(r, a, p, m, ctx);
1105 /* Random bytes are good */
1106 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1109 HWCryptoHook_ErrMsgBuf rmsg;
1110 int to_return = 0; /* assume failure */
1114 rmsg.size = sizeof(tempbuf);
1118 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1122 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1125 /* FIXME: When this error is returned, HWCryptoHook is
1126 telling us that falling back to software computation
1127 might be a good thing. */
1128 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1130 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1131 HWCRHK_R_REQUEST_FALLBACK);
1135 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1136 HWCRHK_R_REQUEST_FAILED);
1138 ERR_add_error_data(1,rmsg.buf);
1146 static int hwcrhk_rand_status(void)
1151 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1152 * these just wrap the POSIX functions and add some logging.
1155 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1156 HWCryptoHook_CallerContext *cactx)
1158 mt->lockid = CRYPTO_get_new_dynlockid();
1159 if (mt->lockid == 0)
1160 return 1; /* failure */
1161 return 0; /* success */
1164 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1166 CRYPTO_w_lock(mt->lockid);
1170 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1172 CRYPTO_w_unlock(mt->lockid);
1175 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1177 CRYPTO_destroy_dynlockid(mt->lockid);
1180 static int hwcrhk_get_pass(const char *prompt_info,
1181 int *len_io, char *buf,
1182 HWCryptoHook_PassphraseContext *ppctx,
1183 HWCryptoHook_CallerContext *cactx)
1185 pem_password_cb *callback = NULL;
1186 void *callback_data = NULL;
1187 UI_METHOD *ui_method = NULL;
1188 /* Despite what the documentation says prompt_info can be
1191 if (prompt_info && !*prompt_info)
1196 if (cactx->ui_method)
1197 ui_method = cactx->ui_method;
1198 if (cactx->password_callback)
1199 callback = cactx->password_callback;
1200 if (cactx->callback_data)
1201 callback_data = cactx->callback_data;
1205 if (ppctx->ui_method)
1207 ui_method = ppctx->ui_method;
1210 if (ppctx->callback_data)
1211 callback_data = ppctx->callback_data;
1213 if (callback == NULL && ui_method == NULL)
1215 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1221 UI *ui = UI_new_method(ui_method);
1225 char *prompt = UI_construct_prompt(ui,
1226 "pass phrase", prompt_info);
1228 ok = UI_add_input_string(ui,prompt,
1229 UI_INPUT_FLAG_DEFAULT_PWD,
1230 buf,0,(*len_io) - 1);
1231 UI_add_user_data(ui, callback_data);
1232 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1239 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1242 *len_io = strlen(buf);
1245 OPENSSL_free(prompt);
1250 *len_io = callback(buf, *len_io, 0, callback_data);
1257 static int hwcrhk_insert_card(const char *prompt_info,
1258 const char *wrong_info,
1259 HWCryptoHook_PassphraseContext *ppctx,
1260 HWCryptoHook_CallerContext *cactx)
1264 void *callback_data = NULL;
1265 UI_METHOD *ui_method = NULL;
1269 if (cactx->ui_method)
1270 ui_method = cactx->ui_method;
1271 if (cactx->callback_data)
1272 callback_data = cactx->callback_data;
1276 if (ppctx->ui_method)
1277 ui_method = ppctx->ui_method;
1278 if (ppctx->callback_data)
1279 callback_data = ppctx->callback_data;
1281 if (ui_method == NULL)
1283 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1284 HWCRHK_R_NO_CALLBACK);
1288 ui = UI_new_method(ui_method);
1294 /* Despite what the documentation says wrong_info can be
1297 if (wrong_info && *wrong_info)
1298 BIO_snprintf(buf, sizeof(buf)-1,
1299 "Current card: \"%s\"\n", wrong_info);
1302 ok = UI_dup_info_string(ui, buf);
1303 if (ok >= 0 && prompt_info)
1305 BIO_snprintf(buf, sizeof(buf)-1,
1306 "Insert card \"%s\"", prompt_info);
1307 ok = UI_dup_input_boolean(ui, buf,
1308 "\n then hit <enter> or C<enter> to cancel\n",
1309 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1311 UI_add_user_data(ui, callback_data);
1314 ok = UI_process(ui);
1317 if (ok == -2 || (ok >= 0 && answer == 'C'))
1327 static void hwcrhk_log_message(void *logstr, const char *message)
1329 BIO *lstream = NULL;
1331 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1333 lstream=*(BIO **)logstr;
1336 BIO_printf(lstream, "%s\n", message);
1338 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1341 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1342 * shared-library. */
1343 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1344 static int bind_fn(ENGINE *e, const char *id)
1346 if(id && (strcmp(id, engine_hwcrhk_id) != 0) &&
1347 (strcmp(id, engine_hwcrhk_id_alt) != 0))
1353 IMPLEMENT_DYNAMIC_CHECK_FN()
1354 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1355 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1357 #endif /* !OPENSSL_NO_HW_CHIL */
1358 #endif /* !OPENSSL_NO_HW */