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 (shenson@bigfoot.com)
4 * for the OpenSSL project 2000.
6 /* ====================================================================
7 * Copyright (c) 1999-2001 The OpenSSL Project. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
21 * 3. All advertising materials mentioning features or use of this
22 * software must display the following acknowledgment:
23 * "This product includes software developed by the OpenSSL Project
24 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27 * endorse or promote products derived from this software without
28 * prior written permission. For written permission, please contact
29 * licensing@OpenSSL.org.
31 * 5. Products derived from this software may not be called "OpenSSL"
32 * nor may "OpenSSL" appear in their names without prior written
33 * permission of the OpenSSL Project.
35 * 6. Redistributions of any form whatsoever must retain the following
37 * "This product includes software developed by the OpenSSL Project
38 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51 * OF THE POSSIBILITY OF SUCH DAMAGE.
52 * ====================================================================
54 * This product includes cryptographic software written by Eric Young
55 * (eay@cryptsoft.com). This product includes software written by Tim
56 * Hudson (tjh@cryptsoft.com).
62 #include <openssl/crypto.h>
63 #include <openssl/pem.h>
64 #include <openssl/dso.h>
65 #include <openssl/engine.h>
66 #include <openssl/ui.h>
67 #include <openssl/rand.h>
68 #include <openssl/rsa.h>
69 #include <openssl/dh.h>
70 #include <openssl/bn.h>
73 #ifndef OPENSSL_NO_HW_CHIL
75 /* Attribution notice: nCipher have said several times that it's OK for
76 * us to implement a general interface to their boxes, and recently declared
77 * their HWCryptoHook to be public, and therefore available for us to use.
80 * The hwcryptohook.h included here is from May 2000.
84 #include "hwcryptohook.h"
86 #include "vendor_defns/hwcryptohook.h"
89 #define HWCRHK_LIB_NAME "CHIL engine"
90 #include "e_chil_err.c"
92 static int hwcrhk_destroy(ENGINE *e);
93 static int hwcrhk_init(ENGINE *e);
94 static int hwcrhk_finish(ENGINE *e);
95 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
97 /* Functions to handle mutexes */
98 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
99 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
100 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
101 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
104 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
105 const BIGNUM *m, BN_CTX *ctx);
107 #ifndef OPENSSL_NO_RSA
109 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
111 /* This function is aliased to mod_exp (with the mont stuff dropped). */
112 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
113 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
115 #ifndef OPENSSL_NO_DH
117 /* This function is alised to mod_exp (with the DH and mont dropped). */
118 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
119 const BIGNUM *a, const BIGNUM *p,
120 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
124 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
125 static int hwcrhk_rand_status(void);
128 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
129 UI_METHOD *ui_method, void *callback_data);
130 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
131 UI_METHOD *ui_method, void *callback_data);
132 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
133 int ind,long argl, void *argp);
135 /* Interaction stuff */
136 static int hwcrhk_insert_card(const char *prompt_info,
137 const char *wrong_info,
138 HWCryptoHook_PassphraseContext *ppctx,
139 HWCryptoHook_CallerContext *cactx);
140 static int hwcrhk_get_pass(const char *prompt_info,
141 int *len_io, char *buf,
142 HWCryptoHook_PassphraseContext *ppctx,
143 HWCryptoHook_CallerContext *cactx);
144 static void hwcrhk_log_message(void *logstr, const char *message);
146 /* The definitions for control commands specific to this engine */
147 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
148 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
149 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
150 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
151 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
152 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
155 "Specifies the path to the 'hwcrhk' shared library",
156 ENGINE_CMD_FLAG_STRING},
157 {HWCRHK_CMD_FORK_CHECK,
159 "Turns fork() checking on or off (boolean)",
160 ENGINE_CMD_FLAG_NUMERIC},
161 {HWCRHK_CMD_THREAD_LOCKING,
163 "Turns thread-safe locking on or off (boolean)",
164 ENGINE_CMD_FLAG_NUMERIC},
165 {HWCRHK_CMD_SET_USER_INTERFACE,
166 "SET_USER_INTERFACE",
167 "Set the global user interface (internal)",
168 ENGINE_CMD_FLAG_INTERNAL},
169 {HWCRHK_CMD_SET_CALLBACK_DATA,
171 "Set the global user interface extra data (internal)",
172 ENGINE_CMD_FLAG_INTERNAL},
176 #ifndef OPENSSL_NO_RSA
177 /* Our internal RSA_METHOD that we provide pointers to */
178 static RSA_METHOD hwcrhk_rsa =
197 #ifndef OPENSSL_NO_DH
198 /* Our internal DH_METHOD that we provide pointers to */
199 static DH_METHOD hwcrhk_dh =
213 static RAND_METHOD hwcrhk_rand =
215 /* "CHIL RAND method", */
224 /* Constants used when creating the ENGINE */
225 static const char *engine_hwcrhk_id = "chil";
226 static const char *engine_hwcrhk_name = "CHIL hardware engine support";
227 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
228 /* Compatibility hack, the dynamic library uses this form in the path */
229 static const char *engine_hwcrhk_id_alt = "ncipher";
232 /* Internal stuff for HWCryptoHook */
234 /* Some structures needed for proper use of thread locks */
235 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
236 into HWCryptoHook_Mutex */
237 struct HWCryptoHook_MutexValue
242 /* hwcryptohook.h has some typedefs that turn
243 struct HWCryptoHook_PassphraseContextValue
244 into HWCryptoHook_PassphraseContext */
245 struct HWCryptoHook_PassphraseContextValue
247 UI_METHOD *ui_method;
251 /* hwcryptohook.h has some typedefs that turn
252 struct HWCryptoHook_CallerContextValue
253 into HWCryptoHook_CallerContext */
254 struct HWCryptoHook_CallerContextValue
256 pem_password_cb *password_callback; /* Deprecated! Only present for
257 backward compatibility! */
258 UI_METHOD *ui_method;
262 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
263 BIGNUM's, so lets define a couple of conversion macros */
264 #define BN2MPI(mp, bn) \
265 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
266 #define MPI2BN(bn, mp) \
267 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
269 static BIO *logstream = NULL;
270 static int disable_mutex_callbacks = 0;
272 /* One might wonder why these are needed, since one can pass down at least
273 a UI_METHOD and a pointer to callback data to the key-loading functions.
274 The thing is that the ModExp and RSAImmed functions can load keys as well,
275 if the data they get is in a special, nCipher-defined format (hint: if you
276 look at the private exponent of the RSA data as a string, you'll see this
277 string: "nCipher KM tool key id", followed by some bytes, followed a key
278 identity string, followed by more bytes. This happens when you use "embed"
279 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
280 any passphrase or caller context, and our functions can't really take any
281 callback data either. Still, the "insert_card" and "get_passphrase"
282 callbacks may be called down the line, and will need to know what user
283 interface callbacks to call, and having callback data from the application
284 may be a nice thing as well, so we need to keep track of that globally. */
285 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
287 /* Stuff to pass to the HWCryptoHook library */
288 static HWCryptoHook_InitInfo hwcrhk_globals = {
289 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
290 &logstream, /* logstream */
291 sizeof(BN_ULONG), /* limbsize */
292 0, /* mslimb first: false for BNs */
293 -1, /* msbyte first: use native */
294 0, /* Max mutexes, 0 = no small limit */
295 0, /* Max simultaneous, 0 = default */
297 /* The next few are mutex stuff: we write wrapper functions
298 around the OS mutex functions. We initialise them to 0
299 here, and change that to actual function pointers in hwcrhk_init()
300 if dynamic locks are supported (that is, if the application
301 programmer has made sure of setting up callbacks bafore starting
302 this engine) *and* if disable_mutex_callbacks hasn't been set by
303 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
304 sizeof(HWCryptoHook_Mutex),
310 /* The next few are condvar stuff: we write wrapper functions
311 round the OS functions. Currently not implemented and not
312 and absolute necessity even in threaded programs, therefore
313 0'ed. Will hopefully be implemented some day, since it
314 enhances the efficiency of HWCryptoHook. */
315 0, /* sizeof(HWCryptoHook_CondVar), */
316 0, /* hwcrhk_cv_init, */
317 0, /* hwcrhk_cv_wait, */
318 0, /* hwcrhk_cv_signal, */
319 0, /* hwcrhk_cv_broadcast, */
320 0, /* hwcrhk_cv_destroy, */
322 hwcrhk_get_pass, /* pass phrase */
323 hwcrhk_insert_card, /* insert a card */
324 hwcrhk_log_message /* Log message */
328 /* Now, to our own code */
330 /* This internal function is used by ENGINE_chil() and possibly by the
331 * "dynamic" ENGINE support too */
332 static int bind_helper(ENGINE *e)
334 #ifndef OPENSSL_NO_RSA
335 const RSA_METHOD *meth1;
337 #ifndef OPENSSL_NO_DH
338 const DH_METHOD *meth2;
340 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
341 !ENGINE_set_name(e, engine_hwcrhk_name) ||
342 #ifndef OPENSSL_NO_RSA
343 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
345 #ifndef OPENSSL_NO_DH
346 !ENGINE_set_DH(e, &hwcrhk_dh) ||
348 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
349 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
350 !ENGINE_set_init_function(e, hwcrhk_init) ||
351 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
352 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
353 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
354 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
355 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
358 #ifndef OPENSSL_NO_RSA
359 /* We know that the "PKCS1_SSLeay()" functions hook properly
360 * to the cswift-specific mod_exp and mod_exp_crt so we use
361 * those functions. NB: We don't use ENGINE_openssl() or
362 * anything "more generic" because something like the RSAref
363 * code may not hook properly, and if you own one of these
364 * cards then you have the right to do RSA operations on it
366 meth1 = RSA_PKCS1_SSLeay();
367 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
368 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
369 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
370 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
373 #ifndef OPENSSL_NO_DH
374 /* Much the same for Diffie-Hellman */
375 meth2 = DH_OpenSSL();
376 hwcrhk_dh.generate_key = meth2->generate_key;
377 hwcrhk_dh.compute_key = meth2->compute_key;
380 /* Ensure the hwcrhk error handling is set up */
381 ERR_load_HWCRHK_strings();
385 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
386 static ENGINE *engine_chil(void)
388 ENGINE *ret = ENGINE_new();
391 if(!bind_helper(ret))
399 void ENGINE_load_chil(void)
401 /* Copied from eng_[openssl|dyn].c */
402 ENGINE *toadd = engine_chil();
410 /* This is a process-global DSO handle used for loading and unloading
411 * the HWCryptoHook library. NB: This is only set (or unset) during an
412 * init() or finish() call (reference counts permitting) and they're
413 * operating with global locks, so this should be thread-safe
415 static DSO *hwcrhk_dso = NULL;
416 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
417 #ifndef OPENSSL_NO_RSA
418 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
421 /* These are the function pointers that are (un)set when the library has
422 * successfully (un)loaded. */
423 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
424 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
425 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
426 #ifndef OPENSSL_NO_RSA
427 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
429 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
430 #ifndef OPENSSL_NO_RSA
431 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
432 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
433 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
435 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
437 /* Used in the DSO operations. */
438 static const char *HWCRHK_LIBNAME = NULL;
439 static void free_HWCRHK_LIBNAME(void)
442 OPENSSL_free((void*)HWCRHK_LIBNAME);
443 HWCRHK_LIBNAME = NULL;
445 static const char *get_HWCRHK_LIBNAME(void)
448 return HWCRHK_LIBNAME;
451 static long set_HWCRHK_LIBNAME(const char *name)
453 free_HWCRHK_LIBNAME();
454 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
456 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
457 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
458 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
459 #ifndef OPENSSL_NO_RSA
460 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
462 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
463 #ifndef OPENSSL_NO_RSA
464 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
465 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
466 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
468 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
470 /* HWCryptoHook library functions and mechanics - these are used by the
471 * higher-level functions further down. NB: As and where there's no
472 * error checking, take a look lower down where these functions are
473 * called, the checking and error handling is probably down there. */
475 /* utility function to obtain a context */
476 static int get_context(HWCryptoHook_ContextHandle *hac,
477 HWCryptoHook_CallerContext *cac)
480 HWCryptoHook_ErrMsgBuf rmsg;
483 rmsg.size = sizeof(tempbuf);
485 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
492 /* similarly to release one. */
493 static void release_context(HWCryptoHook_ContextHandle hac)
495 p_hwcrhk_Finish(hac);
498 /* Destructor (complements the "ENGINE_chil()" constructor) */
499 static int hwcrhk_destroy(ENGINE *e)
501 free_HWCRHK_LIBNAME();
502 ERR_unload_HWCRHK_strings();
506 /* (de)initialisation functions. */
507 static int hwcrhk_init(ENGINE *e)
509 HWCryptoHook_Init_t *p1;
510 HWCryptoHook_Finish_t *p2;
511 HWCryptoHook_ModExp_t *p3;
512 #ifndef OPENSSL_NO_RSA
513 HWCryptoHook_RSA_t *p4;
514 HWCryptoHook_RSALoadKey_t *p5;
515 HWCryptoHook_RSAGetPublicKey_t *p6;
516 HWCryptoHook_RSAUnloadKey_t *p7;
518 HWCryptoHook_RandomBytes_t *p8;
519 HWCryptoHook_ModExpCRT_t *p9;
521 if(hwcrhk_dso != NULL)
523 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
526 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
527 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
528 if(hwcrhk_dso == NULL)
530 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
533 if(!(p1 = (HWCryptoHook_Init_t *)
534 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
535 !(p2 = (HWCryptoHook_Finish_t *)
536 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
537 !(p3 = (HWCryptoHook_ModExp_t *)
538 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
539 #ifndef OPENSSL_NO_RSA
540 !(p4 = (HWCryptoHook_RSA_t *)
541 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
542 !(p5 = (HWCryptoHook_RSALoadKey_t *)
543 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
544 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
545 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
546 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
547 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
549 !(p8 = (HWCryptoHook_RandomBytes_t *)
550 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
551 !(p9 = (HWCryptoHook_ModExpCRT_t *)
552 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
554 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
557 /* Copy the pointers */
559 p_hwcrhk_Finish = p2;
560 p_hwcrhk_ModExp = p3;
561 #ifndef OPENSSL_NO_RSA
563 p_hwcrhk_RSALoadKey = p5;
564 p_hwcrhk_RSAGetPublicKey = p6;
565 p_hwcrhk_RSAUnloadKey = p7;
567 p_hwcrhk_RandomBytes = p8;
568 p_hwcrhk_ModExpCRT = p9;
570 /* Check if the application decided to support dynamic locks,
571 and if it does, use them. */
572 if (disable_mutex_callbacks == 0)
574 if (CRYPTO_get_dynlock_create_callback() != NULL &&
575 CRYPTO_get_dynlock_lock_callback() != NULL &&
576 CRYPTO_get_dynlock_destroy_callback() != NULL)
578 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
579 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
580 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
581 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
583 else if (CRYPTO_get_locking_callback() != NULL)
585 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_LOCKING_MISSING);
586 ERR_add_error_data(1,"You HAVE to add dynamic locking callbacks via CRYPTO_set_dynlock_{create,lock,destroy}_callback()");
591 /* Try and get a context - if not, we may have a DSO but no
593 if(!get_context(&hwcrhk_context, &password_context))
595 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
598 /* Everything's fine. */
599 #ifndef OPENSSL_NO_RSA
600 if (hndidx_rsa == -1)
601 hndidx_rsa = RSA_get_ex_new_index(0,
602 "nFast HWCryptoHook RSA key handle",
603 NULL, NULL, hwcrhk_ex_free);
608 DSO_free(hwcrhk_dso);
610 p_hwcrhk_Init = NULL;
611 p_hwcrhk_Finish = NULL;
612 p_hwcrhk_ModExp = NULL;
613 #ifndef OPENSSL_NO_RSA
615 p_hwcrhk_RSALoadKey = NULL;
616 p_hwcrhk_RSAGetPublicKey = NULL;
617 p_hwcrhk_RSAUnloadKey = NULL;
619 p_hwcrhk_ModExpCRT = NULL;
620 p_hwcrhk_RandomBytes = NULL;
624 static int hwcrhk_finish(ENGINE *e)
627 free_HWCRHK_LIBNAME();
628 if(hwcrhk_dso == NULL)
630 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
634 release_context(hwcrhk_context);
635 if(!DSO_free(hwcrhk_dso))
637 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
645 p_hwcrhk_Init = NULL;
646 p_hwcrhk_Finish = NULL;
647 p_hwcrhk_ModExp = NULL;
648 #ifndef OPENSSL_NO_RSA
650 p_hwcrhk_RSALoadKey = NULL;
651 p_hwcrhk_RSAGetPublicKey = NULL;
652 p_hwcrhk_RSAUnloadKey = NULL;
654 p_hwcrhk_ModExpCRT = NULL;
655 p_hwcrhk_RandomBytes = NULL;
659 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
665 case HWCRHK_CMD_SO_PATH:
668 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
673 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
676 return set_HWCRHK_LIBNAME((const char *)p);
677 case ENGINE_CTRL_SET_LOGSTREAM:
681 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);
711 /* this enables or disables the "SimpleForkCheck" flag used in the
712 * initialisation structure. */
713 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
714 case HWCRHK_CMD_FORK_CHECK:
715 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
717 hwcrhk_globals.flags |=
718 HWCryptoHook_InitFlags_SimpleForkCheck;
720 hwcrhk_globals.flags &=
721 ~HWCryptoHook_InitFlags_SimpleForkCheck;
722 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
724 /* This will prevent the initialisation function from "installing"
725 * the mutex-handling callbacks, even if they are available from
726 * within the library (or were provided to the library from the
727 * calling application). This is to remove any baggage for
728 * applications not using multithreading. */
729 case ENGINE_CTRL_CHIL_NO_LOCKING:
730 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
731 disable_mutex_callbacks = 1;
732 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
734 case HWCRHK_CMD_THREAD_LOCKING:
735 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
736 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
737 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
740 /* The command isn't understood by this engine */
742 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
743 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
751 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
752 UI_METHOD *ui_method, void *callback_data)
754 #ifndef OPENSSL_NO_RSA
757 EVP_PKEY *res = NULL;
758 #ifndef OPENSSL_NO_RSA
759 HWCryptoHook_MPI e, n;
760 HWCryptoHook_RSAKeyHandle *hptr;
762 #if !defined(OPENSSL_NO_RSA)
764 HWCryptoHook_ErrMsgBuf rmsg;
766 HWCryptoHook_PassphraseContext ppctx;
768 #if !defined(OPENSSL_NO_RSA)
770 rmsg.size = sizeof(tempbuf);
775 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
776 HWCRHK_R_NOT_INITIALISED);
779 #ifndef OPENSSL_NO_RSA
780 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
783 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
784 ERR_R_MALLOC_FAILURE);
787 ppctx.ui_method = ui_method;
788 ppctx.callback_data = callback_data;
789 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
792 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
793 HWCRHK_R_CHIL_ERROR);
794 ERR_add_error_data(1,rmsg.buf);
799 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
804 #ifndef OPENSSL_NO_RSA
805 rtmp = RSA_new_method(eng);
806 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
809 rtmp->flags |= RSA_FLAG_EXT_PKEY;
812 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
813 != HWCRYPTOHOOK_ERROR_MPISIZE)
815 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,HWCRHK_R_CHIL_ERROR);
816 ERR_add_error_data(1,rmsg.buf);
820 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
821 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
825 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
827 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
828 HWCRHK_R_CHIL_ERROR);
829 ERR_add_error_data(1,rmsg.buf);
832 rtmp->e->top = e.size / sizeof(BN_ULONG);
834 rtmp->n->top = n.size / sizeof(BN_ULONG);
837 res = EVP_PKEY_new();
838 EVP_PKEY_assign_RSA(res, rtmp);
842 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
843 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
849 #ifndef OPENSSL_NO_RSA
856 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
857 UI_METHOD *ui_method, void *callback_data)
859 EVP_PKEY *res = NULL;
861 #ifndef OPENSSL_NO_RSA
862 res = hwcrhk_load_privkey(eng, key_id,
863 ui_method, callback_data);
869 #ifndef OPENSSL_NO_RSA
874 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
876 res->pkey.rsa = RSA_new();
877 res->pkey.rsa->n = rsa->n;
878 res->pkey.rsa->e = rsa->e;
881 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
887 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
888 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
899 /* A little mod_exp */
900 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
901 const BIGNUM *m, BN_CTX *ctx)
904 HWCryptoHook_ErrMsgBuf rmsg;
905 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
906 we use them directly, plus a little macro magic. We only
907 thing we need to make sure of is that enough space is allocated. */
908 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
911 to_return = 0; /* expect failure */
913 rmsg.size = sizeof(tempbuf);
917 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
920 /* Prepare the params */
921 bn_expand2(r, m->top); /* Check for error !! */
927 /* Perform the operation */
928 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
930 /* Convert the response */
931 r->top = m_r.size / sizeof(BN_ULONG);
936 /* FIXME: When this error is returned, HWCryptoHook is
937 telling us that falling back to software computation
938 might be a good thing. */
939 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
941 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
945 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
947 ERR_add_error_data(1,rmsg.buf);
956 #ifndef OPENSSL_NO_RSA
957 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
960 HWCryptoHook_ErrMsgBuf rmsg;
961 HWCryptoHook_RSAKeyHandle *hptr;
962 int to_return = 0, ret;
965 rmsg.size = sizeof(tempbuf);
969 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
973 /* This provides support for nForce keys. Since that's opaque data
974 all we do is provide a handle to the proper key and let HWCryptoHook
975 take care of the rest. */
976 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
979 HWCryptoHook_MPI m_a, m_r;
983 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
984 HWCRHK_R_MISSING_KEY_COMPONENTS);
988 /* Prepare the params */
989 bn_expand2(r, rsa->n->top); /* Check for error !! */
993 /* Perform the operation */
994 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
996 /* Convert the response */
997 r->top = m_r.size / sizeof(BN_ULONG);
1002 /* FIXME: When this error is returned, HWCryptoHook is
1003 telling us that falling back to software computation
1004 might be a good thing. */
1005 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1007 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1008 HWCRHK_R_REQUEST_FALLBACK);
1012 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1013 HWCRHK_R_REQUEST_FAILED);
1015 ERR_add_error_data(1,rmsg.buf);
1021 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1023 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1025 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1026 HWCRHK_R_MISSING_KEY_COMPONENTS);
1030 /* Prepare the params */
1031 bn_expand2(r, rsa->n->top); /* Check for error !! */
1033 BN2MPI(m_p, rsa->p);
1034 BN2MPI(m_q, rsa->q);
1035 BN2MPI(m_dmp1, rsa->dmp1);
1036 BN2MPI(m_dmq1, rsa->dmq1);
1037 BN2MPI(m_iqmp, rsa->iqmp);
1040 /* Perform the operation */
1041 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1042 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1044 /* Convert the response */
1045 r->top = m_r.size / sizeof(BN_ULONG);
1050 /* FIXME: When this error is returned, HWCryptoHook is
1051 telling us that falling back to software computation
1052 might be a good thing. */
1053 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1055 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1056 HWCRHK_R_REQUEST_FALLBACK);
1060 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1061 HWCRHK_R_REQUEST_FAILED);
1063 ERR_add_error_data(1,rmsg.buf);
1067 /* If we're here, we must be here with some semblance of success :-) */
1074 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1075 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1076 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1078 return hwcrhk_mod_exp(r, a, p, m, ctx);
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);
1104 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1108 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1111 /* FIXME: When this error is returned, HWCryptoHook is
1112 telling us that falling back to software computation
1113 might be a good thing. */
1114 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1116 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1117 HWCRHK_R_REQUEST_FALLBACK);
1121 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1122 HWCRHK_R_REQUEST_FAILED);
1124 ERR_add_error_data(1,rmsg.buf);
1132 static int hwcrhk_rand_status(void)
1137 /* This cleans up an RSA KM key, called when ex_data is freed */
1139 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1140 int ind,long argl, void *argp)
1143 HWCryptoHook_ErrMsgBuf rmsg;
1144 #ifndef OPENSSL_NO_RSA
1145 HWCryptoHook_RSAKeyHandle *hptr;
1147 #if !defined(OPENSSL_NO_RSA)
1152 rmsg.size = sizeof(tempbuf);
1154 #ifndef OPENSSL_NO_RSA
1155 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1158 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1164 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1165 * these just wrap the POSIX functions and add some logging.
1168 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1169 HWCryptoHook_CallerContext *cactx)
1171 mt->lockid = CRYPTO_get_new_dynlockid();
1172 if (mt->lockid == 0)
1173 return 1; /* failure */
1174 return 0; /* success */
1177 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1179 CRYPTO_w_lock(mt->lockid);
1183 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1185 CRYPTO_w_unlock(mt->lockid);
1188 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1190 CRYPTO_destroy_dynlockid(mt->lockid);
1193 static int hwcrhk_get_pass(const char *prompt_info,
1194 int *len_io, char *buf,
1195 HWCryptoHook_PassphraseContext *ppctx,
1196 HWCryptoHook_CallerContext *cactx)
1198 pem_password_cb *callback = NULL;
1199 void *callback_data = NULL;
1200 UI_METHOD *ui_method = NULL;
1204 if (cactx->ui_method)
1205 ui_method = cactx->ui_method;
1206 if (cactx->password_callback)
1207 callback = cactx->password_callback;
1208 if (cactx->callback_data)
1209 callback_data = cactx->callback_data;
1213 if (ppctx->ui_method)
1215 ui_method = ppctx->ui_method;
1218 if (ppctx->callback_data)
1219 callback_data = ppctx->callback_data;
1221 if (callback == NULL && ui_method == NULL)
1223 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1229 UI *ui = UI_new_method(ui_method);
1233 char *prompt = UI_construct_prompt(ui,
1234 "pass phrase", prompt_info);
1236 ok = UI_add_input_string(ui,prompt,
1237 UI_INPUT_FLAG_DEFAULT_PWD,
1238 buf,0,(*len_io) - 1);
1239 UI_add_user_data(ui, callback_data);
1240 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1247 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1250 *len_io = strlen(buf);
1253 OPENSSL_free(prompt);
1258 *len_io = callback(buf, *len_io, 0, callback_data);
1265 static int hwcrhk_insert_card(const char *prompt_info,
1266 const char *wrong_info,
1267 HWCryptoHook_PassphraseContext *ppctx,
1268 HWCryptoHook_CallerContext *cactx)
1272 void *callback_data = NULL;
1273 UI_METHOD *ui_method = NULL;
1277 if (cactx->ui_method)
1278 ui_method = cactx->ui_method;
1279 if (cactx->callback_data)
1280 callback_data = cactx->callback_data;
1284 if (ppctx->ui_method)
1285 ui_method = ppctx->ui_method;
1286 if (ppctx->callback_data)
1287 callback_data = ppctx->callback_data;
1289 if (ui_method == NULL)
1291 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1292 HWCRHK_R_NO_CALLBACK);
1296 ui = UI_new_method(ui_method);
1304 BIO_snprintf(buf, sizeof(buf)-1,
1305 "Current card: \"%s\"\n", wrong_info);
1306 ok = UI_dup_info_string(ui, buf);
1307 if (ok >= 0 && prompt_info)
1309 BIO_snprintf(buf, sizeof(buf)-1,
1310 "Insert card \"%s\"", prompt_info);
1311 ok = UI_dup_input_boolean(ui, buf,
1312 "\n then hit <enter> or C<enter> to cancel\n",
1313 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1315 UI_add_user_data(ui, callback_data);
1318 ok = UI_process(ui);
1321 if (ok == -2 || (ok >= 0 && answer == 'C'))
1331 static void hwcrhk_log_message(void *logstr, const char *message)
1333 BIO *lstream = NULL;
1335 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1337 lstream=*(BIO **)logstr;
1340 BIO_printf(lstream, "%s\n", message);
1342 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1345 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1346 * shared-library. */
1347 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1348 static int bind_fn(ENGINE *e, const char *id)
1350 if(id && (strcmp(id, engine_hwcrhk_id) != 0) &&
1351 (strcmp(id, engine_hwcrhk_id_alt) != 0))
1357 IMPLEMENT_DYNAMIC_CHECK_FN()
1358 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1359 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1361 #endif /* !OPENSSL_NO_HW_CHIL */
1362 #endif /* !OPENSSL_NO_HW */