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";
228 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
229 /* Compatibility hack, the dynamic library uses this form in the path */
230 static const char *engine_hwcrhk_id_alt = "ncipher";
233 /* Internal stuff for HWCryptoHook */
235 /* Some structures needed for proper use of thread locks */
236 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
237 into HWCryptoHook_Mutex */
238 struct HWCryptoHook_MutexValue
243 /* hwcryptohook.h has some typedefs that turn
244 struct HWCryptoHook_PassphraseContextValue
245 into HWCryptoHook_PassphraseContext */
246 struct HWCryptoHook_PassphraseContextValue
248 UI_METHOD *ui_method;
252 /* hwcryptohook.h has some typedefs that turn
253 struct HWCryptoHook_CallerContextValue
254 into HWCryptoHook_CallerContext */
255 struct HWCryptoHook_CallerContextValue
257 pem_password_cb *password_callback; /* Deprecated! Only present for
258 backward compatibility! */
259 UI_METHOD *ui_method;
263 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
264 BIGNUM's, so lets define a couple of conversion macros */
265 #define BN2MPI(mp, bn) \
266 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
267 #define MPI2BN(bn, mp) \
268 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
270 static BIO *logstream = NULL;
271 static int disable_mutex_callbacks = 0;
273 /* One might wonder why these are needed, since one can pass down at least
274 a UI_METHOD and a pointer to callback data to the key-loading functions.
275 The thing is that the ModExp and RSAImmed functions can load keys as well,
276 if the data they get is in a special, nCipher-defined format (hint: if you
277 look at the private exponent of the RSA data as a string, you'll see this
278 string: "nCipher KM tool key id", followed by some bytes, followed a key
279 identity string, followed by more bytes. This happens when you use "embed"
280 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
281 any passphrase or caller context, and our functions can't really take any
282 callback data either. Still, the "insert_card" and "get_passphrase"
283 callbacks may be called down the line, and will need to know what user
284 interface callbacks to call, and having callback data from the application
285 may be a nice thing as well, so we need to keep track of that globally. */
286 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
288 /* Stuff to pass to the HWCryptoHook library */
289 static HWCryptoHook_InitInfo hwcrhk_globals = {
290 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
291 &logstream, /* logstream */
292 sizeof(BN_ULONG), /* limbsize */
293 0, /* mslimb first: false for BNs */
294 -1, /* msbyte first: use native */
295 0, /* Max mutexes, 0 = no small limit */
296 0, /* Max simultaneous, 0 = default */
298 /* The next few are mutex stuff: we write wrapper functions
299 around the OS mutex functions. We initialise them to 0
300 here, and change that to actual function pointers in hwcrhk_init()
301 if dynamic locks are supported (that is, if the application
302 programmer has made sure of setting up callbacks bafore starting
303 this engine) *and* if disable_mutex_callbacks hasn't been set by
304 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
305 sizeof(HWCryptoHook_Mutex),
311 /* The next few are condvar stuff: we write wrapper functions
312 round the OS functions. Currently not implemented and not
313 and absolute necessity even in threaded programs, therefore
314 0'ed. Will hopefully be implemented some day, since it
315 enhances the efficiency of HWCryptoHook. */
316 0, /* sizeof(HWCryptoHook_CondVar), */
317 0, /* hwcrhk_cv_init, */
318 0, /* hwcrhk_cv_wait, */
319 0, /* hwcrhk_cv_signal, */
320 0, /* hwcrhk_cv_broadcast, */
321 0, /* hwcrhk_cv_destroy, */
323 hwcrhk_get_pass, /* pass phrase */
324 hwcrhk_insert_card, /* insert a card */
325 hwcrhk_log_message /* Log message */
329 /* Now, to our own code */
331 /* This internal function is used by ENGINE_chil() and possibly by the
332 * "dynamic" ENGINE support too */
333 static int bind_helper(ENGINE *e)
335 #ifndef OPENSSL_NO_RSA
336 const RSA_METHOD *meth1;
338 #ifndef OPENSSL_NO_DH
339 const DH_METHOD *meth2;
341 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
342 !ENGINE_set_name(e, engine_hwcrhk_name) ||
343 #ifndef OPENSSL_NO_RSA
344 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
346 #ifndef OPENSSL_NO_DH
347 !ENGINE_set_DH(e, &hwcrhk_dh) ||
349 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
350 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
351 !ENGINE_set_init_function(e, hwcrhk_init) ||
352 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
353 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
354 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
355 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
356 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
359 #ifndef OPENSSL_NO_RSA
360 /* We know that the "PKCS1_SSLeay()" functions hook properly
361 * to the cswift-specific mod_exp and mod_exp_crt so we use
362 * those functions. NB: We don't use ENGINE_openssl() or
363 * anything "more generic" because something like the RSAref
364 * code may not hook properly, and if you own one of these
365 * cards then you have the right to do RSA operations on it
367 meth1 = RSA_PKCS1_SSLeay();
368 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
369 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
370 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
371 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
374 #ifndef OPENSSL_NO_DH
375 /* Much the same for Diffie-Hellman */
376 meth2 = DH_OpenSSL();
377 hwcrhk_dh.generate_key = meth2->generate_key;
378 hwcrhk_dh.compute_key = meth2->compute_key;
381 /* Ensure the hwcrhk error handling is set up */
382 ERR_load_HWCRHK_strings();
386 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
387 static ENGINE *engine_chil(void)
389 ENGINE *ret = ENGINE_new();
392 if(!bind_helper(ret))
400 void ENGINE_load_chil(void)
402 /* Copied from eng_[openssl|dyn].c */
403 ENGINE *toadd = engine_chil();
411 /* This is a process-global DSO handle used for loading and unloading
412 * the HWCryptoHook library. NB: This is only set (or unset) during an
413 * init() or finish() call (reference counts permitting) and they're
414 * operating with global locks, so this should be thread-safe
416 static DSO *hwcrhk_dso = NULL;
417 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
418 #ifndef OPENSSL_NO_RSA
419 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
422 /* These are the function pointers that are (un)set when the library has
423 * successfully (un)loaded. */
424 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
425 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
426 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
427 #ifndef OPENSSL_NO_RSA
428 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
430 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
431 #ifndef OPENSSL_NO_RSA
432 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
433 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
434 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
436 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
438 /* Used in the DSO operations. */
439 static const char *HWCRHK_LIBNAME = NULL;
440 static void free_HWCRHK_LIBNAME(void)
443 OPENSSL_free((void*)HWCRHK_LIBNAME);
444 HWCRHK_LIBNAME = NULL;
446 static const char *get_HWCRHK_LIBNAME(void)
449 return HWCRHK_LIBNAME;
452 static long set_HWCRHK_LIBNAME(const char *name)
454 free_HWCRHK_LIBNAME();
455 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
457 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
458 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
459 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
460 #ifndef OPENSSL_NO_RSA
461 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
463 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
464 #ifndef OPENSSL_NO_RSA
465 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
466 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
467 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
469 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
471 /* HWCryptoHook library functions and mechanics - these are used by the
472 * higher-level functions further down. NB: As and where there's no
473 * error checking, take a look lower down where these functions are
474 * called, the checking and error handling is probably down there. */
476 /* utility function to obtain a context */
477 static int get_context(HWCryptoHook_ContextHandle *hac,
478 HWCryptoHook_CallerContext *cac)
481 HWCryptoHook_ErrMsgBuf rmsg;
484 rmsg.size = sizeof(tempbuf);
486 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
493 /* similarly to release one. */
494 static void release_context(HWCryptoHook_ContextHandle hac)
496 p_hwcrhk_Finish(hac);
499 /* Destructor (complements the "ENGINE_chil()" constructor) */
500 static int hwcrhk_destroy(ENGINE *e)
502 free_HWCRHK_LIBNAME();
503 ERR_unload_HWCRHK_strings();
507 /* (de)initialisation functions. */
508 static int hwcrhk_init(ENGINE *e)
510 HWCryptoHook_Init_t *p1;
511 HWCryptoHook_Finish_t *p2;
512 HWCryptoHook_ModExp_t *p3;
513 #ifndef OPENSSL_NO_RSA
514 HWCryptoHook_RSA_t *p4;
515 HWCryptoHook_RSALoadKey_t *p5;
516 HWCryptoHook_RSAGetPublicKey_t *p6;
517 HWCryptoHook_RSAUnloadKey_t *p7;
519 HWCryptoHook_RandomBytes_t *p8;
520 HWCryptoHook_ModExpCRT_t *p9;
522 if(hwcrhk_dso != NULL)
524 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
527 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
528 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
529 if(hwcrhk_dso == NULL)
531 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
534 if(!(p1 = (HWCryptoHook_Init_t *)
535 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
536 !(p2 = (HWCryptoHook_Finish_t *)
537 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
538 !(p3 = (HWCryptoHook_ModExp_t *)
539 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
540 #ifndef OPENSSL_NO_RSA
541 !(p4 = (HWCryptoHook_RSA_t *)
542 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
543 !(p5 = (HWCryptoHook_RSALoadKey_t *)
544 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
545 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
546 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
547 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
548 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
550 !(p8 = (HWCryptoHook_RandomBytes_t *)
551 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
552 !(p9 = (HWCryptoHook_ModExpCRT_t *)
553 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
555 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
558 /* Copy the pointers */
560 p_hwcrhk_Finish = p2;
561 p_hwcrhk_ModExp = p3;
562 #ifndef OPENSSL_NO_RSA
564 p_hwcrhk_RSALoadKey = p5;
565 p_hwcrhk_RSAGetPublicKey = p6;
566 p_hwcrhk_RSAUnloadKey = p7;
568 p_hwcrhk_RandomBytes = p8;
569 p_hwcrhk_ModExpCRT = p9;
571 /* Check if the application decided to support dynamic locks,
572 and if it does, use them. */
573 if (disable_mutex_callbacks == 0)
575 if (CRYPTO_get_dynlock_create_callback() != NULL &&
576 CRYPTO_get_dynlock_lock_callback() != NULL &&
577 CRYPTO_get_dynlock_destroy_callback() != NULL)
579 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
580 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
581 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
582 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
584 else if (CRYPTO_get_locking_callback() != NULL)
586 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_LOCKING_MISSING);
587 ERR_add_error_data(1,"You HAVE to add dynamic locking callbacks via CRYPTO_set_dynlock_{create,lock,destroy}_callback()");
592 /* Try and get a context - if not, we may have a DSO but no
594 if(!get_context(&hwcrhk_context, &password_context))
596 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
599 /* Everything's fine. */
600 #ifndef OPENSSL_NO_RSA
601 if (hndidx_rsa == -1)
602 hndidx_rsa = RSA_get_ex_new_index(0,
603 "nFast HWCryptoHook RSA key handle",
604 NULL, NULL, hwcrhk_ex_free);
609 DSO_free(hwcrhk_dso);
611 p_hwcrhk_Init = NULL;
612 p_hwcrhk_Finish = NULL;
613 p_hwcrhk_ModExp = NULL;
614 #ifndef OPENSSL_NO_RSA
616 p_hwcrhk_RSALoadKey = NULL;
617 p_hwcrhk_RSAGetPublicKey = NULL;
618 p_hwcrhk_RSAUnloadKey = NULL;
620 p_hwcrhk_ModExpCRT = NULL;
621 p_hwcrhk_RandomBytes = NULL;
625 static int hwcrhk_finish(ENGINE *e)
628 free_HWCRHK_LIBNAME();
629 if(hwcrhk_dso == NULL)
631 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
635 release_context(hwcrhk_context);
636 if(!DSO_free(hwcrhk_dso))
638 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
646 p_hwcrhk_Init = NULL;
647 p_hwcrhk_Finish = NULL;
648 p_hwcrhk_ModExp = NULL;
649 #ifndef OPENSSL_NO_RSA
651 p_hwcrhk_RSALoadKey = NULL;
652 p_hwcrhk_RSAGetPublicKey = NULL;
653 p_hwcrhk_RSAUnloadKey = NULL;
655 p_hwcrhk_ModExpCRT = NULL;
656 p_hwcrhk_RandomBytes = NULL;
660 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
666 case HWCRHK_CMD_SO_PATH:
669 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
674 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
677 return set_HWCRHK_LIBNAME((const char *)p);
678 case ENGINE_CTRL_SET_LOGSTREAM:
682 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
688 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
691 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
693 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
695 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
696 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
697 password_context.password_callback = (pem_password_cb *)f;
698 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
700 case ENGINE_CTRL_SET_USER_INTERFACE:
701 case HWCRHK_CMD_SET_USER_INTERFACE:
702 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
703 password_context.ui_method = (UI_METHOD *)p;
704 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
706 case ENGINE_CTRL_SET_CALLBACK_DATA:
707 case HWCRHK_CMD_SET_CALLBACK_DATA:
708 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
709 password_context.callback_data = p;
710 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
712 /* this enables or disables the "SimpleForkCheck" flag used in the
713 * initialisation structure. */
714 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
715 case HWCRHK_CMD_FORK_CHECK:
716 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
718 hwcrhk_globals.flags |=
719 HWCryptoHook_InitFlags_SimpleForkCheck;
721 hwcrhk_globals.flags &=
722 ~HWCryptoHook_InitFlags_SimpleForkCheck;
723 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. */
730 case ENGINE_CTRL_CHIL_NO_LOCKING:
731 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
732 disable_mutex_callbacks = 1;
733 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
735 case HWCRHK_CMD_THREAD_LOCKING:
736 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
737 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
738 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
741 /* The command isn't understood by this engine */
743 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
744 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
752 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
753 UI_METHOD *ui_method, void *callback_data)
755 #ifndef OPENSSL_NO_RSA
758 EVP_PKEY *res = NULL;
759 #ifndef OPENSSL_NO_RSA
760 HWCryptoHook_MPI e, n;
761 HWCryptoHook_RSAKeyHandle *hptr;
763 #if !defined(OPENSSL_NO_RSA)
765 HWCryptoHook_ErrMsgBuf rmsg;
767 HWCryptoHook_PassphraseContext ppctx;
769 #if !defined(OPENSSL_NO_RSA)
771 rmsg.size = sizeof(tempbuf);
776 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
777 HWCRHK_R_NOT_INITIALISED);
780 #ifndef OPENSSL_NO_RSA
781 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
784 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
785 ERR_R_MALLOC_FAILURE);
788 ppctx.ui_method = ui_method;
789 ppctx.callback_data = callback_data;
790 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
793 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
794 HWCRHK_R_CHIL_ERROR);
795 ERR_add_error_data(1,rmsg.buf);
800 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
805 #ifndef OPENSSL_NO_RSA
806 rtmp = RSA_new_method(eng);
807 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
810 rtmp->flags |= RSA_FLAG_EXT_PKEY;
813 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
814 != HWCRYPTOHOOK_ERROR_MPISIZE)
816 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,HWCRHK_R_CHIL_ERROR);
817 ERR_add_error_data(1,rmsg.buf);
821 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
822 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
826 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
828 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
829 HWCRHK_R_CHIL_ERROR);
830 ERR_add_error_data(1,rmsg.buf);
833 rtmp->e->top = e.size / sizeof(BN_ULONG);
835 rtmp->n->top = n.size / sizeof(BN_ULONG);
838 res = EVP_PKEY_new();
839 EVP_PKEY_assign_RSA(res, rtmp);
843 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
844 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
850 #ifndef OPENSSL_NO_RSA
857 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
858 UI_METHOD *ui_method, void *callback_data)
860 EVP_PKEY *res = NULL;
862 #ifndef OPENSSL_NO_RSA
863 res = hwcrhk_load_privkey(eng, key_id,
864 ui_method, callback_data);
870 #ifndef OPENSSL_NO_RSA
875 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
877 res->pkey.rsa = RSA_new();
878 res->pkey.rsa->n = rsa->n;
879 res->pkey.rsa->e = rsa->e;
882 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
888 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
889 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
900 /* A little mod_exp */
901 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
902 const BIGNUM *m, BN_CTX *ctx)
905 HWCryptoHook_ErrMsgBuf rmsg;
906 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
907 we use them directly, plus a little macro magic. We only
908 thing we need to make sure of is that enough space is allocated. */
909 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
912 to_return = 0; /* expect failure */
914 rmsg.size = sizeof(tempbuf);
918 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
921 /* Prepare the params */
922 bn_expand2(r, m->top); /* Check for error !! */
928 /* Perform the operation */
929 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
931 /* Convert the response */
932 r->top = m_r.size / sizeof(BN_ULONG);
937 /* FIXME: When this error is returned, HWCryptoHook is
938 telling us that falling back to software computation
939 might be a good thing. */
940 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
942 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
946 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
948 ERR_add_error_data(1,rmsg.buf);
957 #ifndef OPENSSL_NO_RSA
958 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
961 HWCryptoHook_ErrMsgBuf rmsg;
962 HWCryptoHook_RSAKeyHandle *hptr;
963 int to_return = 0, ret;
966 rmsg.size = sizeof(tempbuf);
970 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
974 /* This provides support for nForce keys. Since that's opaque data
975 all we do is provide a handle to the proper key and let HWCryptoHook
976 take care of the rest. */
977 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
980 HWCryptoHook_MPI m_a, m_r;
984 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
985 HWCRHK_R_MISSING_KEY_COMPONENTS);
989 /* Prepare the params */
990 bn_expand2(r, rsa->n->top); /* Check for error !! */
994 /* Perform the operation */
995 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
997 /* Convert the response */
998 r->top = m_r.size / sizeof(BN_ULONG);
1003 /* FIXME: When this error is returned, HWCryptoHook is
1004 telling us that falling back to software computation
1005 might be a good thing. */
1006 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1008 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1009 HWCRHK_R_REQUEST_FALLBACK);
1013 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1014 HWCRHK_R_REQUEST_FAILED);
1016 ERR_add_error_data(1,rmsg.buf);
1022 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1024 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1026 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1027 HWCRHK_R_MISSING_KEY_COMPONENTS);
1031 /* Prepare the params */
1032 bn_expand2(r, rsa->n->top); /* Check for error !! */
1034 BN2MPI(m_p, rsa->p);
1035 BN2MPI(m_q, rsa->q);
1036 BN2MPI(m_dmp1, rsa->dmp1);
1037 BN2MPI(m_dmq1, rsa->dmq1);
1038 BN2MPI(m_iqmp, rsa->iqmp);
1041 /* Perform the operation */
1042 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1043 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1045 /* Convert the response */
1046 r->top = m_r.size / sizeof(BN_ULONG);
1051 /* FIXME: When this error is returned, HWCryptoHook is
1052 telling us that falling back to software computation
1053 might be a good thing. */
1054 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1056 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1057 HWCRHK_R_REQUEST_FALLBACK);
1061 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1062 HWCRHK_R_REQUEST_FAILED);
1064 ERR_add_error_data(1,rmsg.buf);
1068 /* If we're here, we must be here with some semblance of success :-) */
1075 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1076 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1077 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1079 return hwcrhk_mod_exp(r, a, p, m, ctx);
1082 #ifndef OPENSSL_NO_DH
1083 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1084 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1085 const BIGNUM *a, const BIGNUM *p,
1086 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1088 return hwcrhk_mod_exp(r, a, p, m, ctx);
1092 /* Random bytes are good */
1093 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1096 HWCryptoHook_ErrMsgBuf rmsg;
1097 int to_return = 0; /* assume failure */
1101 rmsg.size = sizeof(tempbuf);
1105 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1109 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1112 /* FIXME: When this error is returned, HWCryptoHook is
1113 telling us that falling back to software computation
1114 might be a good thing. */
1115 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1117 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1118 HWCRHK_R_REQUEST_FALLBACK);
1122 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1123 HWCRHK_R_REQUEST_FAILED);
1125 ERR_add_error_data(1,rmsg.buf);
1133 static int hwcrhk_rand_status(void)
1138 /* This cleans up an RSA KM key, called when ex_data is freed */
1140 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1141 int ind,long argl, void *argp)
1144 HWCryptoHook_ErrMsgBuf rmsg;
1145 #ifndef OPENSSL_NO_RSA
1146 HWCryptoHook_RSAKeyHandle *hptr;
1148 #if !defined(OPENSSL_NO_RSA)
1153 rmsg.size = sizeof(tempbuf);
1155 #ifndef OPENSSL_NO_RSA
1156 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1159 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1165 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1166 * these just wrap the POSIX functions and add some logging.
1169 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1170 HWCryptoHook_CallerContext *cactx)
1172 mt->lockid = CRYPTO_get_new_dynlockid();
1173 if (mt->lockid == 0)
1174 return 1; /* failure */
1175 return 0; /* success */
1178 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1180 CRYPTO_w_lock(mt->lockid);
1184 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1186 CRYPTO_w_unlock(mt->lockid);
1189 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1191 CRYPTO_destroy_dynlockid(mt->lockid);
1194 static int hwcrhk_get_pass(const char *prompt_info,
1195 int *len_io, char *buf,
1196 HWCryptoHook_PassphraseContext *ppctx,
1197 HWCryptoHook_CallerContext *cactx)
1199 pem_password_cb *callback = NULL;
1200 void *callback_data = NULL;
1201 UI_METHOD *ui_method = NULL;
1205 if (cactx->ui_method)
1206 ui_method = cactx->ui_method;
1207 if (cactx->password_callback)
1208 callback = cactx->password_callback;
1209 if (cactx->callback_data)
1210 callback_data = cactx->callback_data;
1214 if (ppctx->ui_method)
1216 ui_method = ppctx->ui_method;
1219 if (ppctx->callback_data)
1220 callback_data = ppctx->callback_data;
1222 if (callback == NULL && ui_method == NULL)
1224 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1230 UI *ui = UI_new_method(ui_method);
1234 char *prompt = UI_construct_prompt(ui,
1235 "pass phrase", prompt_info);
1237 ok = UI_add_input_string(ui,prompt,
1238 UI_INPUT_FLAG_DEFAULT_PWD,
1239 buf,0,(*len_io) - 1);
1240 UI_add_user_data(ui, callback_data);
1241 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1248 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1251 *len_io = strlen(buf);
1254 OPENSSL_free(prompt);
1259 *len_io = callback(buf, *len_io, 0, callback_data);
1266 static int hwcrhk_insert_card(const char *prompt_info,
1267 const char *wrong_info,
1268 HWCryptoHook_PassphraseContext *ppctx,
1269 HWCryptoHook_CallerContext *cactx)
1273 void *callback_data = NULL;
1274 UI_METHOD *ui_method = NULL;
1278 if (cactx->ui_method)
1279 ui_method = cactx->ui_method;
1280 if (cactx->callback_data)
1281 callback_data = cactx->callback_data;
1285 if (ppctx->ui_method)
1286 ui_method = ppctx->ui_method;
1287 if (ppctx->callback_data)
1288 callback_data = ppctx->callback_data;
1290 if (ui_method == NULL)
1292 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1293 HWCRHK_R_NO_CALLBACK);
1297 ui = UI_new_method(ui_method);
1305 BIO_snprintf(buf, sizeof(buf)-1,
1306 "Current card: \"%s\"\n", wrong_info);
1307 ok = UI_dup_info_string(ui, buf);
1308 if (ok >= 0 && prompt_info)
1310 BIO_snprintf(buf, sizeof(buf)-1,
1311 "Insert card \"%s\"", prompt_info);
1312 ok = UI_dup_input_boolean(ui, buf,
1313 "\n then hit <enter> or C<enter> to cancel\n",
1314 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1316 UI_add_user_data(ui, callback_data);
1319 ok = UI_process(ui);
1322 if (ok == -2 || (ok >= 0 && answer == 'C'))
1332 static void hwcrhk_log_message(void *logstr, const char *message)
1334 BIO *lstream = NULL;
1336 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1338 lstream=*(BIO **)logstr;
1341 BIO_printf(lstream, "%s\n", message);
1343 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1346 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1347 * shared-library. */
1348 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1349 static int bind_fn(ENGINE *e, const char *id)
1351 if(id && (strcmp(id, engine_hwcrhk_id) != 0) &&
1352 (strcmp(id, engine_hwcrhk_id_alt) != 0))
1358 IMPLEMENT_DYNAMIC_CHECK_FN()
1359 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1360 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1362 #endif /* !OPENSSL_NO_HW_CHIL */
1363 #endif /* !OPENSSL_NO_HW */