1 /* crypto/engine/hw_ncipher.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).
63 #include <openssl/crypto.h>
64 #include <openssl/pem.h>
65 #include <openssl/dso.h>
66 #include <openssl/engine.h>
67 #include <openssl/ui.h>
70 #ifndef OPENSSL_NO_HW_NCIPHER
72 /* Attribution notice: nCipher have said several times that it's OK for
73 * us to implement a general interface to their boxes, and recently declared
74 * their HWCryptoHook to be public, and therefore available for us to use.
77 * The hwcryptohook.h included here is from May 2000.
81 #include "hwcryptohook.h"
83 #include "vendor_defns/hwcryptohook.h"
86 #define HWCRHK_LIB_NAME "hwcrhk engine"
87 #include "hw_ncipher_err.c"
89 static int hwcrhk_destroy(ENGINE *e);
90 static int hwcrhk_init(ENGINE *e);
91 static int hwcrhk_finish(ENGINE *e);
92 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
94 /* Functions to handle mutexes if have dynamic locks */
95 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
96 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
97 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
98 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
99 #if 1 /* This is a HACK which will disappear in 0.9.8 */
100 /* Functions to handle mutexes if only have static locks */
101 static int hwcrhk_static_mutex_init(HWCryptoHook_Mutex *m,
102 HWCryptoHook_CallerContext *c);
103 static int hwcrhk_static_mutex_lock(HWCryptoHook_Mutex *m);
104 static void hwcrhk_static_mutex_unlock(HWCryptoHook_Mutex *m);
105 static void hwcrhk_static_mutex_destroy(HWCryptoHook_Mutex *m);
109 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
110 const BIGNUM *m, BN_CTX *ctx);
112 #ifndef OPENSSL_NO_RSA
114 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *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);
120 #ifndef OPENSSL_NO_DH
122 /* This function is alised to mod_exp (with the DH and mont dropped). */
123 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
124 const BIGNUM *a, const BIGNUM *p,
125 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
129 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
130 static int hwcrhk_rand_status(void);
133 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
134 UI_METHOD *ui_method, void *callback_data);
135 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
136 UI_METHOD *ui_method, void *callback_data);
137 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
138 int ind,long argl, void *argp);
140 /* Interaction stuff */
141 static int hwcrhk_insert_card(const char *prompt_info,
142 const char *wrong_info,
143 HWCryptoHook_PassphraseContext *ppctx,
144 HWCryptoHook_CallerContext *cactx);
145 static int hwcrhk_get_pass(const char *prompt_info,
146 int *len_io, char *buf,
147 HWCryptoHook_PassphraseContext *ppctx,
148 HWCryptoHook_CallerContext *cactx);
149 static void hwcrhk_log_message(void *logstr, const char *message);
151 /* The definitions for control commands specific to this engine */
152 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
153 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
154 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
155 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
156 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
157 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
160 "Specifies the path to the 'hwcrhk' shared library",
161 ENGINE_CMD_FLAG_STRING},
162 {HWCRHK_CMD_FORK_CHECK,
164 "Turns fork() checking on or off (boolean)",
165 ENGINE_CMD_FLAG_NUMERIC},
166 {HWCRHK_CMD_THREAD_LOCKING,
168 "Turns thread-safe locking on or off (boolean)",
169 ENGINE_CMD_FLAG_NUMERIC},
170 {HWCRHK_CMD_SET_USER_INTERFACE,
171 "SET_USER_INTERFACE",
172 "Set the global user interface (internal)",
173 ENGINE_CMD_FLAG_INTERNAL},
174 {HWCRHK_CMD_SET_CALLBACK_DATA,
176 "Set the global user interface extra data (internal)",
177 ENGINE_CMD_FLAG_INTERNAL},
181 #ifndef OPENSSL_NO_RSA
182 /* Our internal RSA_METHOD that we provide pointers to */
183 static RSA_METHOD hwcrhk_rsa =
185 "nCipher RSA method",
201 #ifndef OPENSSL_NO_DH
202 /* Our internal DH_METHOD that we provide pointers to */
203 static DH_METHOD hwcrhk_dh =
216 static RAND_METHOD hwcrhk_rand =
218 /* "nCipher RAND method", */
227 /* Constants used when creating the ENGINE */
228 static const char *engine_hwcrhk_id = "chil";
229 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
231 /* Internal stuff for HWCryptoHook */
233 /* Some structures needed for proper use of thread locks */
234 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
235 into HWCryptoHook_Mutex */
236 struct HWCryptoHook_MutexValue
241 /* hwcryptohook.h has some typedefs that turn
242 struct HWCryptoHook_PassphraseContextValue
243 into HWCryptoHook_PassphraseContext */
244 struct HWCryptoHook_PassphraseContextValue
246 UI_METHOD *ui_method;
250 /* hwcryptohook.h has some typedefs that turn
251 struct HWCryptoHook_CallerContextValue
252 into HWCryptoHook_CallerContext */
253 struct HWCryptoHook_CallerContextValue
255 pem_password_cb *password_callback; /* Deprecated! Only present for
256 backward compatibility! */
257 UI_METHOD *ui_method;
261 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
262 BIGNUM's, so lets define a couple of conversion macros */
263 #define BN2MPI(mp, bn) \
264 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
265 #define MPI2BN(bn, mp) \
266 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
268 static BIO *logstream = NULL;
269 static int disable_mutex_callbacks = 0;
271 /* One might wonder why these are needed, since one can pass down at least
272 a UI_METHOD and a pointer to callback data to the key-loading functions.
273 The thing is that the ModExp and RSAImmed functions can load keys as well,
274 if the data they get is in a special, nCipher-defined format (hint: if you
275 look at the private exponent of the RSA data as a string, you'll see this
276 string: "nCipher KM tool key id", followed by some bytes, followed a key
277 identity string, followed by more bytes. This happens when you use "embed"
278 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
279 any passphrase or caller context, and our functions can't really take any
280 callback data either. Still, the "insert_card" and "get_passphrase"
281 callbacks may be called down the line, and will need to know what user
282 interface callbacks to call, and having callback data from the application
283 may be a nice thing as well, so we need to keep track of that globally. */
284 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
286 /* Stuff to pass to the HWCryptoHook library */
287 static HWCryptoHook_InitInfo hwcrhk_globals = {
288 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
289 &logstream, /* logstream */
290 sizeof(BN_ULONG), /* limbsize */
291 0, /* mslimb first: false for BNs */
292 -1, /* msbyte first: use native */
293 0, /* Max mutexes, 0 = no small limit */
294 0, /* Max simultaneous, 0 = default */
296 /* The next few are mutex stuff: we write wrapper functions
297 around the OS mutex functions. We initialise them to 0
298 here, and change that to actual function pointers in hwcrhk_init()
299 if dynamic locks are supported (that is, if the application
300 programmer has made sure of setting up callbacks bafore starting
301 this engine) *and* if disable_mutex_callbacks hasn't been set by
302 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
303 sizeof(HWCryptoHook_Mutex),
309 /* The next few are condvar stuff: we write wrapper functions
310 round the OS functions. Currently not implemented and not
311 and absolute necessity even in threaded programs, therefore
312 0'ed. Will hopefully be implemented some day, since it
313 enhances the efficiency of HWCryptoHook. */
314 0, /* sizeof(HWCryptoHook_CondVar), */
315 0, /* hwcrhk_cv_init, */
316 0, /* hwcrhk_cv_wait, */
317 0, /* hwcrhk_cv_signal, */
318 0, /* hwcrhk_cv_broadcast, */
319 0, /* hwcrhk_cv_destroy, */
321 hwcrhk_get_pass, /* pass phrase */
322 hwcrhk_insert_card, /* insert a card */
323 hwcrhk_log_message /* Log message */
327 /* Now, to our own code */
329 /* This internal function is used by ENGINE_ncipher() and possibly by the
330 * "dynamic" ENGINE support too */
331 static int bind_helper(ENGINE *e)
333 #ifndef OPENSSL_NO_RSA
334 const RSA_METHOD *meth1;
336 #ifndef OPENSSL_NO_DH
337 const DH_METHOD *meth2;
339 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
340 !ENGINE_set_name(e, engine_hwcrhk_name) ||
341 #ifndef OPENSSL_NO_RSA
342 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
344 #ifndef OPENSSL_NO_DH
345 !ENGINE_set_DH(e, &hwcrhk_dh) ||
347 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
348 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
349 !ENGINE_set_init_function(e, hwcrhk_init) ||
350 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
351 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
352 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
353 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
354 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
357 #ifndef OPENSSL_NO_RSA
358 /* We know that the "PKCS1_SSLeay()" functions hook properly
359 * to the cswift-specific mod_exp and mod_exp_crt so we use
360 * those functions. NB: We don't use ENGINE_openssl() or
361 * anything "more generic" because something like the RSAref
362 * code may not hook properly, and if you own one of these
363 * cards then you have the right to do RSA operations on it
365 meth1 = RSA_PKCS1_SSLeay();
366 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
367 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
368 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
369 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
372 #ifndef OPENSSL_NO_DH
373 /* Much the same for Diffie-Hellman */
374 meth2 = DH_OpenSSL();
375 hwcrhk_dh.generate_key = meth2->generate_key;
376 hwcrhk_dh.compute_key = meth2->compute_key;
379 /* Ensure the hwcrhk error handling is set up */
380 ERR_load_HWCRHK_strings();
384 #ifndef ENGINE_DYNAMIC_SUPPORT
385 static ENGINE *engine_ncipher(void)
387 ENGINE *ret = ENGINE_new();
390 if(!bind_helper(ret))
398 void ENGINE_load_chil(void)
400 /* Copied from eng_[openssl|dyn].c */
401 ENGINE *toadd = engine_ncipher();
409 /* This is a process-global DSO handle used for loading and unloading
410 * the HWCryptoHook library. NB: This is only set (or unset) during an
411 * init() or finish() call (reference counts permitting) and they're
412 * operating with global locks, so this should be thread-safe
414 static DSO *hwcrhk_dso = NULL;
415 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
416 #ifndef OPENSSL_NO_RSA
417 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
420 /* These are the function pointers that are (un)set when the library has
421 * successfully (un)loaded. */
422 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
423 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
424 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
425 #ifndef OPENSSL_NO_RSA
426 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
428 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
429 #ifndef OPENSSL_NO_RSA
430 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
431 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
432 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
434 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
436 /* Used in the DSO operations. */
437 static const char *HWCRHK_LIBNAME = NULL;
438 static void free_HWCRHK_LIBNAME(void)
441 OPENSSL_free((void*)HWCRHK_LIBNAME);
442 HWCRHK_LIBNAME = NULL;
444 static const char *get_HWCRHK_LIBNAME(void)
447 return HWCRHK_LIBNAME;
450 static long set_HWCRHK_LIBNAME(const char *name)
452 free_HWCRHK_LIBNAME();
453 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
455 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
456 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
457 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
458 #ifndef OPENSSL_NO_RSA
459 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
461 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
462 #ifndef OPENSSL_NO_RSA
463 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
464 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
465 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
467 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
469 /* HWCryptoHook library functions and mechanics - these are used by the
470 * higher-level functions further down. NB: As and where there's no
471 * error checking, take a look lower down where these functions are
472 * called, the checking and error handling is probably down there. */
474 /* utility function to obtain a context */
475 static int get_context(HWCryptoHook_ContextHandle *hac,
476 HWCryptoHook_CallerContext *cac)
479 HWCryptoHook_ErrMsgBuf rmsg;
482 rmsg.size = sizeof(tempbuf);
484 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
491 /* similarly to release one. */
492 static void release_context(HWCryptoHook_ContextHandle hac)
494 p_hwcrhk_Finish(hac);
497 /* Destructor (complements the "ENGINE_ncipher()" constructor) */
498 static int hwcrhk_destroy(ENGINE *e)
500 free_HWCRHK_LIBNAME();
501 ERR_unload_HWCRHK_strings();
505 /* (de)initialisation functions. */
506 static int hwcrhk_init(ENGINE *e)
508 HWCryptoHook_Init_t *p1;
509 HWCryptoHook_Finish_t *p2;
510 HWCryptoHook_ModExp_t *p3;
511 #ifndef OPENSSL_NO_RSA
512 HWCryptoHook_RSA_t *p4;
513 HWCryptoHook_RSALoadKey_t *p5;
514 HWCryptoHook_RSAGetPublicKey_t *p6;
515 HWCryptoHook_RSAUnloadKey_t *p7;
517 HWCryptoHook_RandomBytes_t *p8;
518 HWCryptoHook_ModExpCRT_t *p9;
520 if(hwcrhk_dso != NULL)
522 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
525 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
526 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
527 if(hwcrhk_dso == NULL)
529 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
532 if(!(p1 = (HWCryptoHook_Init_t *)
533 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
534 !(p2 = (HWCryptoHook_Finish_t *)
535 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
536 !(p3 = (HWCryptoHook_ModExp_t *)
537 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
538 #ifndef OPENSSL_NO_RSA
539 !(p4 = (HWCryptoHook_RSA_t *)
540 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
541 !(p5 = (HWCryptoHook_RSALoadKey_t *)
542 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
543 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
544 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
545 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
546 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
548 !(p8 = (HWCryptoHook_RandomBytes_t *)
549 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
550 !(p9 = (HWCryptoHook_ModExpCRT_t *)
551 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
553 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
556 /* Copy the pointers */
558 p_hwcrhk_Finish = p2;
559 p_hwcrhk_ModExp = p3;
560 #ifndef OPENSSL_NO_RSA
562 p_hwcrhk_RSALoadKey = p5;
563 p_hwcrhk_RSAGetPublicKey = p6;
564 p_hwcrhk_RSAUnloadKey = p7;
566 p_hwcrhk_RandomBytes = p8;
567 p_hwcrhk_ModExpCRT = p9;
569 /* Check if the application decided to support dynamic locks,
570 and if it does, use them. */
571 if (disable_mutex_callbacks == 0)
573 if (CRYPTO_get_dynlock_create_callback() != NULL &&
574 CRYPTO_get_dynlock_lock_callback() != NULL &&
575 CRYPTO_get_dynlock_destroy_callback() != NULL)
577 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
578 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
579 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
580 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
582 else if (CRYPTO_get_locking_callback() != NULL)
584 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DYNAMIC_LOCKING_MISSING);
585 ERR_add_error_data(1,"You HAVE to add dynamic locking callbacks via CRYPTO_set_dynlock_{create,lock,destroy}_callback()");
586 #if 1 /* This is a HACK which will disappear in 0.9.8 */
587 hwcrhk_globals.maxmutexes = 1; /* Only have one lock */
588 hwcrhk_globals.mutex_init = hwcrhk_static_mutex_init;
589 hwcrhk_globals.mutex_acquire = hwcrhk_static_mutex_lock;
590 hwcrhk_globals.mutex_release = hwcrhk_static_mutex_unlock;
591 hwcrhk_globals.mutex_destroy = hwcrhk_static_mutex_destroy;
598 /* Try and get a context - if not, we may have a DSO but no
600 if(!get_context(&hwcrhk_context, &password_context))
602 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
605 /* Everything's fine. */
606 #ifndef OPENSSL_NO_RSA
607 if (hndidx_rsa == -1)
608 hndidx_rsa = RSA_get_ex_new_index(0,
609 "nFast HWCryptoHook RSA key handle",
610 NULL, NULL, hwcrhk_ex_free);
615 DSO_free(hwcrhk_dso);
617 p_hwcrhk_Init = NULL;
618 p_hwcrhk_Finish = NULL;
619 p_hwcrhk_ModExp = NULL;
620 #ifndef OPENSSL_NO_RSA
622 p_hwcrhk_RSALoadKey = NULL;
623 p_hwcrhk_RSAGetPublicKey = NULL;
624 p_hwcrhk_RSAUnloadKey = NULL;
626 p_hwcrhk_ModExpCRT = NULL;
627 p_hwcrhk_RandomBytes = NULL;
631 static int hwcrhk_finish(ENGINE *e)
634 free_HWCRHK_LIBNAME();
635 if(hwcrhk_dso == NULL)
637 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
641 release_context(hwcrhk_context);
642 if(!DSO_free(hwcrhk_dso))
644 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
652 p_hwcrhk_Init = NULL;
653 p_hwcrhk_Finish = NULL;
654 p_hwcrhk_ModExp = NULL;
655 #ifndef OPENSSL_NO_RSA
657 p_hwcrhk_RSALoadKey = NULL;
658 p_hwcrhk_RSAGetPublicKey = NULL;
659 p_hwcrhk_RSAUnloadKey = NULL;
661 p_hwcrhk_ModExpCRT = NULL;
662 p_hwcrhk_RandomBytes = NULL;
666 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
672 case HWCRHK_CMD_SO_PATH:
675 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
680 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
683 return set_HWCRHK_LIBNAME((const char *)p);
684 case ENGINE_CTRL_SET_LOGSTREAM:
688 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
694 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
697 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
699 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
701 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
702 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
703 password_context.password_callback = (pem_password_cb *)f;
704 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
706 case ENGINE_CTRL_SET_USER_INTERFACE:
707 case HWCRHK_CMD_SET_USER_INTERFACE:
708 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
709 password_context.ui_method = (UI_METHOD *)p;
710 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
712 case ENGINE_CTRL_SET_CALLBACK_DATA:
713 case HWCRHK_CMD_SET_CALLBACK_DATA:
714 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
715 password_context.callback_data = p;
716 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
718 /* this enables or disables the "SimpleForkCheck" flag used in the
719 * initialisation structure. */
720 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
721 case HWCRHK_CMD_FORK_CHECK:
722 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
724 hwcrhk_globals.flags |=
725 HWCryptoHook_InitFlags_SimpleForkCheck;
727 hwcrhk_globals.flags &=
728 ~HWCryptoHook_InitFlags_SimpleForkCheck;
729 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
731 /* This will prevent the initialisation function from "installing"
732 * the mutex-handling callbacks, even if they are available from
733 * within the library (or were provided to the library from the
734 * calling application). This is to remove any baggage for
735 * applications not using multithreading. */
736 case ENGINE_CTRL_CHIL_NO_LOCKING:
737 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
738 disable_mutex_callbacks = 1;
739 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
741 case HWCRHK_CMD_THREAD_LOCKING:
742 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
743 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
744 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
747 /* The command isn't understood by this engine */
749 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
750 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
758 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
759 UI_METHOD *ui_method, void *callback_data)
761 #ifndef OPENSSL_NO_RSA
764 EVP_PKEY *res = NULL;
765 #ifndef OPENSSL_NO_RSA
766 HWCryptoHook_MPI e, n;
767 HWCryptoHook_RSAKeyHandle *hptr;
769 #if !defined(OPENSSL_NO_RSA)
771 HWCryptoHook_ErrMsgBuf rmsg;
773 HWCryptoHook_PassphraseContext ppctx;
775 #if !defined(OPENSSL_NO_RSA)
777 rmsg.size = sizeof(tempbuf);
782 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
783 HWCRHK_R_NOT_INITIALISED);
786 #ifndef OPENSSL_NO_RSA
787 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
790 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
791 ERR_R_MALLOC_FAILURE);
794 ppctx.ui_method = ui_method;
795 ppctx.callback_data = callback_data;
796 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
799 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
800 HWCRHK_R_CHIL_ERROR);
801 ERR_add_error_data(1,rmsg.buf);
806 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
811 #ifndef OPENSSL_NO_RSA
812 rtmp = RSA_new_method(eng);
813 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
816 rtmp->flags |= RSA_FLAG_EXT_PKEY;
819 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
820 != HWCRYPTOHOOK_ERROR_MPISIZE)
822 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
823 ERR_add_error_data(1,rmsg.buf);
827 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
828 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
832 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
834 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
835 HWCRHK_R_CHIL_ERROR);
836 ERR_add_error_data(1,rmsg.buf);
839 rtmp->e->top = e.size / sizeof(BN_ULONG);
841 rtmp->n->top = n.size / sizeof(BN_ULONG);
844 res = EVP_PKEY_new();
845 EVP_PKEY_assign_RSA(res, rtmp);
849 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
850 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
856 #ifndef OPENSSL_NO_RSA
863 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
864 UI_METHOD *ui_method, void *callback_data)
866 EVP_PKEY *res = NULL;
868 #ifndef OPENSSL_NO_RSA
869 res = hwcrhk_load_privkey(eng, key_id,
870 ui_method, callback_data);
876 #ifndef OPENSSL_NO_RSA
881 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
883 res->pkey.rsa = RSA_new();
884 res->pkey.rsa->n = rsa->n;
885 res->pkey.rsa->e = rsa->e;
888 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
894 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
895 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
906 /* A little mod_exp */
907 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
908 const BIGNUM *m, BN_CTX *ctx)
911 HWCryptoHook_ErrMsgBuf rmsg;
912 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
913 we use them directly, plus a little macro magic. We only
914 thing we need to make sure of is that enough space is allocated. */
915 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
918 to_return = 0; /* expect failure */
920 rmsg.size = sizeof(tempbuf);
924 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
927 /* Prepare the params */
928 bn_expand2(r, m->top); /* Check for error !! */
934 /* Perform the operation */
935 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
937 /* Convert the response */
938 r->top = m_r.size / sizeof(BN_ULONG);
943 /* FIXME: When this error is returned, HWCryptoHook is
944 telling us that falling back to software computation
945 might be a good thing. */
946 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
948 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
952 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
954 ERR_add_error_data(1,rmsg.buf);
963 #ifndef OPENSSL_NO_RSA
964 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
967 HWCryptoHook_ErrMsgBuf rmsg;
968 HWCryptoHook_RSAKeyHandle *hptr;
969 int to_return = 0, ret;
972 rmsg.size = sizeof(tempbuf);
976 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
980 /* This provides support for nForce keys. Since that's opaque data
981 all we do is provide a handle to the proper key and let HWCryptoHook
982 take care of the rest. */
983 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
986 HWCryptoHook_MPI m_a, m_r;
990 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
991 HWCRHK_R_MISSING_KEY_COMPONENTS);
995 /* Prepare the params */
996 bn_expand2(r, rsa->n->top); /* Check for error !! */
1000 /* Perform the operation */
1001 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
1003 /* Convert the response */
1004 r->top = m_r.size / sizeof(BN_ULONG);
1009 /* FIXME: When this error is returned, HWCryptoHook is
1010 telling us that falling back to software computation
1011 might be a good thing. */
1012 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1014 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1015 HWCRHK_R_REQUEST_FALLBACK);
1019 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1020 HWCRHK_R_REQUEST_FAILED);
1022 ERR_add_error_data(1,rmsg.buf);
1028 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1030 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1032 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1033 HWCRHK_R_MISSING_KEY_COMPONENTS);
1037 /* Prepare the params */
1038 bn_expand2(r, rsa->n->top); /* Check for error !! */
1040 BN2MPI(m_p, rsa->p);
1041 BN2MPI(m_q, rsa->q);
1042 BN2MPI(m_dmp1, rsa->dmp1);
1043 BN2MPI(m_dmq1, rsa->dmq1);
1044 BN2MPI(m_iqmp, rsa->iqmp);
1047 /* Perform the operation */
1048 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1049 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1051 /* Convert the response */
1052 r->top = m_r.size / sizeof(BN_ULONG);
1057 /* FIXME: When this error is returned, HWCryptoHook is
1058 telling us that falling back to software computation
1059 might be a good thing. */
1060 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1062 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1063 HWCRHK_R_REQUEST_FALLBACK);
1067 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1068 HWCRHK_R_REQUEST_FAILED);
1070 ERR_add_error_data(1,rmsg.buf);
1074 /* If we're here, we must be here with some semblance of success :-) */
1081 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1082 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1083 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1085 return hwcrhk_mod_exp(r, a, p, m, ctx);
1088 #ifndef OPENSSL_NO_DH
1089 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1090 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1091 const BIGNUM *a, const BIGNUM *p,
1092 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1094 return hwcrhk_mod_exp(r, a, p, m, ctx);
1098 /* Random bytes are good */
1099 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1102 HWCryptoHook_ErrMsgBuf rmsg;
1103 int to_return = 0; /* assume failure */
1107 rmsg.size = sizeof(tempbuf);
1111 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1115 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1118 /* FIXME: When this error is returned, HWCryptoHook is
1119 telling us that falling back to software computation
1120 might be a good thing. */
1121 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1123 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1124 HWCRHK_R_REQUEST_FALLBACK);
1128 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1129 HWCRHK_R_REQUEST_FAILED);
1131 ERR_add_error_data(1,rmsg.buf);
1139 static int hwcrhk_rand_status(void)
1144 /* This cleans up an RSA KM key, called when ex_data is freed */
1146 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1147 int ind,long argl, void *argp)
1150 HWCryptoHook_ErrMsgBuf rmsg;
1151 #ifndef OPENSSL_NO_RSA
1152 HWCryptoHook_RSAKeyHandle *hptr;
1154 #if !defined(OPENSSL_NO_RSA)
1159 rmsg.size = sizeof(tempbuf);
1161 #ifndef OPENSSL_NO_RSA
1162 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1165 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1171 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1172 * these just wrap the POSIX functions and add some logging.
1175 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1176 HWCryptoHook_CallerContext *cactx)
1178 mt->lockid = CRYPTO_get_new_dynlockid();
1179 if (mt->lockid == 0)
1180 return 1; /* failure */
1181 return 0; /* success */
1184 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1186 CRYPTO_w_lock(mt->lockid);
1190 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1192 CRYPTO_w_unlock(mt->lockid);
1195 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1197 CRYPTO_destroy_dynlockid(mt->lockid);
1200 /* Mutex upcalls to use if the application does not support dynamic locks */
1202 static int hwcrhk_static_mutex_init(HWCryptoHook_Mutex *m,
1203 HWCryptoHook_CallerContext *c)
1207 static int hwcrhk_static_mutex_lock(HWCryptoHook_Mutex *m)
1209 CRYPTO_w_lock(CRYPTO_LOCK_HWCRHK);
1212 static void hwcrhk_static_mutex_unlock(HWCryptoHook_Mutex *m)
1214 CRYPTO_w_unlock(CRYPTO_LOCK_HWCRHK);
1216 static void hwcrhk_static_mutex_destroy(HWCryptoHook_Mutex *m)
1220 static int hwcrhk_get_pass(const char *prompt_info,
1221 int *len_io, char *buf,
1222 HWCryptoHook_PassphraseContext *ppctx,
1223 HWCryptoHook_CallerContext *cactx)
1225 pem_password_cb *callback = NULL;
1226 void *callback_data = NULL;
1227 UI_METHOD *ui_method = NULL;
1231 if (cactx->ui_method)
1232 ui_method = cactx->ui_method;
1233 if (cactx->password_callback)
1234 callback = cactx->password_callback;
1235 if (cactx->callback_data)
1236 callback_data = cactx->callback_data;
1240 if (ppctx->ui_method)
1242 ui_method = ppctx->ui_method;
1245 if (ppctx->callback_data)
1246 callback_data = ppctx->callback_data;
1248 if (callback == NULL && ui_method == NULL)
1250 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1256 UI *ui = UI_new_method(ui_method);
1260 char *prompt = UI_construct_prompt(ui,
1261 "pass phrase", prompt_info);
1263 ok = UI_add_input_string(ui,prompt,
1264 UI_INPUT_FLAG_DEFAULT_PWD,
1265 buf,0,(*len_io) - 1);
1266 UI_add_user_data(ui, callback_data);
1267 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1274 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1277 *len_io = strlen(buf);
1280 OPENSSL_free(prompt);
1285 *len_io = callback(buf, *len_io, 0, callback_data);
1292 static int hwcrhk_insert_card(const char *prompt_info,
1293 const char *wrong_info,
1294 HWCryptoHook_PassphraseContext *ppctx,
1295 HWCryptoHook_CallerContext *cactx)
1299 void *callback_data = NULL;
1300 UI_METHOD *ui_method = NULL;
1304 if (cactx->ui_method)
1305 ui_method = cactx->ui_method;
1306 if (cactx->callback_data)
1307 callback_data = cactx->callback_data;
1311 if (ppctx->ui_method)
1312 ui_method = ppctx->ui_method;
1313 if (ppctx->callback_data)
1314 callback_data = ppctx->callback_data;
1316 if (ui_method == NULL)
1318 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1319 HWCRHK_R_NO_CALLBACK);
1323 ui = UI_new_method(ui_method);
1331 BIO_snprintf(buf, sizeof(buf)-1,
1332 "Current card: \"%s\"\n", wrong_info);
1333 ok = UI_dup_info_string(ui, buf);
1334 if (ok >= 0 && prompt_info)
1336 BIO_snprintf(buf, sizeof(buf)-1,
1337 "Insert card \"%s\"", prompt_info);
1338 ok = UI_dup_input_boolean(ui, buf,
1339 "\n then hit <enter> or C<enter> to cancel\n",
1340 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1342 UI_add_user_data(ui, callback_data);
1345 ok = UI_process(ui);
1348 if (ok == -2 || (ok >= 0 && answer == 'C'))
1358 static void hwcrhk_log_message(void *logstr, const char *message)
1360 BIO *lstream = NULL;
1362 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1364 lstream=*(BIO **)logstr;
1367 BIO_printf(lstream, "%s\n", message);
1369 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1372 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1373 * shared-library. */
1374 #ifdef ENGINE_DYNAMIC_SUPPORT
1375 static int bind_fn(ENGINE *e, const char *id)
1377 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1383 IMPLEMENT_DYNAMIC_CHECK_FN()
1384 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1385 #endif /* ENGINE_DYNAMIC_SUPPORT */
1387 #endif /* !OPENSSL_NO_HW_NCIPHER */
1388 #endif /* !OPENSSL_NO_HW */