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
79 /* Attribution notice: nCipher have said several times that it's OK for
80 * us to implement a general interface to their boxes, and recently declared
81 * their HWCryptoHook to be public, and therefore available for us to use.
84 * The hwcryptohook.h included here is from May 2000.
88 #include "hwcryptohook.h"
90 #include "vendor_defns/hwcryptohook.h"
93 #define HWCRHK_LIB_NAME "CHIL engine"
94 #include "e_chil_err.c"
96 static int hwcrhk_destroy(ENGINE *e);
97 static int hwcrhk_init(ENGINE *e);
98 static int hwcrhk_finish(ENGINE *e);
99 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
101 /* Functions to handle mutexes */
102 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
103 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
104 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
105 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
108 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
109 const BIGNUM *m, BN_CTX *ctx);
111 #ifndef OPENSSL_NO_RSA
113 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
114 /* This function is aliased to mod_exp (with the mont stuff dropped). */
115 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
116 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
117 static int hwcrhk_rsa_finish(RSA *rsa);
120 #ifndef OPENSSL_NO_DH
122 /* This function is alised to mod_exp (with the DH and mont dropped). */
123 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
124 const BIGNUM *a, const BIGNUM *p,
125 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
129 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
130 static int hwcrhk_rand_status(void);
133 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
134 UI_METHOD *ui_method, void *callback_data);
135 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
136 UI_METHOD *ui_method, void *callback_data);
138 /* Interaction stuff */
139 static int hwcrhk_insert_card(const char *prompt_info,
140 const char *wrong_info,
141 HWCryptoHook_PassphraseContext *ppctx,
142 HWCryptoHook_CallerContext *cactx);
143 static int hwcrhk_get_pass(const char *prompt_info,
144 int *len_io, char *buf,
145 HWCryptoHook_PassphraseContext *ppctx,
146 HWCryptoHook_CallerContext *cactx);
147 static void hwcrhk_log_message(void *logstr, const char *message);
149 /* The definitions for control commands specific to this engine */
150 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
151 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
152 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
153 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
154 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
155 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
158 "Specifies the path to the 'hwcrhk' shared library",
159 ENGINE_CMD_FLAG_STRING},
160 {HWCRHK_CMD_FORK_CHECK,
162 "Turns fork() checking on (non-zero) or off (zero)",
163 ENGINE_CMD_FLAG_NUMERIC},
164 {HWCRHK_CMD_THREAD_LOCKING,
166 "Turns thread-safe locking on (zero) or off (non-zero)",
167 ENGINE_CMD_FLAG_NUMERIC},
168 {HWCRHK_CMD_SET_USER_INTERFACE,
169 "SET_USER_INTERFACE",
170 "Set the global user interface (internal)",
171 ENGINE_CMD_FLAG_INTERNAL},
172 {HWCRHK_CMD_SET_CALLBACK_DATA,
174 "Set the global user interface extra data (internal)",
175 ENGINE_CMD_FLAG_INTERNAL},
179 #ifndef OPENSSL_NO_RSA
180 /* Our internal RSA_METHOD that we provide pointers to */
181 static RSA_METHOD hwcrhk_rsa =
200 #ifndef OPENSSL_NO_DH
201 /* Our internal DH_METHOD that we provide pointers to */
202 static DH_METHOD hwcrhk_dh =
216 static RAND_METHOD hwcrhk_rand =
218 /* "CHIL RAND method", */
227 /* Constants used when creating the ENGINE */
228 static const char *engine_hwcrhk_id = "chil";
229 static const char *engine_hwcrhk_name = "CHIL hardware engine support";
230 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
231 /* Compatibility hack, the dynamic library uses this form in the path */
232 static const char *engine_hwcrhk_id_alt = "ncipher";
235 /* Internal stuff for HWCryptoHook */
237 /* Some structures needed for proper use of thread locks */
238 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
239 into HWCryptoHook_Mutex */
240 struct HWCryptoHook_MutexValue
245 /* hwcryptohook.h has some typedefs that turn
246 struct HWCryptoHook_PassphraseContextValue
247 into HWCryptoHook_PassphraseContext */
248 struct HWCryptoHook_PassphraseContextValue
250 UI_METHOD *ui_method;
254 /* hwcryptohook.h has some typedefs that turn
255 struct HWCryptoHook_CallerContextValue
256 into HWCryptoHook_CallerContext */
257 struct HWCryptoHook_CallerContextValue
259 pem_password_cb *password_callback; /* Deprecated! Only present for
260 backward compatibility! */
261 UI_METHOD *ui_method;
265 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
266 BIGNUM's, so lets define a couple of conversion macros */
267 #define BN2MPI(mp, bn) \
268 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
269 #define MPI2BN(bn, mp) \
270 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
272 static BIO *logstream = NULL;
273 static int disable_mutex_callbacks = 0;
275 /* One might wonder why these are needed, since one can pass down at least
276 a UI_METHOD and a pointer to callback data to the key-loading functions.
277 The thing is that the ModExp and RSAImmed functions can load keys as well,
278 if the data they get is in a special, nCipher-defined format (hint: if you
279 look at the private exponent of the RSA data as a string, you'll see this
280 string: "nCipher KM tool key id", followed by some bytes, followed a key
281 identity string, followed by more bytes. This happens when you use "embed"
282 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
283 any passphrase or caller context, and our functions can't really take any
284 callback data either. Still, the "insert_card" and "get_passphrase"
285 callbacks may be called down the line, and will need to know what user
286 interface callbacks to call, and having callback data from the application
287 may be a nice thing as well, so we need to keep track of that globally. */
288 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
290 /* Stuff to pass to the HWCryptoHook library */
291 static HWCryptoHook_InitInfo hwcrhk_globals = {
292 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
293 &logstream, /* logstream */
294 sizeof(BN_ULONG), /* limbsize */
295 0, /* mslimb first: false for BNs */
296 -1, /* msbyte first: use native */
297 0, /* Max mutexes, 0 = no small limit */
298 0, /* Max simultaneous, 0 = default */
300 /* The next few are mutex stuff: we write wrapper functions
301 around the OS mutex functions. We initialise them to 0
302 here, and change that to actual function pointers in hwcrhk_init()
303 if dynamic locks are supported (that is, if the application
304 programmer has made sure of setting up callbacks bafore starting
305 this engine) *and* if disable_mutex_callbacks hasn't been set by
306 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
307 sizeof(HWCryptoHook_Mutex),
313 /* The next few are condvar stuff: we write wrapper functions
314 round the OS functions. Currently not implemented and not
315 and absolute necessity even in threaded programs, therefore
316 0'ed. Will hopefully be implemented some day, since it
317 enhances the efficiency of HWCryptoHook. */
318 0, /* sizeof(HWCryptoHook_CondVar), */
319 0, /* hwcrhk_cv_init, */
320 0, /* hwcrhk_cv_wait, */
321 0, /* hwcrhk_cv_signal, */
322 0, /* hwcrhk_cv_broadcast, */
323 0, /* hwcrhk_cv_destroy, */
325 hwcrhk_get_pass, /* pass phrase */
326 hwcrhk_insert_card, /* insert a card */
327 hwcrhk_log_message /* Log message */
331 /* Now, to our own code */
333 /* This internal function is used by ENGINE_chil() and possibly by the
334 * "dynamic" ENGINE support too */
335 static int bind_helper(ENGINE *e)
337 #ifndef OPENSSL_NO_RSA
338 const RSA_METHOD *meth1;
340 #ifndef OPENSSL_NO_DH
341 const DH_METHOD *meth2;
343 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
344 !ENGINE_set_name(e, engine_hwcrhk_name) ||
345 #ifndef OPENSSL_NO_RSA
346 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
348 #ifndef OPENSSL_NO_DH
349 !ENGINE_set_DH(e, &hwcrhk_dh) ||
351 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
352 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
353 !ENGINE_set_init_function(e, hwcrhk_init) ||
354 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
355 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
356 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
357 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
358 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
361 #ifndef OPENSSL_NO_RSA
362 /* We know that the "PKCS1_SSLeay()" functions hook properly
363 * to the cswift-specific mod_exp and mod_exp_crt so we use
364 * those functions. NB: We don't use ENGINE_openssl() or
365 * anything "more generic" because something like the RSAref
366 * code may not hook properly, and if you own one of these
367 * cards then you have the right to do RSA operations on it
369 meth1 = RSA_PKCS1_SSLeay();
370 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
371 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
372 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
373 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
376 #ifndef OPENSSL_NO_DH
377 /* Much the same for Diffie-Hellman */
378 meth2 = DH_OpenSSL();
379 hwcrhk_dh.generate_key = meth2->generate_key;
380 hwcrhk_dh.compute_key = meth2->compute_key;
383 /* Ensure the hwcrhk error handling is set up */
384 ERR_load_HWCRHK_strings();
388 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
389 static ENGINE *engine_chil(void)
391 ENGINE *ret = ENGINE_new();
394 if(!bind_helper(ret))
402 void ENGINE_load_chil(void)
404 /* Copied from eng_[openssl|dyn].c */
405 ENGINE *toadd = engine_chil();
413 /* This is a process-global DSO handle used for loading and unloading
414 * the HWCryptoHook library. NB: This is only set (or unset) during an
415 * init() or finish() call (reference counts permitting) and they're
416 * operating with global locks, so this should be thread-safe
418 static DSO *hwcrhk_dso = NULL;
419 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
420 #ifndef OPENSSL_NO_RSA
421 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
424 /* These are the function pointers that are (un)set when the library has
425 * successfully (un)loaded. */
426 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
427 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
428 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
429 #ifndef OPENSSL_NO_RSA
430 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
432 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
433 #ifndef OPENSSL_NO_RSA
434 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
435 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
436 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
438 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
440 /* Used in the DSO operations. */
441 static const char *HWCRHK_LIBNAME = NULL;
442 static void free_HWCRHK_LIBNAME(void)
445 OPENSSL_free((void*)HWCRHK_LIBNAME);
446 HWCRHK_LIBNAME = NULL;
448 static const char *get_HWCRHK_LIBNAME(void)
451 return HWCRHK_LIBNAME;
454 static long set_HWCRHK_LIBNAME(const char *name)
456 free_HWCRHK_LIBNAME();
457 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
459 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
460 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
461 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
462 #ifndef OPENSSL_NO_RSA
463 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
465 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
466 #ifndef OPENSSL_NO_RSA
467 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
468 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
469 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
471 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
473 /* HWCryptoHook library functions and mechanics - these are used by the
474 * higher-level functions further down. NB: As and where there's no
475 * error checking, take a look lower down where these functions are
476 * called, the checking and error handling is probably down there. */
478 /* utility function to obtain a context */
479 static int get_context(HWCryptoHook_ContextHandle *hac,
480 HWCryptoHook_CallerContext *cac)
483 HWCryptoHook_ErrMsgBuf rmsg;
486 rmsg.size = sizeof(tempbuf);
488 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
495 /* similarly to release one. */
496 static void release_context(HWCryptoHook_ContextHandle hac)
498 p_hwcrhk_Finish(hac);
501 /* Destructor (complements the "ENGINE_chil()" constructor) */
502 static int hwcrhk_destroy(ENGINE *e)
504 free_HWCRHK_LIBNAME();
505 ERR_unload_HWCRHK_strings();
509 /* (de)initialisation functions. */
510 static int hwcrhk_init(ENGINE *e)
512 HWCryptoHook_Init_t *p1;
513 HWCryptoHook_Finish_t *p2;
514 HWCryptoHook_ModExp_t *p3;
515 #ifndef OPENSSL_NO_RSA
516 HWCryptoHook_RSA_t *p4;
517 HWCryptoHook_RSALoadKey_t *p5;
518 HWCryptoHook_RSAGetPublicKey_t *p6;
519 HWCryptoHook_RSAUnloadKey_t *p7;
521 HWCryptoHook_RandomBytes_t *p8;
522 HWCryptoHook_ModExpCRT_t *p9;
524 if(hwcrhk_dso != NULL)
526 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
529 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
530 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
531 if(hwcrhk_dso == NULL)
533 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
536 if(!(p1 = (HWCryptoHook_Init_t *)
537 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
538 !(p2 = (HWCryptoHook_Finish_t *)
539 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
540 !(p3 = (HWCryptoHook_ModExp_t *)
541 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
542 #ifndef OPENSSL_NO_RSA
543 !(p4 = (HWCryptoHook_RSA_t *)
544 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
545 !(p5 = (HWCryptoHook_RSALoadKey_t *)
546 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
547 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
548 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
549 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
550 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
552 !(p8 = (HWCryptoHook_RandomBytes_t *)
553 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
554 !(p9 = (HWCryptoHook_ModExpCRT_t *)
555 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
557 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
560 /* Copy the pointers */
562 p_hwcrhk_Finish = p2;
563 p_hwcrhk_ModExp = p3;
564 #ifndef OPENSSL_NO_RSA
566 p_hwcrhk_RSALoadKey = p5;
567 p_hwcrhk_RSAGetPublicKey = p6;
568 p_hwcrhk_RSAUnloadKey = p7;
570 p_hwcrhk_RandomBytes = p8;
571 p_hwcrhk_ModExpCRT = p9;
573 /* Check if the application decided to support dynamic locks,
574 and if it does, use them. */
575 if (disable_mutex_callbacks == 0)
577 if (CRYPTO_get_dynlock_create_callback() != NULL &&
578 CRYPTO_get_dynlock_lock_callback() != NULL &&
579 CRYPTO_get_dynlock_destroy_callback() != NULL)
581 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
582 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
583 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
584 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
588 /* Try and get a context - if not, we may have a DSO but no
590 if(!get_context(&hwcrhk_context, &password_context))
592 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
595 /* Everything's fine. */
596 #ifndef OPENSSL_NO_RSA
597 if (hndidx_rsa == -1)
598 hndidx_rsa = RSA_get_ex_new_index(0,
599 "nFast HWCryptoHook RSA key handle",
605 DSO_free(hwcrhk_dso);
607 p_hwcrhk_Init = NULL;
608 p_hwcrhk_Finish = NULL;
609 p_hwcrhk_ModExp = NULL;
610 #ifndef OPENSSL_NO_RSA
612 p_hwcrhk_RSALoadKey = NULL;
613 p_hwcrhk_RSAGetPublicKey = NULL;
614 p_hwcrhk_RSAUnloadKey = NULL;
616 p_hwcrhk_ModExpCRT = NULL;
617 p_hwcrhk_RandomBytes = NULL;
621 static int hwcrhk_finish(ENGINE *e)
624 free_HWCRHK_LIBNAME();
625 if(hwcrhk_dso == NULL)
627 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
631 release_context(hwcrhk_context);
632 if(!DSO_free(hwcrhk_dso))
634 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
642 p_hwcrhk_Init = NULL;
643 p_hwcrhk_Finish = NULL;
644 p_hwcrhk_ModExp = NULL;
645 #ifndef OPENSSL_NO_RSA
647 p_hwcrhk_RSALoadKey = NULL;
648 p_hwcrhk_RSAGetPublicKey = NULL;
649 p_hwcrhk_RSAUnloadKey = NULL;
651 p_hwcrhk_ModExpCRT = NULL;
652 p_hwcrhk_RandomBytes = NULL;
656 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
662 case HWCRHK_CMD_SO_PATH:
665 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
670 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
673 return set_HWCRHK_LIBNAME((const char *)p);
674 case ENGINE_CTRL_SET_LOGSTREAM:
678 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
684 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
687 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
689 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
691 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
692 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
693 password_context.password_callback = (pem_password_cb *)f;
694 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
696 case ENGINE_CTRL_SET_USER_INTERFACE:
697 case HWCRHK_CMD_SET_USER_INTERFACE:
698 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
699 password_context.ui_method = (UI_METHOD *)p;
700 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
702 case ENGINE_CTRL_SET_CALLBACK_DATA:
703 case HWCRHK_CMD_SET_CALLBACK_DATA:
704 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
705 password_context.callback_data = p;
706 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
708 /* this enables or disables the "SimpleForkCheck" flag used in the
709 * initialisation structure. */
710 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
711 case HWCRHK_CMD_FORK_CHECK:
712 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
714 hwcrhk_globals.flags |=
715 HWCryptoHook_InitFlags_SimpleForkCheck;
717 hwcrhk_globals.flags &=
718 ~HWCryptoHook_InitFlags_SimpleForkCheck;
719 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
721 /* This will prevent the initialisation function from "installing"
722 * the mutex-handling callbacks, even if they are available from
723 * within the library (or were provided to the library from the
724 * calling application). This is to remove any baggage for
725 * applications not using multithreading. */
726 case ENGINE_CTRL_CHIL_NO_LOCKING:
727 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
728 disable_mutex_callbacks = 1;
729 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
731 case HWCRHK_CMD_THREAD_LOCKING:
732 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
733 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
734 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
737 /* The command isn't understood by this engine */
739 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
740 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
748 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
749 UI_METHOD *ui_method, void *callback_data)
751 #ifndef OPENSSL_NO_RSA
754 EVP_PKEY *res = NULL;
755 #ifndef OPENSSL_NO_RSA
756 HWCryptoHook_MPI e, n;
757 HWCryptoHook_RSAKeyHandle *hptr;
759 #if !defined(OPENSSL_NO_RSA)
761 HWCryptoHook_ErrMsgBuf rmsg;
762 HWCryptoHook_PassphraseContext ppctx;
765 #if !defined(OPENSSL_NO_RSA)
767 rmsg.size = sizeof(tempbuf);
772 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
773 HWCRHK_R_NOT_INITIALISED);
776 #ifndef OPENSSL_NO_RSA
777 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
780 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
781 ERR_R_MALLOC_FAILURE);
784 ppctx.ui_method = ui_method;
785 ppctx.callback_data = callback_data;
786 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
789 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
790 HWCRHK_R_CHIL_ERROR);
791 ERR_add_error_data(1,rmsg.buf);
796 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
801 #ifndef OPENSSL_NO_RSA
802 rtmp = RSA_new_method(eng);
803 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
806 rtmp->flags |= RSA_FLAG_EXT_PKEY;
809 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
810 != HWCRYPTOHOOK_ERROR_MPISIZE)
812 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,HWCRHK_R_CHIL_ERROR);
813 ERR_add_error_data(1,rmsg.buf);
817 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
818 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
822 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
824 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
825 HWCRHK_R_CHIL_ERROR);
826 ERR_add_error_data(1,rmsg.buf);
829 rtmp->e->top = e.size / sizeof(BN_ULONG);
831 rtmp->n->top = n.size / sizeof(BN_ULONG);
834 res = EVP_PKEY_new();
835 EVP_PKEY_assign_RSA(res, rtmp);
839 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
840 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
844 #ifndef OPENSSL_NO_RSA
851 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
852 UI_METHOD *ui_method, void *callback_data)
854 EVP_PKEY *res = NULL;
856 #ifndef OPENSSL_NO_RSA
857 res = hwcrhk_load_privkey(eng, key_id,
858 ui_method, callback_data);
864 #ifndef OPENSSL_NO_RSA
869 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
871 res->pkey.rsa = RSA_new();
872 res->pkey.rsa->n = rsa->n;
873 res->pkey.rsa->e = rsa->e;
876 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
882 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
883 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
894 /* A little mod_exp */
895 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
896 const BIGNUM *m, BN_CTX *ctx)
899 HWCryptoHook_ErrMsgBuf rmsg;
900 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
901 we use them directly, plus a little macro magic. We only
902 thing we need to make sure of is that enough space is allocated. */
903 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
906 to_return = 0; /* expect failure */
908 rmsg.size = sizeof(tempbuf);
912 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
915 /* Prepare the params */
916 bn_expand2(r, m->top); /* Check for error !! */
922 /* Perform the operation */
923 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
925 /* Convert the response */
926 r->top = m_r.size / sizeof(BN_ULONG);
931 /* FIXME: When this error is returned, HWCryptoHook is
932 telling us that falling back to software computation
933 might be a good thing. */
934 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
936 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
940 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
942 ERR_add_error_data(1,rmsg.buf);
951 #ifndef OPENSSL_NO_RSA
952 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
955 HWCryptoHook_ErrMsgBuf rmsg;
956 HWCryptoHook_RSAKeyHandle *hptr;
957 int to_return = 0, ret;
960 rmsg.size = sizeof(tempbuf);
964 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
968 /* This provides support for nForce keys. Since that's opaque data
969 all we do is provide a handle to the proper key and let HWCryptoHook
970 take care of the rest. */
971 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
974 HWCryptoHook_MPI m_a, m_r;
978 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
979 HWCRHK_R_MISSING_KEY_COMPONENTS);
983 /* Prepare the params */
984 bn_expand2(r, rsa->n->top); /* Check for error !! */
988 /* Perform the operation */
989 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
991 /* Convert the response */
992 r->top = m_r.size / sizeof(BN_ULONG);
997 /* FIXME: When this error is returned, HWCryptoHook is
998 telling us that falling back to software computation
999 might be a good thing. */
1000 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1002 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1003 HWCRHK_R_REQUEST_FALLBACK);
1007 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1008 HWCRHK_R_REQUEST_FAILED);
1010 ERR_add_error_data(1,rmsg.buf);
1016 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1018 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1020 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1021 HWCRHK_R_MISSING_KEY_COMPONENTS);
1025 /* Prepare the params */
1026 bn_expand2(r, rsa->n->top); /* Check for error !! */
1028 BN2MPI(m_p, rsa->p);
1029 BN2MPI(m_q, rsa->q);
1030 BN2MPI(m_dmp1, rsa->dmp1);
1031 BN2MPI(m_dmq1, rsa->dmq1);
1032 BN2MPI(m_iqmp, rsa->iqmp);
1035 /* Perform the operation */
1036 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1037 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1039 /* Convert the response */
1040 r->top = m_r.size / sizeof(BN_ULONG);
1045 /* FIXME: When this error is returned, HWCryptoHook is
1046 telling us that falling back to software computation
1047 might be a good thing. */
1048 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1050 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1051 HWCRHK_R_REQUEST_FALLBACK);
1055 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1056 HWCRHK_R_REQUEST_FAILED);
1058 ERR_add_error_data(1,rmsg.buf);
1062 /* If we're here, we must be here with some semblance of success :-) */
1069 #ifndef OPENSSL_NO_RSA
1070 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1071 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1072 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1074 return hwcrhk_mod_exp(r, a, p, m, ctx);
1077 static int hwcrhk_rsa_finish(RSA *rsa)
1079 HWCryptoHook_RSAKeyHandle *hptr;
1081 hptr = RSA_get_ex_data(rsa, hndidx_rsa);
1084 p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1086 RSA_set_ex_data(rsa, hndidx_rsa, NULL);
1093 #ifndef OPENSSL_NO_DH
1094 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1095 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1096 const BIGNUM *a, const BIGNUM *p,
1097 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1099 return hwcrhk_mod_exp(r, a, p, m, ctx);
1103 /* Random bytes are good */
1104 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1107 HWCryptoHook_ErrMsgBuf rmsg;
1108 int to_return = 0; /* assume failure */
1112 rmsg.size = sizeof(tempbuf);
1116 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1120 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1123 /* FIXME: When this error is returned, HWCryptoHook is
1124 telling us that falling back to software computation
1125 might be a good thing. */
1126 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1128 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1129 HWCRHK_R_REQUEST_FALLBACK);
1133 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1134 HWCRHK_R_REQUEST_FAILED);
1136 ERR_add_error_data(1,rmsg.buf);
1144 static int hwcrhk_rand_status(void)
1149 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1150 * these just wrap the POSIX functions and add some logging.
1153 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1154 HWCryptoHook_CallerContext *cactx)
1156 mt->lockid = CRYPTO_get_new_dynlockid();
1157 if (mt->lockid == 0)
1158 return 1; /* failure */
1159 return 0; /* success */
1162 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1164 CRYPTO_w_lock(mt->lockid);
1168 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1170 CRYPTO_w_unlock(mt->lockid);
1173 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1175 CRYPTO_destroy_dynlockid(mt->lockid);
1178 static int hwcrhk_get_pass(const char *prompt_info,
1179 int *len_io, char *buf,
1180 HWCryptoHook_PassphraseContext *ppctx,
1181 HWCryptoHook_CallerContext *cactx)
1183 pem_password_cb *callback = NULL;
1184 void *callback_data = NULL;
1185 UI_METHOD *ui_method = NULL;
1186 /* Despite what the documentation says prompt_info can be
1189 if (prompt_info && !*prompt_info)
1194 if (cactx->ui_method)
1195 ui_method = cactx->ui_method;
1196 if (cactx->password_callback)
1197 callback = cactx->password_callback;
1198 if (cactx->callback_data)
1199 callback_data = cactx->callback_data;
1203 if (ppctx->ui_method)
1205 ui_method = ppctx->ui_method;
1208 if (ppctx->callback_data)
1209 callback_data = ppctx->callback_data;
1211 if (callback == NULL && ui_method == NULL)
1213 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1219 UI *ui = UI_new_method(ui_method);
1223 char *prompt = UI_construct_prompt(ui,
1224 "pass phrase", prompt_info);
1226 ok = UI_add_input_string(ui,prompt,
1227 UI_INPUT_FLAG_DEFAULT_PWD,
1228 buf,0,(*len_io) - 1);
1229 UI_add_user_data(ui, callback_data);
1230 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1237 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1240 *len_io = strlen(buf);
1243 OPENSSL_free(prompt);
1248 *len_io = callback(buf, *len_io, 0, callback_data);
1255 static int hwcrhk_insert_card(const char *prompt_info,
1256 const char *wrong_info,
1257 HWCryptoHook_PassphraseContext *ppctx,
1258 HWCryptoHook_CallerContext *cactx)
1262 void *callback_data = NULL;
1263 UI_METHOD *ui_method = NULL;
1267 if (cactx->ui_method)
1268 ui_method = cactx->ui_method;
1269 if (cactx->callback_data)
1270 callback_data = cactx->callback_data;
1274 if (ppctx->ui_method)
1275 ui_method = ppctx->ui_method;
1276 if (ppctx->callback_data)
1277 callback_data = ppctx->callback_data;
1279 if (ui_method == NULL)
1281 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1282 HWCRHK_R_NO_CALLBACK);
1286 ui = UI_new_method(ui_method);
1292 /* Despite what the documentation says wrong_info can be
1295 if (wrong_info && *wrong_info)
1296 BIO_snprintf(buf, sizeof(buf)-1,
1297 "Current card: \"%s\"\n", wrong_info);
1300 ok = UI_dup_info_string(ui, buf);
1301 if (ok >= 0 && prompt_info)
1303 BIO_snprintf(buf, sizeof(buf)-1,
1304 "Insert card \"%s\"", prompt_info);
1305 ok = UI_dup_input_boolean(ui, buf,
1306 "\n then hit <enter> or C<enter> to cancel\n",
1307 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1309 UI_add_user_data(ui, callback_data);
1312 ok = UI_process(ui);
1315 if (ok == -2 || (ok >= 0 && answer == 'C'))
1325 static void hwcrhk_log_message(void *logstr, const char *message)
1327 BIO *lstream = NULL;
1329 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1331 lstream=*(BIO **)logstr;
1334 BIO_printf(lstream, "%s\n", message);
1336 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1339 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1340 * shared-library. */
1341 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1342 static int bind_fn(ENGINE *e, const char *id)
1344 if(id && (strcmp(id, engine_hwcrhk_id) != 0) &&
1345 (strcmp(id, engine_hwcrhk_id_alt) != 0))
1351 IMPLEMENT_DYNAMIC_CHECK_FN()
1352 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1353 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1355 #endif /* !OPENSSL_NO_HW_CHIL */
1356 #endif /* !OPENSSL_NO_HW */