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";
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 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
425 /* These are the function pointers that are (un)set when the library has
426 * successfully (un)loaded. */
427 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
428 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
429 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
430 #ifndef OPENSSL_NO_RSA
431 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
433 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
434 #ifndef OPENSSL_NO_RSA
435 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
436 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
437 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
439 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
441 /* Used in the DSO operations. */
442 static const char *HWCRHK_LIBNAME = NULL;
443 static void free_HWCRHK_LIBNAME(void)
446 OPENSSL_free((void*)HWCRHK_LIBNAME);
447 HWCRHK_LIBNAME = NULL;
449 static const char *get_HWCRHK_LIBNAME(void)
452 return HWCRHK_LIBNAME;
455 static long set_HWCRHK_LIBNAME(const char *name)
457 free_HWCRHK_LIBNAME();
458 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
460 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
461 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
462 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
463 #ifndef OPENSSL_NO_RSA
464 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
466 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
467 #ifndef OPENSSL_NO_RSA
468 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
469 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
470 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
472 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
474 /* HWCryptoHook library functions and mechanics - these are used by the
475 * higher-level functions further down. NB: As and where there's no
476 * error checking, take a look lower down where these functions are
477 * called, the checking and error handling is probably down there. */
479 /* utility function to obtain a context */
480 static int get_context(HWCryptoHook_ContextHandle *hac,
481 HWCryptoHook_CallerContext *cac)
484 HWCryptoHook_ErrMsgBuf rmsg;
487 rmsg.size = sizeof(tempbuf);
489 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
496 /* similarly to release one. */
497 static void release_context(HWCryptoHook_ContextHandle hac)
499 p_hwcrhk_Finish(hac);
502 /* Destructor (complements the "ENGINE_chil()" constructor) */
503 static int hwcrhk_destroy(ENGINE *e)
505 free_HWCRHK_LIBNAME();
506 ERR_unload_HWCRHK_strings();
510 /* (de)initialisation functions. */
511 static int hwcrhk_init(ENGINE *e)
513 HWCryptoHook_Init_t *p1;
514 HWCryptoHook_Finish_t *p2;
515 HWCryptoHook_ModExp_t *p3;
516 #ifndef OPENSSL_NO_RSA
517 HWCryptoHook_RSA_t *p4;
518 HWCryptoHook_RSALoadKey_t *p5;
519 HWCryptoHook_RSAGetPublicKey_t *p6;
520 HWCryptoHook_RSAUnloadKey_t *p7;
522 HWCryptoHook_RandomBytes_t *p8;
523 HWCryptoHook_ModExpCRT_t *p9;
525 if(hwcrhk_dso != NULL)
527 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
530 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
531 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
532 if(hwcrhk_dso == NULL)
534 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
537 if(!(p1 = (HWCryptoHook_Init_t *)
538 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
539 !(p2 = (HWCryptoHook_Finish_t *)
540 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
541 !(p3 = (HWCryptoHook_ModExp_t *)
542 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
543 #ifndef OPENSSL_NO_RSA
544 !(p4 = (HWCryptoHook_RSA_t *)
545 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
546 !(p5 = (HWCryptoHook_RSALoadKey_t *)
547 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
548 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
549 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
550 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
551 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
553 !(p8 = (HWCryptoHook_RandomBytes_t *)
554 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
555 !(p9 = (HWCryptoHook_ModExpCRT_t *)
556 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
558 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
561 /* Copy the pointers */
563 p_hwcrhk_Finish = p2;
564 p_hwcrhk_ModExp = p3;
565 #ifndef OPENSSL_NO_RSA
567 p_hwcrhk_RSALoadKey = p5;
568 p_hwcrhk_RSAGetPublicKey = p6;
569 p_hwcrhk_RSAUnloadKey = p7;
571 p_hwcrhk_RandomBytes = p8;
572 p_hwcrhk_ModExpCRT = p9;
574 /* Check if the application decided to support dynamic locks,
575 and if it does, use them. */
576 if (disable_mutex_callbacks == 0)
578 if (CRYPTO_get_dynlock_create_callback() != NULL &&
579 CRYPTO_get_dynlock_lock_callback() != NULL &&
580 CRYPTO_get_dynlock_destroy_callback() != NULL)
582 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
583 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
584 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
585 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
589 /* Try and get a context - if not, we may have a DSO but no
591 if(!get_context(&hwcrhk_context, &password_context))
593 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
596 /* Everything's fine. */
597 #ifndef OPENSSL_NO_RSA
598 if (hndidx_rsa == -1)
599 hndidx_rsa = RSA_get_ex_new_index(0,
600 "nFast HWCryptoHook RSA key handle",
606 DSO_free(hwcrhk_dso);
608 p_hwcrhk_Init = NULL;
609 p_hwcrhk_Finish = NULL;
610 p_hwcrhk_ModExp = NULL;
611 #ifndef OPENSSL_NO_RSA
613 p_hwcrhk_RSALoadKey = NULL;
614 p_hwcrhk_RSAGetPublicKey = NULL;
615 p_hwcrhk_RSAUnloadKey = NULL;
617 p_hwcrhk_ModExpCRT = NULL;
618 p_hwcrhk_RandomBytes = NULL;
622 static int hwcrhk_finish(ENGINE *e)
625 free_HWCRHK_LIBNAME();
626 if(hwcrhk_dso == NULL)
628 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
632 release_context(hwcrhk_context);
633 if(!DSO_free(hwcrhk_dso))
635 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
643 p_hwcrhk_Init = NULL;
644 p_hwcrhk_Finish = NULL;
645 p_hwcrhk_ModExp = NULL;
646 #ifndef OPENSSL_NO_RSA
648 p_hwcrhk_RSALoadKey = NULL;
649 p_hwcrhk_RSAGetPublicKey = NULL;
650 p_hwcrhk_RSAUnloadKey = NULL;
652 p_hwcrhk_ModExpCRT = NULL;
653 p_hwcrhk_RandomBytes = NULL;
657 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
663 case HWCRHK_CMD_SO_PATH:
666 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
671 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
674 return set_HWCRHK_LIBNAME((const char *)p);
675 case ENGINE_CTRL_SET_LOGSTREAM:
679 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
685 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
688 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
690 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
692 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
693 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
694 password_context.password_callback = (pem_password_cb *)f;
695 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
697 case ENGINE_CTRL_SET_USER_INTERFACE:
698 case HWCRHK_CMD_SET_USER_INTERFACE:
699 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
700 password_context.ui_method = (UI_METHOD *)p;
701 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
703 case ENGINE_CTRL_SET_CALLBACK_DATA:
704 case HWCRHK_CMD_SET_CALLBACK_DATA:
705 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
706 password_context.callback_data = p;
707 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
709 /* this enables or disables the "SimpleForkCheck" flag used in the
710 * initialisation structure. */
711 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
712 case HWCRHK_CMD_FORK_CHECK:
713 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
715 hwcrhk_globals.flags |=
716 HWCryptoHook_InitFlags_SimpleForkCheck;
718 hwcrhk_globals.flags &=
719 ~HWCryptoHook_InitFlags_SimpleForkCheck;
720 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
722 /* This will prevent the initialisation function from "installing"
723 * the mutex-handling callbacks, even if they are available from
724 * within the library (or were provided to the library from the
725 * calling application). This is to remove any baggage for
726 * applications not using multithreading. */
727 case ENGINE_CTRL_CHIL_NO_LOCKING:
728 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
729 disable_mutex_callbacks = 1;
730 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
732 case HWCRHK_CMD_THREAD_LOCKING:
733 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
734 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
735 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
738 /* The command isn't understood by this engine */
740 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
741 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
749 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
750 UI_METHOD *ui_method, void *callback_data)
752 #ifndef OPENSSL_NO_RSA
755 EVP_PKEY *res = NULL;
756 #ifndef OPENSSL_NO_RSA
757 HWCryptoHook_MPI e, n;
758 HWCryptoHook_RSAKeyHandle *hptr;
760 #if !defined(OPENSSL_NO_RSA)
762 HWCryptoHook_ErrMsgBuf rmsg;
763 HWCryptoHook_PassphraseContext ppctx;
766 #if !defined(OPENSSL_NO_RSA)
768 rmsg.size = sizeof(tempbuf);
773 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
774 HWCRHK_R_NOT_INITIALISED);
777 #ifndef OPENSSL_NO_RSA
778 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
781 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
782 ERR_R_MALLOC_FAILURE);
785 ppctx.ui_method = ui_method;
786 ppctx.callback_data = callback_data;
787 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
790 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
791 HWCRHK_R_CHIL_ERROR);
792 ERR_add_error_data(1,rmsg.buf);
797 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
802 #ifndef OPENSSL_NO_RSA
803 rtmp = RSA_new_method(eng);
804 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
807 rtmp->flags |= RSA_FLAG_EXT_PKEY;
810 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
811 != HWCRYPTOHOOK_ERROR_MPISIZE)
813 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,HWCRHK_R_CHIL_ERROR);
814 ERR_add_error_data(1,rmsg.buf);
818 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
819 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
823 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
825 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
826 HWCRHK_R_CHIL_ERROR);
827 ERR_add_error_data(1,rmsg.buf);
830 rtmp->e->top = e.size / sizeof(BN_ULONG);
832 rtmp->n->top = n.size / sizeof(BN_ULONG);
835 res = EVP_PKEY_new();
836 EVP_PKEY_assign_RSA(res, rtmp);
840 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
841 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
847 #ifndef OPENSSL_NO_RSA
854 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
855 UI_METHOD *ui_method, void *callback_data)
857 EVP_PKEY *res = NULL;
859 #ifndef OPENSSL_NO_RSA
860 res = hwcrhk_load_privkey(eng, key_id,
861 ui_method, callback_data);
867 #ifndef OPENSSL_NO_RSA
872 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
874 res->pkey.rsa = RSA_new();
875 res->pkey.rsa->n = rsa->n;
876 res->pkey.rsa->e = rsa->e;
879 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
885 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
886 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
897 /* A little mod_exp */
898 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
899 const BIGNUM *m, BN_CTX *ctx)
902 HWCryptoHook_ErrMsgBuf rmsg;
903 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
904 we use them directly, plus a little macro magic. We only
905 thing we need to make sure of is that enough space is allocated. */
906 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
909 to_return = 0; /* expect failure */
911 rmsg.size = sizeof(tempbuf);
915 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
918 /* Prepare the params */
919 bn_expand2(r, m->top); /* Check for error !! */
925 /* Perform the operation */
926 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
928 /* Convert the response */
929 r->top = m_r.size / sizeof(BN_ULONG);
934 /* FIXME: When this error is returned, HWCryptoHook is
935 telling us that falling back to software computation
936 might be a good thing. */
937 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
939 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
943 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
945 ERR_add_error_data(1,rmsg.buf);
954 #ifndef OPENSSL_NO_RSA
955 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
958 HWCryptoHook_ErrMsgBuf rmsg;
959 HWCryptoHook_RSAKeyHandle *hptr;
960 int to_return = 0, ret;
963 rmsg.size = sizeof(tempbuf);
967 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
971 /* This provides support for nForce keys. Since that's opaque data
972 all we do is provide a handle to the proper key and let HWCryptoHook
973 take care of the rest. */
974 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
977 HWCryptoHook_MPI m_a, m_r;
981 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
982 HWCRHK_R_MISSING_KEY_COMPONENTS);
986 /* Prepare the params */
987 bn_expand2(r, rsa->n->top); /* Check for error !! */
991 /* Perform the operation */
992 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
994 /* Convert the response */
995 r->top = m_r.size / sizeof(BN_ULONG);
1000 /* FIXME: When this error is returned, HWCryptoHook is
1001 telling us that falling back to software computation
1002 might be a good thing. */
1003 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1005 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1006 HWCRHK_R_REQUEST_FALLBACK);
1010 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1011 HWCRHK_R_REQUEST_FAILED);
1013 ERR_add_error_data(1,rmsg.buf);
1019 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1021 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1023 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1024 HWCRHK_R_MISSING_KEY_COMPONENTS);
1028 /* Prepare the params */
1029 bn_expand2(r, rsa->n->top); /* Check for error !! */
1031 BN2MPI(m_p, rsa->p);
1032 BN2MPI(m_q, rsa->q);
1033 BN2MPI(m_dmp1, rsa->dmp1);
1034 BN2MPI(m_dmq1, rsa->dmq1);
1035 BN2MPI(m_iqmp, rsa->iqmp);
1038 /* Perform the operation */
1039 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1040 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1042 /* Convert the response */
1043 r->top = m_r.size / sizeof(BN_ULONG);
1048 /* FIXME: When this error is returned, HWCryptoHook is
1049 telling us that falling back to software computation
1050 might be a good thing. */
1051 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1053 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1054 HWCRHK_R_REQUEST_FALLBACK);
1058 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1059 HWCRHK_R_REQUEST_FAILED);
1061 ERR_add_error_data(1,rmsg.buf);
1065 /* If we're here, we must be here with some semblance of success :-) */
1072 #ifndef OPENSSL_NO_RSA
1073 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1074 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1075 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1077 return hwcrhk_mod_exp(r, a, p, m, ctx);
1080 static int hwcrhk_rsa_finish(RSA *rsa)
1082 HWCryptoHook_RSAKeyHandle *hptr;
1084 hptr = RSA_get_ex_data(rsa, hndidx_rsa);
1087 p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1089 RSA_set_ex_data(rsa, hndidx_rsa, NULL);
1096 #ifndef OPENSSL_NO_DH
1097 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1098 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1099 const BIGNUM *a, const BIGNUM *p,
1100 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1102 return hwcrhk_mod_exp(r, a, p, m, ctx);
1106 /* Random bytes are good */
1107 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1110 HWCryptoHook_ErrMsgBuf rmsg;
1111 int to_return = 0; /* assume failure */
1115 rmsg.size = sizeof(tempbuf);
1119 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1123 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1126 /* FIXME: When this error is returned, HWCryptoHook is
1127 telling us that falling back to software computation
1128 might be a good thing. */
1129 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1131 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1132 HWCRHK_R_REQUEST_FALLBACK);
1136 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1137 HWCRHK_R_REQUEST_FAILED);
1139 ERR_add_error_data(1,rmsg.buf);
1147 static int hwcrhk_rand_status(void)
1152 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1153 * these just wrap the POSIX functions and add some logging.
1156 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1157 HWCryptoHook_CallerContext *cactx)
1159 mt->lockid = CRYPTO_get_new_dynlockid();
1160 if (mt->lockid == 0)
1161 return 1; /* failure */
1162 return 0; /* success */
1165 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1167 CRYPTO_w_lock(mt->lockid);
1171 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1173 CRYPTO_w_unlock(mt->lockid);
1176 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1178 CRYPTO_destroy_dynlockid(mt->lockid);
1181 static int hwcrhk_get_pass(const char *prompt_info,
1182 int *len_io, char *buf,
1183 HWCryptoHook_PassphraseContext *ppctx,
1184 HWCryptoHook_CallerContext *cactx)
1186 pem_password_cb *callback = NULL;
1187 void *callback_data = NULL;
1188 UI_METHOD *ui_method = NULL;
1189 /* Despite what the documentation says prompt_info can be
1192 if (prompt_info && !*prompt_info)
1197 if (cactx->ui_method)
1198 ui_method = cactx->ui_method;
1199 if (cactx->password_callback)
1200 callback = cactx->password_callback;
1201 if (cactx->callback_data)
1202 callback_data = cactx->callback_data;
1206 if (ppctx->ui_method)
1208 ui_method = ppctx->ui_method;
1211 if (ppctx->callback_data)
1212 callback_data = ppctx->callback_data;
1214 if (callback == NULL && ui_method == NULL)
1216 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1222 UI *ui = UI_new_method(ui_method);
1226 char *prompt = UI_construct_prompt(ui,
1227 "pass phrase", prompt_info);
1229 ok = UI_add_input_string(ui,prompt,
1230 UI_INPUT_FLAG_DEFAULT_PWD,
1231 buf,0,(*len_io) - 1);
1232 UI_add_user_data(ui, callback_data);
1233 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1240 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1243 *len_io = strlen(buf);
1246 OPENSSL_free(prompt);
1251 *len_io = callback(buf, *len_io, 0, callback_data);
1258 static int hwcrhk_insert_card(const char *prompt_info,
1259 const char *wrong_info,
1260 HWCryptoHook_PassphraseContext *ppctx,
1261 HWCryptoHook_CallerContext *cactx)
1265 void *callback_data = NULL;
1266 UI_METHOD *ui_method = NULL;
1270 if (cactx->ui_method)
1271 ui_method = cactx->ui_method;
1272 if (cactx->callback_data)
1273 callback_data = cactx->callback_data;
1277 if (ppctx->ui_method)
1278 ui_method = ppctx->ui_method;
1279 if (ppctx->callback_data)
1280 callback_data = ppctx->callback_data;
1282 if (ui_method == NULL)
1284 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1285 HWCRHK_R_NO_CALLBACK);
1289 ui = UI_new_method(ui_method);
1295 /* Despite what the documentation says wrong_info can be
1298 if (wrong_info && *wrong_info)
1299 BIO_snprintf(buf, sizeof(buf)-1,
1300 "Current card: \"%s\"\n", wrong_info);
1303 ok = UI_dup_info_string(ui, buf);
1304 if (ok >= 0 && prompt_info)
1306 BIO_snprintf(buf, sizeof(buf)-1,
1307 "Insert card \"%s\"", prompt_info);
1308 ok = UI_dup_input_boolean(ui, buf,
1309 "\n then hit <enter> or C<enter> to cancel\n",
1310 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1312 UI_add_user_data(ui, callback_data);
1315 ok = UI_process(ui);
1318 if (ok == -2 || (ok >= 0 && answer == 'C'))
1328 static void hwcrhk_log_message(void *logstr, const char *message)
1330 BIO *lstream = NULL;
1332 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1334 lstream=*(BIO **)logstr;
1337 BIO_printf(lstream, "%s\n", message);
1339 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1342 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1343 * shared-library. */
1344 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1345 static int bind_fn(ENGINE *e, const char *id)
1347 if(id && (strcmp(id, engine_hwcrhk_id) != 0) &&
1348 (strcmp(id, engine_hwcrhk_id_alt) != 0))
1354 IMPLEMENT_DYNAMIC_CHECK_FN()
1355 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1356 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1358 #endif /* !OPENSSL_NO_HW_CHIL */
1359 #endif /* !OPENSSL_NO_HW */