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 #ifndef OPENSSL_NO_RSA
69 #include <openssl/rsa.h>
72 #include <openssl/dh.h>
74 #include <openssl/bn.h>
77 #ifndef OPENSSL_NO_HW_CHIL
79 /* Attribution notice: nCipher have said several times that it's OK for
80 * us to implement a general interface to their boxes, and recently declared
81 * their HWCryptoHook to be public, and therefore available for us to use.
84 * The hwcryptohook.h included here is from May 2000.
88 #include "hwcryptohook.h"
90 #include "vendor_defns/hwcryptohook.h"
93 #define HWCRHK_LIB_NAME "CHIL engine"
94 #include "e_chil_err.c"
96 static int hwcrhk_destroy(ENGINE *e);
97 static int hwcrhk_init(ENGINE *e);
98 static int hwcrhk_finish(ENGINE *e);
99 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
101 /* Functions to handle mutexes */
102 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
103 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
104 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
105 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
108 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
109 const BIGNUM *m, BN_CTX *ctx);
111 #ifndef OPENSSL_NO_RSA
113 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
115 #ifndef OPENSSL_NO_RSA
116 /* This function is aliased to mod_exp (with the mont stuff dropped). */
117 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
118 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
121 #ifndef OPENSSL_NO_DH
123 /* This function is alised to mod_exp (with the DH and mont dropped). */
124 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
125 const BIGNUM *a, const BIGNUM *p,
126 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
130 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
131 static int hwcrhk_rand_status(void);
134 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
135 UI_METHOD *ui_method, void *callback_data);
136 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
137 UI_METHOD *ui_method, void *callback_data);
138 #ifndef OPENSSL_NO_RSA
139 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
140 int ind,long argl, void *argp);
143 /* Interaction stuff */
144 static int hwcrhk_insert_card(const char *prompt_info,
145 const char *wrong_info,
146 HWCryptoHook_PassphraseContext *ppctx,
147 HWCryptoHook_CallerContext *cactx);
148 static int hwcrhk_get_pass(const char *prompt_info,
149 int *len_io, char *buf,
150 HWCryptoHook_PassphraseContext *ppctx,
151 HWCryptoHook_CallerContext *cactx);
152 static void hwcrhk_log_message(void *logstr, const char *message);
154 /* The definitions for control commands specific to this engine */
155 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
156 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
157 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
158 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
159 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
160 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
163 "Specifies the path to the 'hwcrhk' shared library",
164 ENGINE_CMD_FLAG_STRING},
165 {HWCRHK_CMD_FORK_CHECK,
167 "Turns fork() checking on or off (boolean)",
168 ENGINE_CMD_FLAG_NUMERIC},
169 {HWCRHK_CMD_THREAD_LOCKING,
171 "Turns thread-safe locking on or off (boolean)",
172 ENGINE_CMD_FLAG_NUMERIC},
173 {HWCRHK_CMD_SET_USER_INTERFACE,
174 "SET_USER_INTERFACE",
175 "Set the global user interface (internal)",
176 ENGINE_CMD_FLAG_INTERNAL},
177 {HWCRHK_CMD_SET_CALLBACK_DATA,
179 "Set the global user interface extra data (internal)",
180 ENGINE_CMD_FLAG_INTERNAL},
184 #ifndef OPENSSL_NO_RSA
185 /* Our internal RSA_METHOD that we provide pointers to */
186 static RSA_METHOD hwcrhk_rsa =
205 #ifndef OPENSSL_NO_DH
206 /* Our internal DH_METHOD that we provide pointers to */
207 static DH_METHOD hwcrhk_dh =
221 static RAND_METHOD hwcrhk_rand =
223 /* "CHIL RAND method", */
232 /* Constants used when creating the ENGINE */
233 static const char *engine_hwcrhk_id = "chil";
234 static const char *engine_hwcrhk_name = "CHIL hardware engine support";
235 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
236 /* Compatibility hack, the dynamic library uses this form in the path */
237 static const char *engine_hwcrhk_id_alt = "ncipher";
240 /* Internal stuff for HWCryptoHook */
242 /* Some structures needed for proper use of thread locks */
243 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
244 into HWCryptoHook_Mutex */
245 struct HWCryptoHook_MutexValue
250 /* hwcryptohook.h has some typedefs that turn
251 struct HWCryptoHook_PassphraseContextValue
252 into HWCryptoHook_PassphraseContext */
253 struct HWCryptoHook_PassphraseContextValue
255 UI_METHOD *ui_method;
259 /* hwcryptohook.h has some typedefs that turn
260 struct HWCryptoHook_CallerContextValue
261 into HWCryptoHook_CallerContext */
262 struct HWCryptoHook_CallerContextValue
264 pem_password_cb *password_callback; /* Deprecated! Only present for
265 backward compatibility! */
266 UI_METHOD *ui_method;
270 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
271 BIGNUM's, so lets define a couple of conversion macros */
272 #define BN2MPI(mp, bn) \
273 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
274 #define MPI2BN(bn, mp) \
275 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
277 static BIO *logstream = NULL;
278 static int disable_mutex_callbacks = 0;
280 /* One might wonder why these are needed, since one can pass down at least
281 a UI_METHOD and a pointer to callback data to the key-loading functions.
282 The thing is that the ModExp and RSAImmed functions can load keys as well,
283 if the data they get is in a special, nCipher-defined format (hint: if you
284 look at the private exponent of the RSA data as a string, you'll see this
285 string: "nCipher KM tool key id", followed by some bytes, followed a key
286 identity string, followed by more bytes. This happens when you use "embed"
287 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
288 any passphrase or caller context, and our functions can't really take any
289 callback data either. Still, the "insert_card" and "get_passphrase"
290 callbacks may be called down the line, and will need to know what user
291 interface callbacks to call, and having callback data from the application
292 may be a nice thing as well, so we need to keep track of that globally. */
293 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
295 /* Stuff to pass to the HWCryptoHook library */
296 static HWCryptoHook_InitInfo hwcrhk_globals = {
297 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
298 &logstream, /* logstream */
299 sizeof(BN_ULONG), /* limbsize */
300 0, /* mslimb first: false for BNs */
301 -1, /* msbyte first: use native */
302 0, /* Max mutexes, 0 = no small limit */
303 0, /* Max simultaneous, 0 = default */
305 /* The next few are mutex stuff: we write wrapper functions
306 around the OS mutex functions. We initialise them to 0
307 here, and change that to actual function pointers in hwcrhk_init()
308 if dynamic locks are supported (that is, if the application
309 programmer has made sure of setting up callbacks bafore starting
310 this engine) *and* if disable_mutex_callbacks hasn't been set by
311 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
312 sizeof(HWCryptoHook_Mutex),
318 /* The next few are condvar stuff: we write wrapper functions
319 round the OS functions. Currently not implemented and not
320 and absolute necessity even in threaded programs, therefore
321 0'ed. Will hopefully be implemented some day, since it
322 enhances the efficiency of HWCryptoHook. */
323 0, /* sizeof(HWCryptoHook_CondVar), */
324 0, /* hwcrhk_cv_init, */
325 0, /* hwcrhk_cv_wait, */
326 0, /* hwcrhk_cv_signal, */
327 0, /* hwcrhk_cv_broadcast, */
328 0, /* hwcrhk_cv_destroy, */
330 hwcrhk_get_pass, /* pass phrase */
331 hwcrhk_insert_card, /* insert a card */
332 hwcrhk_log_message /* Log message */
336 /* Now, to our own code */
338 /* This internal function is used by ENGINE_chil() and possibly by the
339 * "dynamic" ENGINE support too */
340 static int bind_helper(ENGINE *e)
342 #ifndef OPENSSL_NO_RSA
343 const RSA_METHOD *meth1;
345 #ifndef OPENSSL_NO_DH
346 const DH_METHOD *meth2;
348 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
349 !ENGINE_set_name(e, engine_hwcrhk_name) ||
350 #ifndef OPENSSL_NO_RSA
351 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
353 #ifndef OPENSSL_NO_DH
354 !ENGINE_set_DH(e, &hwcrhk_dh) ||
356 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
357 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
358 !ENGINE_set_init_function(e, hwcrhk_init) ||
359 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
360 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
361 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
362 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
363 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
366 #ifndef OPENSSL_NO_RSA
367 /* We know that the "PKCS1_SSLeay()" functions hook properly
368 * to the cswift-specific mod_exp and mod_exp_crt so we use
369 * those functions. NB: We don't use ENGINE_openssl() or
370 * anything "more generic" because something like the RSAref
371 * code may not hook properly, and if you own one of these
372 * cards then you have the right to do RSA operations on it
374 meth1 = RSA_PKCS1_SSLeay();
375 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
376 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
377 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
378 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
381 #ifndef OPENSSL_NO_DH
382 /* Much the same for Diffie-Hellman */
383 meth2 = DH_OpenSSL();
384 hwcrhk_dh.generate_key = meth2->generate_key;
385 hwcrhk_dh.compute_key = meth2->compute_key;
388 /* Ensure the hwcrhk error handling is set up */
389 ERR_load_HWCRHK_strings();
393 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
394 static ENGINE *engine_chil(void)
396 ENGINE *ret = ENGINE_new();
399 if(!bind_helper(ret))
407 void ENGINE_load_chil(void)
409 /* Copied from eng_[openssl|dyn].c */
410 ENGINE *toadd = engine_chil();
418 /* This is a process-global DSO handle used for loading and unloading
419 * the HWCryptoHook library. NB: This is only set (or unset) during an
420 * init() or finish() call (reference counts permitting) and they're
421 * operating with global locks, so this should be thread-safe
423 static DSO *hwcrhk_dso = NULL;
424 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
425 #ifndef OPENSSL_NO_RSA
426 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
429 /* These are the function pointers that are (un)set when the library has
430 * successfully (un)loaded. */
431 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
432 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
433 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
434 #ifndef OPENSSL_NO_RSA
435 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
437 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
438 #ifndef OPENSSL_NO_RSA
439 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
440 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
441 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
443 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
445 /* Used in the DSO operations. */
446 static const char *HWCRHK_LIBNAME = NULL;
447 static void free_HWCRHK_LIBNAME(void)
450 OPENSSL_free((void*)HWCRHK_LIBNAME);
451 HWCRHK_LIBNAME = NULL;
453 static const char *get_HWCRHK_LIBNAME(void)
456 return HWCRHK_LIBNAME;
459 static long set_HWCRHK_LIBNAME(const char *name)
461 free_HWCRHK_LIBNAME();
462 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
464 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
465 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
466 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
467 #ifndef OPENSSL_NO_RSA
468 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
470 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
471 #ifndef OPENSSL_NO_RSA
472 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
473 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
474 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
476 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
478 /* HWCryptoHook library functions and mechanics - these are used by the
479 * higher-level functions further down. NB: As and where there's no
480 * error checking, take a look lower down where these functions are
481 * called, the checking and error handling is probably down there. */
483 /* utility function to obtain a context */
484 static int get_context(HWCryptoHook_ContextHandle *hac,
485 HWCryptoHook_CallerContext *cac)
488 HWCryptoHook_ErrMsgBuf rmsg;
491 rmsg.size = sizeof(tempbuf);
493 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
500 /* similarly to release one. */
501 static void release_context(HWCryptoHook_ContextHandle hac)
503 p_hwcrhk_Finish(hac);
506 /* Destructor (complements the "ENGINE_chil()" constructor) */
507 static int hwcrhk_destroy(ENGINE *e)
509 free_HWCRHK_LIBNAME();
510 ERR_unload_HWCRHK_strings();
514 /* (de)initialisation functions. */
515 static int hwcrhk_init(ENGINE *e)
517 HWCryptoHook_Init_t *p1;
518 HWCryptoHook_Finish_t *p2;
519 HWCryptoHook_ModExp_t *p3;
520 #ifndef OPENSSL_NO_RSA
521 HWCryptoHook_RSA_t *p4;
522 HWCryptoHook_RSALoadKey_t *p5;
523 HWCryptoHook_RSAGetPublicKey_t *p6;
524 HWCryptoHook_RSAUnloadKey_t *p7;
526 HWCryptoHook_RandomBytes_t *p8;
527 HWCryptoHook_ModExpCRT_t *p9;
529 if(hwcrhk_dso != NULL)
531 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
534 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
535 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
536 if(hwcrhk_dso == NULL)
538 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
541 if(!(p1 = (HWCryptoHook_Init_t *)
542 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
543 !(p2 = (HWCryptoHook_Finish_t *)
544 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
545 !(p3 = (HWCryptoHook_ModExp_t *)
546 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
547 #ifndef OPENSSL_NO_RSA
548 !(p4 = (HWCryptoHook_RSA_t *)
549 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
550 !(p5 = (HWCryptoHook_RSALoadKey_t *)
551 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
552 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
553 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
554 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
555 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
557 !(p8 = (HWCryptoHook_RandomBytes_t *)
558 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
559 !(p9 = (HWCryptoHook_ModExpCRT_t *)
560 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
562 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
565 /* Copy the pointers */
567 p_hwcrhk_Finish = p2;
568 p_hwcrhk_ModExp = p3;
569 #ifndef OPENSSL_NO_RSA
571 p_hwcrhk_RSALoadKey = p5;
572 p_hwcrhk_RSAGetPublicKey = p6;
573 p_hwcrhk_RSAUnloadKey = p7;
575 p_hwcrhk_RandomBytes = p8;
576 p_hwcrhk_ModExpCRT = p9;
578 /* Check if the application decided to support dynamic locks,
579 and if it does, use them. */
580 if (disable_mutex_callbacks == 0)
582 if (CRYPTO_get_dynlock_create_callback() != NULL &&
583 CRYPTO_get_dynlock_lock_callback() != NULL &&
584 CRYPTO_get_dynlock_destroy_callback() != NULL)
586 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
587 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
588 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
589 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
591 else if (CRYPTO_get_locking_callback() != NULL)
593 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_LOCKING_MISSING);
594 ERR_add_error_data(1,"You HAVE to add dynamic locking callbacks via CRYPTO_set_dynlock_{create,lock,destroy}_callback()");
599 /* Try and get a context - if not, we may have a DSO but no
601 if(!get_context(&hwcrhk_context, &password_context))
603 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
606 /* Everything's fine. */
607 #ifndef OPENSSL_NO_RSA
608 if (hndidx_rsa == -1)
609 hndidx_rsa = RSA_get_ex_new_index(0,
610 "nFast HWCryptoHook RSA key handle",
611 NULL, NULL, hwcrhk_ex_free);
616 DSO_free(hwcrhk_dso);
618 p_hwcrhk_Init = NULL;
619 p_hwcrhk_Finish = NULL;
620 p_hwcrhk_ModExp = NULL;
621 #ifndef OPENSSL_NO_RSA
623 p_hwcrhk_RSALoadKey = NULL;
624 p_hwcrhk_RSAGetPublicKey = NULL;
625 p_hwcrhk_RSAUnloadKey = NULL;
627 p_hwcrhk_ModExpCRT = NULL;
628 p_hwcrhk_RandomBytes = NULL;
632 static int hwcrhk_finish(ENGINE *e)
635 free_HWCRHK_LIBNAME();
636 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))
645 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
653 p_hwcrhk_Init = NULL;
654 p_hwcrhk_Finish = NULL;
655 p_hwcrhk_ModExp = NULL;
656 #ifndef OPENSSL_NO_RSA
658 p_hwcrhk_RSALoadKey = NULL;
659 p_hwcrhk_RSAGetPublicKey = NULL;
660 p_hwcrhk_RSAUnloadKey = NULL;
662 p_hwcrhk_ModExpCRT = NULL;
663 p_hwcrhk_RandomBytes = NULL;
667 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
673 case HWCRHK_CMD_SO_PATH:
676 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
681 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
684 return set_HWCRHK_LIBNAME((const char *)p);
685 case ENGINE_CTRL_SET_LOGSTREAM:
689 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
695 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
698 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
700 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
702 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
703 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
704 password_context.password_callback = (pem_password_cb *)f;
705 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
707 case ENGINE_CTRL_SET_USER_INTERFACE:
708 case HWCRHK_CMD_SET_USER_INTERFACE:
709 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
710 password_context.ui_method = (UI_METHOD *)p;
711 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
713 case ENGINE_CTRL_SET_CALLBACK_DATA:
714 case HWCRHK_CMD_SET_CALLBACK_DATA:
715 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
716 password_context.callback_data = p;
717 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
719 /* this enables or disables the "SimpleForkCheck" flag used in the
720 * initialisation structure. */
721 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
722 case HWCRHK_CMD_FORK_CHECK:
723 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
725 hwcrhk_globals.flags |=
726 HWCryptoHook_InitFlags_SimpleForkCheck;
728 hwcrhk_globals.flags &=
729 ~HWCryptoHook_InitFlags_SimpleForkCheck;
730 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
732 /* This will prevent the initialisation function from "installing"
733 * the mutex-handling callbacks, even if they are available from
734 * within the library (or were provided to the library from the
735 * calling application). This is to remove any baggage for
736 * applications not using multithreading. */
737 case ENGINE_CTRL_CHIL_NO_LOCKING:
738 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
739 disable_mutex_callbacks = 1;
740 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
742 case HWCRHK_CMD_THREAD_LOCKING:
743 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
744 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
745 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
748 /* The command isn't understood by this engine */
750 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
751 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
759 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
760 UI_METHOD *ui_method, void *callback_data)
762 #ifndef OPENSSL_NO_RSA
765 EVP_PKEY *res = NULL;
766 #ifndef OPENSSL_NO_RSA
767 HWCryptoHook_MPI e, n;
768 HWCryptoHook_RSAKeyHandle *hptr;
770 #if !defined(OPENSSL_NO_RSA)
772 HWCryptoHook_ErrMsgBuf rmsg;
773 HWCryptoHook_PassphraseContext ppctx;
776 #if !defined(OPENSSL_NO_RSA)
778 rmsg.size = sizeof(tempbuf);
783 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
784 HWCRHK_R_NOT_INITIALISED);
787 #ifndef OPENSSL_NO_RSA
788 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
791 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
792 ERR_R_MALLOC_FAILURE);
795 ppctx.ui_method = ui_method;
796 ppctx.callback_data = callback_data;
797 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
800 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
801 HWCRHK_R_CHIL_ERROR);
802 ERR_add_error_data(1,rmsg.buf);
807 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
812 #ifndef OPENSSL_NO_RSA
813 rtmp = RSA_new_method(eng);
814 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
817 rtmp->flags |= RSA_FLAG_EXT_PKEY;
820 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
821 != HWCRYPTOHOOK_ERROR_MPISIZE)
823 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,HWCRHK_R_CHIL_ERROR);
824 ERR_add_error_data(1,rmsg.buf);
828 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
829 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
833 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
835 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
836 HWCRHK_R_CHIL_ERROR);
837 ERR_add_error_data(1,rmsg.buf);
840 rtmp->e->top = e.size / sizeof(BN_ULONG);
842 rtmp->n->top = n.size / sizeof(BN_ULONG);
845 res = EVP_PKEY_new();
846 EVP_PKEY_assign_RSA(res, rtmp);
850 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
851 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
857 #ifndef OPENSSL_NO_RSA
864 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
865 UI_METHOD *ui_method, void *callback_data)
867 EVP_PKEY *res = NULL;
869 #ifndef OPENSSL_NO_RSA
870 res = hwcrhk_load_privkey(eng, key_id,
871 ui_method, callback_data);
877 #ifndef OPENSSL_NO_RSA
882 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
884 res->pkey.rsa = RSA_new();
885 res->pkey.rsa->n = rsa->n;
886 res->pkey.rsa->e = rsa->e;
889 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
895 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
896 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
907 /* A little mod_exp */
908 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
909 const BIGNUM *m, BN_CTX *ctx)
912 HWCryptoHook_ErrMsgBuf rmsg;
913 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
914 we use them directly, plus a little macro magic. We only
915 thing we need to make sure of is that enough space is allocated. */
916 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
919 to_return = 0; /* expect failure */
921 rmsg.size = sizeof(tempbuf);
925 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
928 /* Prepare the params */
929 bn_expand2(r, m->top); /* Check for error !! */
935 /* Perform the operation */
936 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
938 /* Convert the response */
939 r->top = m_r.size / sizeof(BN_ULONG);
944 /* FIXME: When this error is returned, HWCryptoHook is
945 telling us that falling back to software computation
946 might be a good thing. */
947 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
949 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
953 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
955 ERR_add_error_data(1,rmsg.buf);
964 #ifndef OPENSSL_NO_RSA
965 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
968 HWCryptoHook_ErrMsgBuf rmsg;
969 HWCryptoHook_RSAKeyHandle *hptr;
970 int to_return = 0, ret;
973 rmsg.size = sizeof(tempbuf);
977 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
981 /* This provides support for nForce keys. Since that's opaque data
982 all we do is provide a handle to the proper key and let HWCryptoHook
983 take care of the rest. */
984 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
987 HWCryptoHook_MPI m_a, m_r;
991 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
992 HWCRHK_R_MISSING_KEY_COMPONENTS);
996 /* Prepare the params */
997 bn_expand2(r, rsa->n->top); /* Check for error !! */
1001 /* Perform the operation */
1002 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
1004 /* Convert the response */
1005 r->top = m_r.size / sizeof(BN_ULONG);
1010 /* FIXME: When this error is returned, HWCryptoHook is
1011 telling us that falling back to software computation
1012 might be a good thing. */
1013 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1015 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1016 HWCRHK_R_REQUEST_FALLBACK);
1020 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1021 HWCRHK_R_REQUEST_FAILED);
1023 ERR_add_error_data(1,rmsg.buf);
1029 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1031 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1033 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1034 HWCRHK_R_MISSING_KEY_COMPONENTS);
1038 /* Prepare the params */
1039 bn_expand2(r, rsa->n->top); /* Check for error !! */
1041 BN2MPI(m_p, rsa->p);
1042 BN2MPI(m_q, rsa->q);
1043 BN2MPI(m_dmp1, rsa->dmp1);
1044 BN2MPI(m_dmq1, rsa->dmq1);
1045 BN2MPI(m_iqmp, rsa->iqmp);
1048 /* Perform the operation */
1049 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1050 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1052 /* Convert the response */
1053 r->top = m_r.size / sizeof(BN_ULONG);
1058 /* FIXME: When this error is returned, HWCryptoHook is
1059 telling us that falling back to software computation
1060 might be a good thing. */
1061 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1063 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1064 HWCRHK_R_REQUEST_FALLBACK);
1068 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1069 HWCRHK_R_REQUEST_FAILED);
1071 ERR_add_error_data(1,rmsg.buf);
1075 /* If we're here, we must be here with some semblance of success :-) */
1082 #ifndef OPENSSL_NO_RSA
1083 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1084 static int hwcrhk_mod_exp_mont(BIGNUM *r, 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 #ifndef OPENSSL_NO_DH
1092 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1093 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1094 const BIGNUM *a, const BIGNUM *p,
1095 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1097 return hwcrhk_mod_exp(r, a, p, m, ctx);
1101 /* Random bytes are good */
1102 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1105 HWCryptoHook_ErrMsgBuf rmsg;
1106 int to_return = 0; /* assume failure */
1110 rmsg.size = sizeof(tempbuf);
1114 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1118 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1121 /* FIXME: When this error is returned, HWCryptoHook is
1122 telling us that falling back to software computation
1123 might be a good thing. */
1124 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1126 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1127 HWCRHK_R_REQUEST_FALLBACK);
1131 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1132 HWCRHK_R_REQUEST_FAILED);
1134 ERR_add_error_data(1,rmsg.buf);
1142 static int hwcrhk_rand_status(void)
1147 /* This cleans up an RSA KM key, called when ex_data is freed */
1148 #ifndef OPENSSL_NO_RSA
1149 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1150 int ind,long argl, void *argp)
1153 HWCryptoHook_ErrMsgBuf rmsg;
1154 #ifndef OPENSSL_NO_RSA
1155 HWCryptoHook_RSAKeyHandle *hptr;
1157 #if !defined(OPENSSL_NO_RSA)
1162 rmsg.size = sizeof(tempbuf);
1164 #ifndef OPENSSL_NO_RSA
1165 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1168 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1175 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1176 * these just wrap the POSIX functions and add some logging.
1179 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1180 HWCryptoHook_CallerContext *cactx)
1182 mt->lockid = CRYPTO_get_new_dynlockid();
1183 if (mt->lockid == 0)
1184 return 1; /* failure */
1185 return 0; /* success */
1188 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1190 CRYPTO_w_lock(mt->lockid);
1194 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1196 CRYPTO_w_unlock(mt->lockid);
1199 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1201 CRYPTO_destroy_dynlockid(mt->lockid);
1204 static int hwcrhk_get_pass(const char *prompt_info,
1205 int *len_io, char *buf,
1206 HWCryptoHook_PassphraseContext *ppctx,
1207 HWCryptoHook_CallerContext *cactx)
1209 pem_password_cb *callback = NULL;
1210 void *callback_data = NULL;
1211 UI_METHOD *ui_method = NULL;
1215 if (cactx->ui_method)
1216 ui_method = cactx->ui_method;
1217 if (cactx->password_callback)
1218 callback = cactx->password_callback;
1219 if (cactx->callback_data)
1220 callback_data = cactx->callback_data;
1224 if (ppctx->ui_method)
1226 ui_method = ppctx->ui_method;
1229 if (ppctx->callback_data)
1230 callback_data = ppctx->callback_data;
1232 if (callback == NULL && ui_method == NULL)
1234 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1240 UI *ui = UI_new_method(ui_method);
1244 char *prompt = UI_construct_prompt(ui,
1245 "pass phrase", prompt_info);
1247 ok = UI_add_input_string(ui,prompt,
1248 UI_INPUT_FLAG_DEFAULT_PWD,
1249 buf,0,(*len_io) - 1);
1250 UI_add_user_data(ui, callback_data);
1251 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1258 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1261 *len_io = strlen(buf);
1264 OPENSSL_free(prompt);
1269 *len_io = callback(buf, *len_io, 0, callback_data);
1276 static int hwcrhk_insert_card(const char *prompt_info,
1277 const char *wrong_info,
1278 HWCryptoHook_PassphraseContext *ppctx,
1279 HWCryptoHook_CallerContext *cactx)
1283 void *callback_data = NULL;
1284 UI_METHOD *ui_method = NULL;
1288 if (cactx->ui_method)
1289 ui_method = cactx->ui_method;
1290 if (cactx->callback_data)
1291 callback_data = cactx->callback_data;
1295 if (ppctx->ui_method)
1296 ui_method = ppctx->ui_method;
1297 if (ppctx->callback_data)
1298 callback_data = ppctx->callback_data;
1300 if (ui_method == NULL)
1302 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1303 HWCRHK_R_NO_CALLBACK);
1307 ui = UI_new_method(ui_method);
1315 BIO_snprintf(buf, sizeof(buf)-1,
1316 "Current card: \"%s\"\n", wrong_info);
1317 ok = UI_dup_info_string(ui, buf);
1318 if (ok >= 0 && prompt_info)
1320 BIO_snprintf(buf, sizeof(buf)-1,
1321 "Insert card \"%s\"", prompt_info);
1322 ok = UI_dup_input_boolean(ui, buf,
1323 "\n then hit <enter> or C<enter> to cancel\n",
1324 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1326 UI_add_user_data(ui, callback_data);
1329 ok = UI_process(ui);
1332 if (ok == -2 || (ok >= 0 && answer == 'C'))
1342 static void hwcrhk_log_message(void *logstr, const char *message)
1344 BIO *lstream = NULL;
1346 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1348 lstream=*(BIO **)logstr;
1351 BIO_printf(lstream, "%s\n", message);
1353 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1356 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1357 * shared-library. */
1358 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1359 static int bind_fn(ENGINE *e, const char *id)
1361 if(id && (strcmp(id, engine_hwcrhk_id) != 0) &&
1362 (strcmp(id, engine_hwcrhk_id_alt) != 0))
1368 IMPLEMENT_DYNAMIC_CHECK_FN()
1369 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1370 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1372 #endif /* !OPENSSL_NO_HW_CHIL */
1373 #endif /* !OPENSSL_NO_HW */