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 */
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*);
101 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
102 const BIGNUM *m, BN_CTX *ctx);
104 #ifndef OPENSSL_NO_RSA
106 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa);
108 /* This function is aliased to mod_exp (with the mont stuff dropped). */
109 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
110 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
113 /* This function is alised to mod_exp (with the DH and mont dropped). */
114 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
115 const BIGNUM *a, const BIGNUM *p,
116 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
119 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
120 static int hwcrhk_rand_status(void);
123 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
124 UI_METHOD *ui_method, void *callback_data);
125 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
126 UI_METHOD *ui_method, void *callback_data);
127 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
128 int ind,long argl, void *argp);
130 /* Interaction stuff */
131 static int hwcrhk_insert_card(const char *prompt_info,
132 const char *wrong_info,
133 HWCryptoHook_PassphraseContext *ppctx,
134 HWCryptoHook_CallerContext *cactx);
135 static int hwcrhk_get_pass(const char *prompt_info,
136 int *len_io, char *buf,
137 HWCryptoHook_PassphraseContext *ppctx,
138 HWCryptoHook_CallerContext *cactx);
139 static void hwcrhk_log_message(void *logstr, const char *message);
141 /* The definitions for control commands specific to this engine */
142 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
143 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
144 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
145 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
146 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
147 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
150 "Specifies the path to the 'hwcrhk' shared library",
151 ENGINE_CMD_FLAG_STRING},
152 {HWCRHK_CMD_FORK_CHECK,
154 "Turns fork() checking on or off (boolean)",
155 ENGINE_CMD_FLAG_NUMERIC},
156 {HWCRHK_CMD_THREAD_LOCKING,
158 "Turns thread-safe locking on or off (boolean)",
159 ENGINE_CMD_FLAG_NUMERIC},
160 {HWCRHK_CMD_SET_USER_INTERFACE,
161 "SET_USER_INTERFACE",
162 "Set the global user interface (internal)",
163 ENGINE_CMD_FLAG_INTERNAL},
164 {HWCRHK_CMD_SET_CALLBACK_DATA,
166 "Set the global user interface extra data (internal)",
167 ENGINE_CMD_FLAG_INTERNAL},
171 #ifndef OPENSSL_NO_RSA
172 /* Our internal RSA_METHOD that we provide pointers to */
173 static RSA_METHOD hwcrhk_rsa =
175 "nCipher RSA method",
191 #ifndef OPENSSL_NO_DH
192 /* Our internal DH_METHOD that we provide pointers to */
193 static DH_METHOD hwcrhk_dh =
206 static RAND_METHOD hwcrhk_rand =
208 /* "nCipher RAND method", */
217 /* Constants used when creating the ENGINE */
218 static const char *engine_hwcrhk_id = "chil";
219 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
221 /* Internal stuff for HWCryptoHook */
223 /* Some structures needed for proper use of thread locks */
224 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
225 into HWCryptoHook_Mutex */
226 struct HWCryptoHook_MutexValue
231 /* hwcryptohook.h has some typedefs that turn
232 struct HWCryptoHook_PassphraseContextValue
233 into HWCryptoHook_PassphraseContext */
234 struct HWCryptoHook_PassphraseContextValue
236 UI_METHOD *ui_method;
240 /* hwcryptohook.h has some typedefs that turn
241 struct HWCryptoHook_CallerContextValue
242 into HWCryptoHook_CallerContext */
243 struct HWCryptoHook_CallerContextValue
245 pem_password_cb *password_callback; /* Deprecated! Only present for
246 backward compatibility! */
247 UI_METHOD *ui_method;
251 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
252 BIGNUM's, so lets define a couple of conversion macros */
253 #define BN2MPI(mp, bn) \
254 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
255 #define MPI2BN(bn, mp) \
256 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
258 static BIO *logstream = NULL;
259 static int disable_mutex_callbacks = 0;
261 /* One might wonder why these are needed, since one can pass down at least
262 a UI_METHOD and a pointer to callback data to the key-loading functions.
263 The thing is that the ModExp and RSAImmed functions can load keys as well,
264 if the data they get is in a special, nCipher-defined format (hint: if you
265 look at the private exponent of the RSA data as a string, you'll see this
266 string: "nCipher KM tool key id", followed by some bytes, followed a key
267 identity string, followed by more bytes. This happens when you use "embed"
268 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
269 any passphrase or caller context, and our functions can't really take any
270 callback data either. Still, the "insert_card" and "get_passphrase"
271 callbacks may be called down the line, and will need to know what user
272 interface callbacks to call, and having callback data from the application
273 may be a nice thing as well, so we need to keep track of that globally. */
274 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
276 /* Stuff to pass to the HWCryptoHook library */
277 static HWCryptoHook_InitInfo hwcrhk_globals = {
278 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
279 &logstream, /* logstream */
280 sizeof(BN_ULONG), /* limbsize */
281 0, /* mslimb first: false for BNs */
282 -1, /* msbyte first: use native */
283 0, /* Max mutexes, 0 = no small limit */
284 0, /* Max simultaneous, 0 = default */
286 /* The next few are mutex stuff: we write wrapper functions
287 around the OS mutex functions. We initialise them to 0
288 here, and change that to actual function pointers in hwcrhk_init()
289 if dynamic locks are supported (that is, if the application
290 programmer has made sure of setting up callbacks bafore starting
291 this engine) *and* if disable_mutex_callbacks hasn't been set by
292 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
293 sizeof(HWCryptoHook_Mutex),
299 /* The next few are condvar stuff: we write wrapper functions
300 round the OS functions. Currently not implemented and not
301 and absolute necessity even in threaded programs, therefore
302 0'ed. Will hopefully be implemented some day, since it
303 enhances the efficiency of HWCryptoHook. */
304 0, /* sizeof(HWCryptoHook_CondVar), */
305 0, /* hwcrhk_cv_init, */
306 0, /* hwcrhk_cv_wait, */
307 0, /* hwcrhk_cv_signal, */
308 0, /* hwcrhk_cv_broadcast, */
309 0, /* hwcrhk_cv_destroy, */
311 hwcrhk_get_pass, /* pass phrase */
312 hwcrhk_insert_card, /* insert a card */
313 hwcrhk_log_message /* Log message */
317 /* Now, to our own code */
319 /* This internal function is used by ENGINE_ncipher() and possibly by the
320 * "dynamic" ENGINE support too */
321 static int bind_helper(ENGINE *e)
323 #ifndef OPENSSL_NO_RSA
324 const RSA_METHOD *meth1;
326 #ifndef OPENSSL_NO_DH
327 const DH_METHOD *meth2;
329 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
330 !ENGINE_set_name(e, engine_hwcrhk_name) ||
331 #ifndef OPENSSL_NO_RSA
332 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
334 #ifndef OPENSSL_NO_DH
335 !ENGINE_set_DH(e, &hwcrhk_dh) ||
337 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
338 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
339 !ENGINE_set_init_function(e, hwcrhk_init) ||
340 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
341 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
342 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
343 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
344 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
347 #ifndef OPENSSL_NO_RSA
348 /* We know that the "PKCS1_SSLeay()" functions hook properly
349 * to the cswift-specific mod_exp and mod_exp_crt so we use
350 * those functions. NB: We don't use ENGINE_openssl() or
351 * anything "more generic" because something like the RSAref
352 * code may not hook properly, and if you own one of these
353 * cards then you have the right to do RSA operations on it
355 meth1 = RSA_PKCS1_SSLeay();
356 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
357 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
358 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
359 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
362 #ifndef OPENSSL_NO_DH
363 /* Much the same for Diffie-Hellman */
364 meth2 = DH_OpenSSL();
365 hwcrhk_dh.generate_key = meth2->generate_key;
366 hwcrhk_dh.compute_key = meth2->compute_key;
369 /* Ensure the hwcrhk error handling is set up */
370 ERR_load_HWCRHK_strings();
374 static ENGINE *engine_ncipher(void)
376 ENGINE *ret = ENGINE_new();
379 if(!bind_helper(ret))
387 void ENGINE_load_chil(void)
389 /* Copied from eng_[openssl|dyn].c */
390 ENGINE *toadd = engine_ncipher();
397 /* This is a process-global DSO handle used for loading and unloading
398 * the HWCryptoHook library. NB: This is only set (or unset) during an
399 * init() or finish() call (reference counts permitting) and they're
400 * operating with global locks, so this should be thread-safe
402 static DSO *hwcrhk_dso = NULL;
403 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
404 #ifndef OPENSSL_NO_RSA
405 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
408 /* These are the function pointers that are (un)set when the library has
409 * successfully (un)loaded. */
410 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
411 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
412 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
413 #ifndef OPENSSL_NO_RSA
414 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
416 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
417 #ifndef OPENSSL_NO_RSA
418 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
419 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
420 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
422 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
424 /* Used in the DSO operations. */
425 static const char *HWCRHK_LIBNAME = NULL;
426 static void free_HWCRHK_LIBNAME(void)
429 OPENSSL_free((void*)HWCRHK_LIBNAME);
430 HWCRHK_LIBNAME = NULL;
432 static const char *get_HWCRHK_LIBNAME(void)
435 return HWCRHK_LIBNAME;
438 static long set_HWCRHK_LIBNAME(const char *name)
440 free_HWCRHK_LIBNAME();
441 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
443 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
444 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
445 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
446 #ifndef OPENSSL_NO_RSA
447 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
449 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
450 #ifndef OPENSSL_NO_RSA
451 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
452 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
453 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
455 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
457 /* HWCryptoHook library functions and mechanics - these are used by the
458 * higher-level functions further down. NB: As and where there's no
459 * error checking, take a look lower down where these functions are
460 * called, the checking and error handling is probably down there. */
462 /* utility function to obtain a context */
463 static int get_context(HWCryptoHook_ContextHandle *hac,
464 HWCryptoHook_CallerContext *cac)
467 HWCryptoHook_ErrMsgBuf rmsg;
470 rmsg.size = sizeof(tempbuf);
472 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
479 /* similarly to release one. */
480 static void release_context(HWCryptoHook_ContextHandle hac)
482 p_hwcrhk_Finish(hac);
485 /* Destructor (complements the "ENGINE_ncipher()" constructor) */
486 static int hwcrhk_destroy(ENGINE *e)
488 free_HWCRHK_LIBNAME();
489 ERR_unload_HWCRHK_strings();
493 /* (de)initialisation functions. */
494 static int hwcrhk_init(ENGINE *e)
496 HWCryptoHook_Init_t *p1;
497 HWCryptoHook_Finish_t *p2;
498 HWCryptoHook_ModExp_t *p3;
499 #ifndef OPENSSL_NO_RSA
500 HWCryptoHook_RSA_t *p4;
501 HWCryptoHook_RSALoadKey_t *p5;
502 HWCryptoHook_RSAGetPublicKey_t *p6;
503 HWCryptoHook_RSAUnloadKey_t *p7;
505 HWCryptoHook_RandomBytes_t *p8;
506 HWCryptoHook_ModExpCRT_t *p9;
508 if(hwcrhk_dso != NULL)
510 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
513 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
514 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
515 if(hwcrhk_dso == NULL)
517 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
520 if(!(p1 = (HWCryptoHook_Init_t *)
521 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
522 !(p2 = (HWCryptoHook_Finish_t *)
523 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
524 !(p3 = (HWCryptoHook_ModExp_t *)
525 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
526 #ifndef OPENSSL_NO_RSA
527 !(p4 = (HWCryptoHook_RSA_t *)
528 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
529 !(p5 = (HWCryptoHook_RSALoadKey_t *)
530 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
531 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
532 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
533 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
534 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
536 !(p8 = (HWCryptoHook_RandomBytes_t *)
537 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
538 !(p9 = (HWCryptoHook_ModExpCRT_t *)
539 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
541 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
544 /* Copy the pointers */
546 p_hwcrhk_Finish = p2;
547 p_hwcrhk_ModExp = p3;
548 #ifndef OPENSSL_NO_RSA
550 p_hwcrhk_RSALoadKey = p5;
551 p_hwcrhk_RSAGetPublicKey = p6;
552 p_hwcrhk_RSAUnloadKey = p7;
554 p_hwcrhk_RandomBytes = p8;
555 p_hwcrhk_ModExpCRT = p9;
557 /* Check if the application decided to support dynamic locks,
558 and if it does, use them. */
559 if (disable_mutex_callbacks == 0 &&
560 CRYPTO_get_dynlock_create_callback() != NULL &&
561 CRYPTO_get_dynlock_lock_callback() != NULL &&
562 CRYPTO_get_dynlock_destroy_callback() != NULL)
564 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
565 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
566 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
567 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
570 /* Try and get a context - if not, we may have a DSO but no
572 if(!get_context(&hwcrhk_context, &password_context))
574 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
577 /* Everything's fine. */
578 #ifndef OPENSSL_NO_RSA
579 if (hndidx_rsa == -1)
580 hndidx_rsa = RSA_get_ex_new_index(0,
581 "nFast HWCryptoHook RSA key handle",
582 NULL, NULL, hwcrhk_ex_free);
587 DSO_free(hwcrhk_dso);
589 p_hwcrhk_Init = NULL;
590 p_hwcrhk_Finish = NULL;
591 p_hwcrhk_ModExp = NULL;
592 #ifndef OPENSSL_NO_RSA
594 p_hwcrhk_RSALoadKey = NULL;
595 p_hwcrhk_RSAGetPublicKey = NULL;
596 p_hwcrhk_RSAUnloadKey = NULL;
598 p_hwcrhk_ModExpCRT = NULL;
599 p_hwcrhk_RandomBytes = NULL;
603 static int hwcrhk_finish(ENGINE *e)
606 free_HWCRHK_LIBNAME();
607 if(hwcrhk_dso == NULL)
609 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
613 release_context(hwcrhk_context);
614 if(!DSO_free(hwcrhk_dso))
616 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
624 p_hwcrhk_Init = NULL;
625 p_hwcrhk_Finish = NULL;
626 p_hwcrhk_ModExp = NULL;
627 #ifndef OPENSSL_NO_RSA
629 p_hwcrhk_RSALoadKey = NULL;
630 p_hwcrhk_RSAGetPublicKey = NULL;
631 p_hwcrhk_RSAUnloadKey = NULL;
633 p_hwcrhk_ModExpCRT = NULL;
634 p_hwcrhk_RandomBytes = NULL;
638 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
644 case HWCRHK_CMD_SO_PATH:
647 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
652 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
655 return set_HWCRHK_LIBNAME((const char *)p);
656 case ENGINE_CTRL_SET_LOGSTREAM:
660 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
666 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
669 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
671 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
673 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
674 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
675 password_context.password_callback = (pem_password_cb *)f;
676 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
678 case ENGINE_CTRL_SET_USER_INTERFACE:
679 case HWCRHK_CMD_SET_USER_INTERFACE:
680 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
681 password_context.ui_method = (UI_METHOD *)p;
682 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
684 case ENGINE_CTRL_SET_CALLBACK_DATA:
685 case HWCRHK_CMD_SET_CALLBACK_DATA:
686 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
687 password_context.callback_data = p;
688 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
690 /* this enables or disables the "SimpleForkCheck" flag used in the
691 * initialisation structure. */
692 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
693 case HWCRHK_CMD_FORK_CHECK:
694 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
696 hwcrhk_globals.flags |=
697 HWCryptoHook_InitFlags_SimpleForkCheck;
699 hwcrhk_globals.flags &=
700 ~HWCryptoHook_InitFlags_SimpleForkCheck;
701 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
703 /* This will prevent the initialisation function from "installing"
704 * the mutex-handling callbacks, even if they are available from
705 * within the library (or were provided to the library from the
706 * calling application). This is to remove any baggage for
707 * applications not using multithreading. */
708 case ENGINE_CTRL_CHIL_NO_LOCKING:
709 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
710 disable_mutex_callbacks = 1;
711 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
713 case HWCRHK_CMD_THREAD_LOCKING:
714 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
715 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
716 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
719 /* The command isn't understood by this engine */
721 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
722 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
730 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
731 UI_METHOD *ui_method, void *callback_data)
733 #ifndef OPENSSL_NO_RSA
736 EVP_PKEY *res = NULL;
737 #ifndef OPENSSL_NO_RSA
738 HWCryptoHook_MPI e, n;
739 HWCryptoHook_RSAKeyHandle *hptr;
741 #if !defined(OPENSSL_NO_RSA)
743 HWCryptoHook_ErrMsgBuf rmsg;
745 HWCryptoHook_PassphraseContext ppctx;
747 #if !defined(OPENSSL_NO_RSA)
749 rmsg.size = sizeof(tempbuf);
754 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
755 HWCRHK_R_NOT_INITIALISED);
758 #ifndef OPENSSL_NO_RSA
759 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
762 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
763 ERR_R_MALLOC_FAILURE);
766 ppctx.ui_method = ui_method;
767 ppctx.callback_data = callback_data;
768 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
771 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
772 HWCRHK_R_CHIL_ERROR);
773 ERR_add_error_data(1,rmsg.buf);
778 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
783 #ifndef OPENSSL_NO_RSA
784 rtmp = RSA_new_method(eng);
785 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
788 rtmp->flags |= RSA_FLAG_EXT_PKEY;
791 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
792 != HWCRYPTOHOOK_ERROR_MPISIZE)
794 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
795 ERR_add_error_data(1,rmsg.buf);
799 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
800 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
804 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
806 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
807 HWCRHK_R_CHIL_ERROR);
808 ERR_add_error_data(1,rmsg.buf);
811 rtmp->e->top = e.size / sizeof(BN_ULONG);
813 rtmp->n->top = n.size / sizeof(BN_ULONG);
816 res = EVP_PKEY_new();
817 EVP_PKEY_assign_RSA(res, rtmp);
821 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
822 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
828 #ifndef OPENSSL_NO_RSA
835 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
836 UI_METHOD *ui_method, void *callback_data)
838 EVP_PKEY *res = NULL;
840 #ifndef OPENSSL_NO_RSA
841 res = hwcrhk_load_privkey(eng, key_id,
842 ui_method, callback_data);
848 #ifndef OPENSSL_NO_RSA
853 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
855 res->pkey.rsa = RSA_new();
856 res->pkey.rsa->n = rsa->n;
857 res->pkey.rsa->e = rsa->e;
860 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
866 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
867 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
878 /* A little mod_exp */
879 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
880 const BIGNUM *m, BN_CTX *ctx)
883 HWCryptoHook_ErrMsgBuf rmsg;
884 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
885 we use them directly, plus a little macro magic. We only
886 thing we need to make sure of is that enough space is allocated. */
887 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
890 to_return = 0; /* expect failure */
892 rmsg.size = sizeof(tempbuf);
896 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
899 /* Prepare the params */
900 bn_expand2(r, m->top); /* Check for error !! */
906 /* Perform the operation */
907 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
909 /* Convert the response */
910 r->top = m_r.size / sizeof(BN_ULONG);
915 /* FIXME: When this error is returned, HWCryptoHook is
916 telling us that falling back to software computation
917 might be a good thing. */
918 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
920 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
924 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
926 ERR_add_error_data(1,rmsg.buf);
935 #ifndef OPENSSL_NO_RSA
936 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
939 HWCryptoHook_ErrMsgBuf rmsg;
940 HWCryptoHook_RSAKeyHandle *hptr;
941 int to_return = 0, ret;
944 rmsg.size = sizeof(tempbuf);
948 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
952 /* This provides support for nForce keys. Since that's opaque data
953 all we do is provide a handle to the proper key and let HWCryptoHook
954 take care of the rest. */
955 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
958 HWCryptoHook_MPI m_a, m_r;
962 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
963 HWCRHK_R_MISSING_KEY_COMPONENTS);
967 /* Prepare the params */
968 bn_expand2(r, rsa->n->top); /* Check for error !! */
972 /* Perform the operation */
973 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
975 /* Convert the response */
976 r->top = m_r.size / sizeof(BN_ULONG);
981 /* FIXME: When this error is returned, HWCryptoHook is
982 telling us that falling back to software computation
983 might be a good thing. */
984 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
986 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
987 HWCRHK_R_REQUEST_FALLBACK);
991 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
992 HWCRHK_R_REQUEST_FAILED);
994 ERR_add_error_data(1,rmsg.buf);
1000 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1002 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1004 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1005 HWCRHK_R_MISSING_KEY_COMPONENTS);
1009 /* Prepare the params */
1010 bn_expand2(r, rsa->n->top); /* Check for error !! */
1012 BN2MPI(m_p, rsa->p);
1013 BN2MPI(m_q, rsa->q);
1014 BN2MPI(m_dmp1, rsa->dmp1);
1015 BN2MPI(m_dmq1, rsa->dmq1);
1016 BN2MPI(m_iqmp, rsa->iqmp);
1019 /* Perform the operation */
1020 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1021 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
1023 /* Convert the response */
1024 r->top = m_r.size / sizeof(BN_ULONG);
1029 /* FIXME: When this error is returned, HWCryptoHook is
1030 telling us that falling back to software computation
1031 might be a good thing. */
1032 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1034 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1035 HWCRHK_R_REQUEST_FALLBACK);
1039 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1040 HWCRHK_R_REQUEST_FAILED);
1042 ERR_add_error_data(1,rmsg.buf);
1046 /* If we're here, we must be here with some semblance of success :-) */
1053 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1054 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1055 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1057 return hwcrhk_mod_exp(r, a, p, m, ctx);
1060 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1061 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1062 const BIGNUM *a, const BIGNUM *p,
1063 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1065 return hwcrhk_mod_exp(r, a, p, m, ctx);
1068 /* Random bytes are good */
1069 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1072 HWCryptoHook_ErrMsgBuf rmsg;
1073 int to_return = 0; /* assume failure */
1077 rmsg.size = sizeof(tempbuf);
1081 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1085 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1088 /* FIXME: When this error is returned, HWCryptoHook is
1089 telling us that falling back to software computation
1090 might be a good thing. */
1091 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1093 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1094 HWCRHK_R_REQUEST_FALLBACK);
1098 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1099 HWCRHK_R_REQUEST_FAILED);
1101 ERR_add_error_data(1,rmsg.buf);
1109 static int hwcrhk_rand_status(void)
1114 /* This cleans up an RSA KM key, called when ex_data is freed */
1116 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1117 int ind,long argl, void *argp)
1120 HWCryptoHook_ErrMsgBuf rmsg;
1121 #ifndef OPENSSL_NO_RSA
1122 HWCryptoHook_RSAKeyHandle *hptr;
1124 #if !defined(OPENSSL_NO_RSA)
1129 rmsg.size = sizeof(tempbuf);
1131 #ifndef OPENSSL_NO_RSA
1132 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1135 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1141 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1142 * these just wrap the POSIX functions and add some logging.
1145 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1146 HWCryptoHook_CallerContext *cactx)
1148 mt->lockid = CRYPTO_get_new_dynlockid();
1149 if (mt->lockid == 0)
1150 return 1; /* failure */
1151 return 0; /* success */
1154 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1156 CRYPTO_w_lock(mt->lockid);
1160 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1162 CRYPTO_w_unlock(mt->lockid);
1165 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1167 CRYPTO_destroy_dynlockid(mt->lockid);
1170 static int hwcrhk_get_pass(const char *prompt_info,
1171 int *len_io, char *buf,
1172 HWCryptoHook_PassphraseContext *ppctx,
1173 HWCryptoHook_CallerContext *cactx)
1175 pem_password_cb *callback = NULL;
1176 void *callback_data = NULL;
1177 UI_METHOD *ui_method = NULL;
1181 if (cactx->ui_method)
1182 ui_method = cactx->ui_method;
1183 if (cactx->password_callback)
1184 callback = cactx->password_callback;
1185 if (cactx->callback_data)
1186 callback_data = cactx->callback_data;
1190 if (ppctx->ui_method)
1192 ui_method = ppctx->ui_method;
1195 if (ppctx->callback_data)
1196 callback_data = ppctx->callback_data;
1198 if (callback == NULL && ui_method == NULL)
1200 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1206 UI *ui = UI_new_method(ui_method);
1210 char *prompt = UI_construct_prompt(ui,
1211 "pass phrase", prompt_info);
1213 ok = UI_add_input_string(ui,prompt,
1214 UI_INPUT_FLAG_DEFAULT_PWD,
1215 buf,0,(*len_io) - 1);
1216 UI_add_user_data(ui, callback_data);
1217 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1224 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1227 *len_io = strlen(buf);
1230 OPENSSL_free(prompt);
1235 *len_io = callback(buf, *len_io, 0, callback_data);
1242 static int hwcrhk_insert_card(const char *prompt_info,
1243 const char *wrong_info,
1244 HWCryptoHook_PassphraseContext *ppctx,
1245 HWCryptoHook_CallerContext *cactx)
1249 void *callback_data = NULL;
1250 UI_METHOD *ui_method = NULL;
1254 if (cactx->ui_method)
1255 ui_method = cactx->ui_method;
1256 if (cactx->callback_data)
1257 callback_data = cactx->callback_data;
1261 if (ppctx->ui_method)
1262 ui_method = ppctx->ui_method;
1263 if (ppctx->callback_data)
1264 callback_data = ppctx->callback_data;
1266 if (ui_method == NULL)
1268 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1269 HWCRHK_R_NO_CALLBACK);
1273 ui = UI_new_method(ui_method);
1281 BIO_snprintf(buf, sizeof(buf)-1,
1282 "Current card: \"%s\"\n", wrong_info);
1283 ok = UI_dup_info_string(ui, buf);
1284 if (ok >= 0 && prompt_info)
1286 BIO_snprintf(buf, sizeof(buf)-1,
1287 "Insert card \"%s\"", prompt_info);
1288 ok = UI_dup_input_boolean(ui, buf,
1289 "\n then hit <enter> or C<enter> to cancel\n",
1290 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1292 UI_add_user_data(ui, callback_data);
1295 ok = UI_process(ui);
1298 if (ok == -2 || (ok >= 0 && answer == 'C'))
1308 static void hwcrhk_log_message(void *logstr, const char *message)
1310 BIO *lstream = NULL;
1312 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1314 lstream=*(BIO **)logstr;
1317 BIO_write(lstream, message, strlen(message));
1319 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1322 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1323 * shared-library. */
1324 #ifdef ENGINE_DYNAMIC_SUPPORT
1325 static int bind_fn(ENGINE *e, const char *id)
1327 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1333 IMPLEMENT_DYNAMIC_CHECK_FN()
1334 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1335 #endif /* ENGINE_DYNAMIC_SUPPORT */
1337 #endif /* !OPENSSL_NO_HW_NCIPHER */
1338 #endif /* !OPENSSL_NO_HW */