2 * Written by Richard Levitte (richard@levitte.org), Geoff Thorpe
3 * (geoff@geoffthorpe.net) and Dr Stephen N Henson (steve@openssl.org) for
4 * 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 *,
104 HWCryptoHook_CallerContext *);
105 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *);
106 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex *);
107 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *);
110 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
111 const BIGNUM *m, BN_CTX *ctx);
113 # ifndef OPENSSL_NO_RSA
115 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa,
117 /* This function is aliased to mod_exp (with the mont stuff dropped). */
118 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
119 const BIGNUM *m, BN_CTX *ctx,
121 static int hwcrhk_rsa_finish(RSA *rsa);
124 # ifndef OPENSSL_NO_DH
126 /* This function is alised to mod_exp (with the DH and mont dropped). */
127 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
128 const BIGNUM *a, const BIGNUM *p,
129 const BIGNUM *m, BN_CTX *ctx,
134 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
135 static int hwcrhk_rand_status(void);
138 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
139 UI_METHOD *ui_method,
140 void *callback_data);
141 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
142 UI_METHOD *ui_method,
143 void *callback_data);
145 /* Interaction stuff */
146 static int hwcrhk_insert_card(const char *prompt_info,
147 const char *wrong_info,
148 HWCryptoHook_PassphraseContext * ppctx,
149 HWCryptoHook_CallerContext * cactx);
150 static int hwcrhk_get_pass(const char *prompt_info,
151 int *len_io, char *buf,
152 HWCryptoHook_PassphraseContext * ppctx,
153 HWCryptoHook_CallerContext * cactx);
154 static void hwcrhk_log_message(void *logstr, const char *message);
156 /* The definitions for control commands specific to this engine */
157 # define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
158 # define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
159 # define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
160 # define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
161 # define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
162 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
165 "Specifies the path to the 'hwcrhk' shared library",
166 ENGINE_CMD_FLAG_STRING},
167 {HWCRHK_CMD_FORK_CHECK,
169 "Turns fork() checking on (non-zero) or off (zero)",
170 ENGINE_CMD_FLAG_NUMERIC},
171 {HWCRHK_CMD_THREAD_LOCKING,
173 "Turns thread-safe locking on (zero) or off (non-zero)",
174 ENGINE_CMD_FLAG_NUMERIC},
175 {HWCRHK_CMD_SET_USER_INTERFACE,
176 "SET_USER_INTERFACE",
177 "Set the global user interface (internal)",
178 ENGINE_CMD_FLAG_INTERNAL},
179 {HWCRHK_CMD_SET_CALLBACK_DATA,
181 "Set the global user interface extra data (internal)",
182 ENGINE_CMD_FLAG_INTERNAL},
186 # ifndef OPENSSL_NO_RSA
187 /* Our internal RSA_METHOD that we provide pointers to */
188 static RSA_METHOD hwcrhk_rsa = {
206 # ifndef OPENSSL_NO_DH
207 /* Our internal DH_METHOD that we provide pointers to */
208 static DH_METHOD hwcrhk_dh = {
221 static RAND_METHOD hwcrhk_rand = {
222 /* "CHIL RAND method", */
231 /* Constants used when creating the ENGINE */
232 static const char *engine_hwcrhk_id = "chil";
233 static const char *engine_hwcrhk_name = "CHIL hardware engine support";
234 # ifndef OPENSSL_NO_DYNAMIC_ENGINE
235 /* Compatibility hack, the dynamic library uses this form in the path */
236 static const char *engine_hwcrhk_id_alt = "ncipher";
239 /* Internal stuff for HWCryptoHook */
241 /* Some structures needed for proper use of thread locks */
243 * hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
244 * into HWCryptoHook_Mutex
246 struct HWCryptoHook_MutexValue {
251 * hwcryptohook.h has some typedefs that turn struct
252 * HWCryptoHook_PassphraseContextValue into HWCryptoHook_PassphraseContext
254 struct HWCryptoHook_PassphraseContextValue {
255 UI_METHOD *ui_method;
260 * hwcryptohook.h has some typedefs that turn struct
261 * HWCryptoHook_CallerContextValue into HWCryptoHook_CallerContext
263 struct HWCryptoHook_CallerContextValue {
264 pem_password_cb *password_callback; /* Deprecated! Only present for
265 * backward compatibility! */
266 UI_METHOD *ui_method;
271 * The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
272 * BIGNUM's, so lets define a couple of conversion macros
274 # define BN2MPI(mp, bn) \
275 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
276 # define MPI2BN(bn, mp) \
277 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
279 static BIO *logstream = NULL;
280 static int disable_mutex_callbacks = 0;
283 * One might wonder why these are needed, since one can pass down at least a
284 * UI_METHOD and a pointer to callback data to the key-loading functions. The
285 * thing is that the ModExp and RSAImmed functions can load keys as well, if
286 * the data they get is in a special, nCipher-defined format (hint: if you
287 * look at the private exponent of the RSA data as a string, you'll see this
288 * string: "nCipher KM tool key id", followed by some bytes, followed a key
289 * identity string, followed by more bytes. This happens when you use
290 * "embed" keys instead of "hwcrhk" keys). Unfortunately, those functions do
291 * not take any passphrase or caller context, and our functions can't really
292 * take any callback data either. Still, the "insert_card" and
293 * "get_passphrase" callbacks may be called down the line, and will need to
294 * know what user interface callbacks to call, and having callback data from
295 * the application may be a nice thing as well, so we need to keep track of
298 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
300 /* Stuff to pass to the HWCryptoHook library */
301 static HWCryptoHook_InitInfo hwcrhk_globals = {
302 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
303 &logstream, /* logstream */
304 sizeof(BN_ULONG), /* limbsize */
305 0, /* mslimb first: false for BNs */
306 -1, /* msbyte first: use native */
307 0, /* Max mutexes, 0 = no small limit */
308 0, /* Max simultaneous, 0 = default */
311 * The next few are mutex stuff: we write wrapper functions around the OS
312 * mutex functions. We initialise them to 0 here, and change that to
313 * actual function pointers in hwcrhk_init() if dynamic locks are
314 * supported (that is, if the application programmer has made sure of
315 * setting up callbacks bafore starting this engine) *and* if
316 * disable_mutex_callbacks hasn't been set by a call to
317 * ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING).
319 sizeof(HWCryptoHook_Mutex),
326 * The next few are condvar stuff: we write wrapper functions round the
327 * OS functions. Currently not implemented and not and absolute
328 * necessity even in threaded programs, therefore 0'ed. Will hopefully
329 * be implemented some day, since it enhances the efficiency of
332 0, /* sizeof(HWCryptoHook_CondVar), */
333 0, /* hwcrhk_cv_init, */
334 0, /* hwcrhk_cv_wait, */
335 0, /* hwcrhk_cv_signal, */
336 0, /* hwcrhk_cv_broadcast, */
337 0, /* hwcrhk_cv_destroy, */
339 hwcrhk_get_pass, /* pass phrase */
340 hwcrhk_insert_card, /* insert a card */
341 hwcrhk_log_message /* Log message */
344 /* Now, to our own code */
347 * This internal function is used by ENGINE_chil() and possibly by the
348 * "dynamic" ENGINE support too
350 static int bind_helper(ENGINE *e)
352 # ifndef OPENSSL_NO_RSA
353 const RSA_METHOD *meth1;
355 # ifndef OPENSSL_NO_DH
356 const DH_METHOD *meth2;
358 if (!ENGINE_set_id(e, engine_hwcrhk_id) ||
359 !ENGINE_set_name(e, engine_hwcrhk_name) ||
360 # ifndef OPENSSL_NO_RSA
361 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
363 # ifndef OPENSSL_NO_DH
364 !ENGINE_set_DH(e, &hwcrhk_dh) ||
366 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
367 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
368 !ENGINE_set_init_function(e, hwcrhk_init) ||
369 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
370 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
371 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
372 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
373 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
376 # ifndef OPENSSL_NO_RSA
378 * We know that the "PKCS1_OpenSSL()" functions hook properly to the
379 * cswift-specific mod_exp and mod_exp_crt so we use those functions. NB:
380 * We don't use ENGINE_openssl() or anything "more generic" because
381 * something like the RSAref code may not hook properly, and if you own
382 * one of these cards then you have the right to do RSA operations on it
385 meth1 = RSA_PKCS1_OpenSSL();
386 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
387 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
388 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
389 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
392 # ifndef OPENSSL_NO_DH
393 /* Much the same for Diffie-Hellman */
394 meth2 = DH_OpenSSL();
395 hwcrhk_dh.generate_key = meth2->generate_key;
396 hwcrhk_dh.compute_key = meth2->compute_key;
399 /* Ensure the hwcrhk error handling is set up */
400 ERR_load_HWCRHK_strings();
404 # ifdef OPENSSL_NO_DYNAMIC_ENGINE
405 static ENGINE *engine_chil(void)
407 ENGINE *ret = ENGINE_new();
410 if (!bind_helper(ret)) {
417 void ENGINE_load_chil(void)
419 /* Copied from eng_[openssl|dyn].c */
420 ENGINE *toadd = engine_chil();
430 * This is a process-global DSO handle used for loading and unloading the
431 * HWCryptoHook library. NB: This is only set (or unset) during an init() or
432 * finish() call (reference counts permitting) and they're operating with
433 * global locks, so this should be thread-safe implicitly.
435 static DSO *hwcrhk_dso = NULL;
436 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
437 # ifndef OPENSSL_NO_RSA
438 /* Index for KM handle. Not really used yet. */
439 static int hndidx_rsa = -1;
443 * These are the function pointers that are (un)set when the library has
444 * successfully (un)loaded.
446 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
447 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
448 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
449 # ifndef OPENSSL_NO_RSA
450 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
452 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
453 # ifndef OPENSSL_NO_RSA
454 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
455 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
456 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
458 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
460 /* Used in the DSO operations. */
461 static const char *HWCRHK_LIBNAME = NULL;
462 static void free_HWCRHK_LIBNAME(void)
464 OPENSSL_free(HWCRHK_LIBNAME);
465 HWCRHK_LIBNAME = NULL;
468 static const char *get_HWCRHK_LIBNAME(void)
471 return HWCRHK_LIBNAME;
475 static long set_HWCRHK_LIBNAME(const char *name)
477 free_HWCRHK_LIBNAME();
478 return (((HWCRHK_LIBNAME = OPENSSL_strdup(name)) != NULL) ? 1 : 0);
481 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
482 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
483 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
484 # ifndef OPENSSL_NO_RSA
485 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
487 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
488 # ifndef OPENSSL_NO_RSA
489 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
490 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
491 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
493 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
496 * HWCryptoHook library functions and mechanics - these are used by the
497 * higher-level functions further down. NB: As and where there's no error
498 * checking, take a look lower down where these functions are called, the
499 * checking and error handling is probably down there.
502 /* utility function to obtain a context */
503 static int get_context(HWCryptoHook_ContextHandle * hac,
504 HWCryptoHook_CallerContext * cac)
507 HWCryptoHook_ErrMsgBuf rmsg;
510 rmsg.size = sizeof(tempbuf);
512 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg, cac);
518 /* similarly to release one. */
519 static void release_context(HWCryptoHook_ContextHandle hac)
521 p_hwcrhk_Finish(hac);
524 /* Destructor (complements the "ENGINE_chil()" constructor) */
525 static int hwcrhk_destroy(ENGINE *e)
527 free_HWCRHK_LIBNAME();
528 ERR_unload_HWCRHK_strings();
532 /* (de)initialisation functions. */
533 static int hwcrhk_init(ENGINE *e)
535 HWCryptoHook_Init_t *p1;
536 HWCryptoHook_Finish_t *p2;
537 HWCryptoHook_ModExp_t *p3;
538 # ifndef OPENSSL_NO_RSA
539 HWCryptoHook_RSA_t *p4;
540 HWCryptoHook_RSALoadKey_t *p5;
541 HWCryptoHook_RSAGetPublicKey_t *p6;
542 HWCryptoHook_RSAUnloadKey_t *p7;
544 HWCryptoHook_RandomBytes_t *p8;
545 HWCryptoHook_ModExpCRT_t *p9;
547 if (hwcrhk_dso != NULL) {
548 HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_ALREADY_LOADED);
551 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
552 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
553 if (hwcrhk_dso == NULL) {
554 HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE);
558 #define BINDIT(t, name) (t *)DSO_bind_func(hwcrhk_dso, name)
559 if ((p1 = BINDIT(HWCryptoHook_Init_t, n_hwcrhk_Init)) == NULL
560 || (p2 = BINDIT(HWCryptoHook_Finish_t, n_hwcrhk_Finish)) == NULL
561 || (p3 = BINDIT(HWCryptoHook_ModExp_t, n_hwcrhk_ModExp)) == NULL
562 # ifndef OPENSSL_NO_RSA
563 || (p4 = BINDIT(HWCryptoHook_RSA_t, n_hwcrhk_RSA)) == NULL
564 || (p5 = BINDIT(HWCryptoHook_RSALoadKey_t, n_hwcrhk_RSALoadKey)) == NULL
565 || (p6 = BINDIT(HWCryptoHook_RSAGetPublicKey_t, n_hwcrhk_RSAGetPublicKey)) == NULL
566 || (p7 = BINDIT(HWCryptoHook_RSAUnloadKey_t, n_hwcrhk_RSAUnloadKey)) == NULL
568 || (p8 = BINDIT(HWCryptoHook_RandomBytes_t, n_hwcrhk_RandomBytes)) == NULL
569 || (p9 = BINDIT(HWCryptoHook_ModExpCRT_t, n_hwcrhk_ModExpCRT)) == NULL) {
570 HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_DSO_FAILURE);
573 /* Copy the pointers */
575 p_hwcrhk_Finish = p2;
576 p_hwcrhk_ModExp = p3;
577 # ifndef OPENSSL_NO_RSA
579 p_hwcrhk_RSALoadKey = p5;
580 p_hwcrhk_RSAGetPublicKey = p6;
581 p_hwcrhk_RSAUnloadKey = p7;
583 p_hwcrhk_RandomBytes = p8;
584 p_hwcrhk_ModExpCRT = p9;
587 * Check if the application decided to support dynamic locks, and if it
590 if (disable_mutex_callbacks == 0) {
591 if (CRYPTO_get_dynlock_create_callback() != NULL &&
592 CRYPTO_get_dynlock_lock_callback() != NULL &&
593 CRYPTO_get_dynlock_destroy_callback() != NULL) {
594 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
595 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
596 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
597 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
602 * Try and get a context - if not, we may have a DSO but no accelerator!
604 if (!get_context(&hwcrhk_context, &password_context)) {
605 HWCRHKerr(HWCRHK_F_HWCRHK_INIT, HWCRHK_R_UNIT_FAILURE);
608 /* Everything's fine. */
609 # ifndef OPENSSL_NO_RSA
610 if (hndidx_rsa == -1)
611 hndidx_rsa = RSA_get_ex_new_index(0,
612 "nFast HWCryptoHook RSA key handle",
617 DSO_free(hwcrhk_dso);
619 p_hwcrhk_Init = NULL;
620 p_hwcrhk_Finish = NULL;
621 p_hwcrhk_ModExp = NULL;
622 # ifndef OPENSSL_NO_RSA
624 p_hwcrhk_RSALoadKey = NULL;
625 p_hwcrhk_RSAGetPublicKey = NULL;
626 p_hwcrhk_RSAUnloadKey = NULL;
628 p_hwcrhk_ModExpCRT = NULL;
629 p_hwcrhk_RandomBytes = NULL;
633 static int hwcrhk_finish(ENGINE *e)
636 free_HWCRHK_LIBNAME();
637 if (hwcrhk_dso == NULL) {
638 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_NOT_LOADED);
642 release_context(hwcrhk_context);
643 if (!DSO_free(hwcrhk_dso)) {
644 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH, HWCRHK_R_DSO_FAILURE);
651 p_hwcrhk_Init = NULL;
652 p_hwcrhk_Finish = NULL;
653 p_hwcrhk_ModExp = NULL;
654 # ifndef OPENSSL_NO_RSA
656 p_hwcrhk_RSALoadKey = NULL;
657 p_hwcrhk_RSAGetPublicKey = NULL;
658 p_hwcrhk_RSAUnloadKey = NULL;
660 p_hwcrhk_ModExpCRT = NULL;
661 p_hwcrhk_RandomBytes = NULL;
665 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
670 case HWCRHK_CMD_SO_PATH:
672 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_ALREADY_LOADED);
676 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, ERR_R_PASSED_NULL_PARAMETER);
679 return set_HWCRHK_LIBNAME((const char *)p);
680 case ENGINE_CTRL_SET_LOGSTREAM:
684 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
687 if (CRYPTO_add(&bio->references, 1, CRYPTO_LOCK_BIO) > 1)
690 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL, HWCRHK_R_BIO_WAS_FREED);
692 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
694 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
695 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
696 password_context.password_callback = (pem_password_cb *)f;
697 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
699 case ENGINE_CTRL_SET_USER_INTERFACE:
700 case HWCRHK_CMD_SET_USER_INTERFACE:
701 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
702 password_context.ui_method = (UI_METHOD *)p;
703 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
705 case ENGINE_CTRL_SET_CALLBACK_DATA:
706 case HWCRHK_CMD_SET_CALLBACK_DATA:
707 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
708 password_context.callback_data = p;
709 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
712 * this enables or disables the "SimpleForkCheck" flag used in the
713 * initialisation structure.
715 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
716 case HWCRHK_CMD_FORK_CHECK:
717 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
719 hwcrhk_globals.flags |= HWCryptoHook_InitFlags_SimpleForkCheck;
721 hwcrhk_globals.flags &= ~HWCryptoHook_InitFlags_SimpleForkCheck;
722 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
725 * This will prevent the initialisation function from "installing"
726 * the mutex-handling callbacks, even if they are available from
727 * within the library (or were provided to the library from the
728 * calling application). This is to remove any baggage for
729 * applications not using multithreading.
731 case ENGINE_CTRL_CHIL_NO_LOCKING:
732 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
733 disable_mutex_callbacks = 1;
734 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
736 case HWCRHK_CMD_THREAD_LOCKING:
737 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
738 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
739 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
742 /* The command isn't understood by this engine */
744 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
745 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
753 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
754 UI_METHOD *ui_method,
757 # ifndef OPENSSL_NO_RSA
760 EVP_PKEY *res = NULL;
761 # ifndef OPENSSL_NO_RSA
762 HWCryptoHook_MPI e, n;
763 HWCryptoHook_RSAKeyHandle *hptr;
765 # if !defined(OPENSSL_NO_RSA)
767 HWCryptoHook_ErrMsgBuf rmsg;
768 HWCryptoHook_PassphraseContext ppctx;
771 # if !defined(OPENSSL_NO_RSA)
773 rmsg.size = sizeof(tempbuf);
776 if (!hwcrhk_context) {
777 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NOT_INITIALISED);
780 # ifndef OPENSSL_NO_RSA
781 hptr = OPENSSL_malloc(sizeof(*hptr));
783 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, 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, &rmsg, &ppctx)) {
789 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
790 ERR_add_error_data(1, rmsg.buf);
794 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_NO_KEY);
798 # ifndef OPENSSL_NO_RSA
799 rtmp = RSA_new_method(eng);
800 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
803 rtmp->flags |= RSA_FLAG_EXT_PKEY;
806 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
807 != HWCRYPTOHOOK_ERROR_MPISIZE) {
808 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
809 ERR_add_error_data(1, rmsg.buf);
813 bn_expand2(rtmp->e, e.size / sizeof(BN_ULONG));
814 bn_expand2(rtmp->n, n.size / sizeof(BN_ULONG));
818 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)) {
819 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
820 ERR_add_error_data(1, rmsg.buf);
823 rtmp->e->top = e.size / sizeof(BN_ULONG);
825 rtmp->n->top = n.size / sizeof(BN_ULONG);
828 res = EVP_PKEY_new();
830 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY, HWCRHK_R_CHIL_ERROR);
833 EVP_PKEY_assign_RSA(res, rtmp);
837 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
838 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
842 # ifndef OPENSSL_NO_RSA
848 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
849 UI_METHOD *ui_method, void *callback_data)
851 EVP_PKEY *res = NULL;
853 # ifndef OPENSSL_NO_RSA
854 res = hwcrhk_load_privkey(eng, key_id, ui_method, callback_data);
859 # ifndef OPENSSL_NO_RSA
864 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
866 res->pkey.rsa = RSA_new();
867 res->pkey.rsa->n = rsa->n;
868 res->pkey.rsa->e = rsa->e;
871 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
877 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
878 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
888 /* A little mod_exp */
889 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
890 const BIGNUM *m, BN_CTX *ctx)
893 HWCryptoHook_ErrMsgBuf rmsg;
895 * Since HWCryptoHook_MPI is pretty compatible with BIGNUM's, we use them
896 * directly, plus a little macro magic. We only thing we need to make
897 * sure of is that enough space is allocated.
899 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
902 to_return = 0; /* expect failure */
904 rmsg.size = sizeof(tempbuf);
906 if (!hwcrhk_context) {
907 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_NOT_INITIALISED);
910 /* Prepare the params */
911 bn_expand2(r, m->top); /* Check for error !! */
917 /* Perform the operation */
918 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
920 /* Convert the response */
921 r->top = m_r.size / sizeof(BN_ULONG);
926 * FIXME: When this error is returned, HWCryptoHook is telling us
927 * that falling back to software computation might be a good thing.
929 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
930 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FALLBACK);
932 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP, HWCRHK_R_REQUEST_FAILED);
934 ERR_add_error_data(1, rmsg.buf);
943 # ifndef OPENSSL_NO_RSA
944 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa,
948 HWCryptoHook_ErrMsgBuf rmsg;
949 HWCryptoHook_RSAKeyHandle *hptr;
950 int to_return = 0, ret;
953 rmsg.size = sizeof(tempbuf);
955 if (!hwcrhk_context) {
956 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP, HWCRHK_R_NOT_INITIALISED);
961 * This provides support for nForce keys. Since that's opaque data all
962 * we do is provide a handle to the proper key and let HWCryptoHook take
966 (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
968 HWCryptoHook_MPI m_a, m_r;
971 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
972 HWCRHK_R_MISSING_KEY_COMPONENTS);
976 /* Prepare the params */
977 bn_expand2(r, rsa->n->top); /* Check for error !! */
981 /* Perform the operation */
982 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
984 /* Convert the response */
985 r->top = m_r.size / sizeof(BN_ULONG);
990 * FIXME: When this error is returned, HWCryptoHook is telling us
991 * that falling back to software computation might be a good
994 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
995 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
996 HWCRHK_R_REQUEST_FALLBACK);
998 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
999 HWCRHK_R_REQUEST_FAILED);
1001 ERR_add_error_data(1, rmsg.buf);
1005 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1007 if (!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp) {
1008 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1009 HWCRHK_R_MISSING_KEY_COMPONENTS);
1013 /* Prepare the params */
1014 bn_expand2(r, rsa->n->top); /* Check for error !! */
1016 BN2MPI(m_p, rsa->p);
1017 BN2MPI(m_q, rsa->q);
1018 BN2MPI(m_dmp1, rsa->dmp1);
1019 BN2MPI(m_dmq1, rsa->dmq1);
1020 BN2MPI(m_iqmp, rsa->iqmp);
1023 /* Perform the operation */
1024 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1025 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1027 /* Convert the response */
1028 r->top = m_r.size / sizeof(BN_ULONG);
1033 * FIXME: When this error is returned, HWCryptoHook is telling us
1034 * that falling back to software computation might be a good
1037 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
1038 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1039 HWCRHK_R_REQUEST_FALLBACK);
1041 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1042 HWCRHK_R_REQUEST_FAILED);
1044 ERR_add_error_data(1, rmsg.buf);
1049 * If we're here, we must be here with some semblance of success :-)
1057 # ifndef OPENSSL_NO_RSA
1058 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1059 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1060 const BIGNUM *m, BN_CTX *ctx,
1063 return hwcrhk_mod_exp(r, a, p, m, ctx);
1066 static int hwcrhk_rsa_finish(RSA *rsa)
1068 HWCryptoHook_RSAKeyHandle *hptr;
1070 hptr = RSA_get_ex_data(rsa, hndidx_rsa);
1072 p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1074 RSA_set_ex_data(rsa, hndidx_rsa, NULL);
1081 # ifndef OPENSSL_NO_DH
1082 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1083 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1084 const BIGNUM *a, const BIGNUM *p,
1085 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1087 return hwcrhk_mod_exp(r, a, p, m, ctx);
1091 /* Random bytes are good */
1092 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1095 HWCryptoHook_ErrMsgBuf rmsg;
1096 int to_return = 0; /* assume failure */
1100 rmsg.size = sizeof(tempbuf);
1102 if (!hwcrhk_context) {
1103 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_NOT_INITIALISED);
1107 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1110 * FIXME: When this error is returned, HWCryptoHook is telling us
1111 * that falling back to software computation might be a good thing.
1113 if (ret == HWCRYPTOHOOK_ERROR_FALLBACK) {
1114 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FALLBACK);
1116 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES, HWCRHK_R_REQUEST_FAILED);
1118 ERR_add_error_data(1, rmsg.buf);
1126 static int hwcrhk_rand_status(void)
1132 * Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1133 * these just wrap the POSIX functions and add some logging.
1136 static int hwcrhk_mutex_init(HWCryptoHook_Mutex * mt,
1137 HWCryptoHook_CallerContext * cactx)
1139 mt->lockid = CRYPTO_get_new_dynlockid();
1140 if (mt->lockid == 0)
1141 return 1; /* failure */
1142 return 0; /* success */
1145 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex * mt)
1147 CRYPTO_w_lock(mt->lockid);
1151 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1153 CRYPTO_w_unlock(mt->lockid);
1156 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex * mt)
1158 CRYPTO_destroy_dynlockid(mt->lockid);
1161 static int hwcrhk_get_pass(const char *prompt_info,
1162 int *len_io, char *buf,
1163 HWCryptoHook_PassphraseContext * ppctx,
1164 HWCryptoHook_CallerContext * cactx)
1166 pem_password_cb *callback = NULL;
1167 void *callback_data = NULL;
1168 UI_METHOD *ui_method = NULL;
1170 * Despite what the documentation says prompt_info can be an empty
1173 if (prompt_info && !*prompt_info)
1177 if (cactx->ui_method)
1178 ui_method = cactx->ui_method;
1179 if (cactx->password_callback)
1180 callback = cactx->password_callback;
1181 if (cactx->callback_data)
1182 callback_data = cactx->callback_data;
1185 if (ppctx->ui_method) {
1186 ui_method = ppctx->ui_method;
1189 if (ppctx->callback_data)
1190 callback_data = ppctx->callback_data;
1192 if (callback == NULL && ui_method == NULL) {
1193 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS, HWCRHK_R_NO_CALLBACK);
1198 UI *ui = UI_new_method(ui_method);
1201 char *prompt = UI_construct_prompt(ui,
1202 "pass phrase", prompt_info);
1204 ok = UI_add_input_string(ui, prompt,
1205 UI_INPUT_FLAG_DEFAULT_PWD,
1206 buf, 0, (*len_io) - 1);
1207 UI_add_user_data(ui, callback_data);
1208 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1212 ok = UI_process(ui);
1214 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1217 *len_io = strlen(buf);
1220 OPENSSL_free(prompt);
1223 *len_io = callback(buf, *len_io, 0, callback_data);
1230 static int hwcrhk_insert_card(const char *prompt_info,
1231 const char *wrong_info,
1232 HWCryptoHook_PassphraseContext * ppctx,
1233 HWCryptoHook_CallerContext * cactx)
1237 void *callback_data = NULL;
1238 UI_METHOD *ui_method = NULL;
1241 if (cactx->ui_method)
1242 ui_method = cactx->ui_method;
1243 if (cactx->callback_data)
1244 callback_data = cactx->callback_data;
1247 if (ppctx->ui_method)
1248 ui_method = ppctx->ui_method;
1249 if (ppctx->callback_data)
1250 callback_data = ppctx->callback_data;
1252 if (ui_method == NULL) {
1253 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD, HWCRHK_R_NO_CALLBACK);
1257 ui = UI_new_method(ui_method);
1263 * Despite what the documentation says wrong_info can be an empty
1266 if (wrong_info && *wrong_info)
1267 BIO_snprintf(buf, sizeof(buf) - 1,
1268 "Current card: \"%s\"\n", wrong_info);
1271 ok = UI_dup_info_string(ui, buf);
1272 if (ok >= 0 && prompt_info) {
1273 BIO_snprintf(buf, sizeof(buf) - 1,
1274 "Insert card \"%s\"", prompt_info);
1275 ok = UI_dup_input_boolean(ui, buf,
1276 "\n then hit <enter> or C<enter> to cancel\n",
1277 "\r\n", "Cc", UI_INPUT_FLAG_ECHO,
1280 UI_add_user_data(ui, callback_data);
1283 ok = UI_process(ui);
1286 if (ok == -2 || (ok >= 0 && answer == 'C'))
1296 static void hwcrhk_log_message(void *logstr, const char *message)
1298 BIO *lstream = NULL;
1300 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1302 lstream = *(BIO **)logstr;
1304 BIO_printf(lstream, "%s\n", message);
1306 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1310 * This stuff is needed if this ENGINE is being compiled into a
1311 * self-contained shared-library.
1313 # ifndef OPENSSL_NO_DYNAMIC_ENGINE
1314 static int bind_fn(ENGINE *e, const char *id)
1316 if (id && (strcmp(id, engine_hwcrhk_id) != 0) &&
1317 (strcmp(id, engine_hwcrhk_id_alt) != 0))
1319 if (!bind_helper(e))
1324 IMPLEMENT_DYNAMIC_CHECK_FN()
1325 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1326 # endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1327 # endif /* !OPENSSL_NO_HW_CHIL */
1328 #endif /* !OPENSSL_NO_HW */