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);
112 #ifndef OPENSSL_NO_DH
114 /* This function is alised to mod_exp (with the DH and mont dropped). */
115 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
116 const BIGNUM *a, const BIGNUM *p,
117 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
121 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
122 static int hwcrhk_rand_status(void);
125 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
126 UI_METHOD *ui_method, void *callback_data);
127 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
128 UI_METHOD *ui_method, void *callback_data);
129 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
130 int ind,long argl, void *argp);
132 /* Interaction stuff */
133 static int hwcrhk_insert_card(const char *prompt_info,
134 const char *wrong_info,
135 HWCryptoHook_PassphraseContext *ppctx,
136 HWCryptoHook_CallerContext *cactx);
137 static int hwcrhk_get_pass(const char *prompt_info,
138 int *len_io, char *buf,
139 HWCryptoHook_PassphraseContext *ppctx,
140 HWCryptoHook_CallerContext *cactx);
141 static void hwcrhk_log_message(void *logstr, const char *message);
143 /* The definitions for control commands specific to this engine */
144 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
145 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
146 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
147 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
148 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
149 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
152 "Specifies the path to the 'hwcrhk' shared library",
153 ENGINE_CMD_FLAG_STRING},
154 {HWCRHK_CMD_FORK_CHECK,
156 "Turns fork() checking on or off (boolean)",
157 ENGINE_CMD_FLAG_NUMERIC},
158 {HWCRHK_CMD_THREAD_LOCKING,
160 "Turns thread-safe locking on or off (boolean)",
161 ENGINE_CMD_FLAG_NUMERIC},
162 {HWCRHK_CMD_SET_USER_INTERFACE,
163 "SET_USER_INTERFACE",
164 "Set the global user interface (internal)",
165 ENGINE_CMD_FLAG_INTERNAL},
166 {HWCRHK_CMD_SET_CALLBACK_DATA,
168 "Set the global user interface extra data (internal)",
169 ENGINE_CMD_FLAG_INTERNAL},
173 #ifndef OPENSSL_NO_RSA
174 /* Our internal RSA_METHOD that we provide pointers to */
175 static RSA_METHOD hwcrhk_rsa =
177 "nCipher RSA method",
193 #ifndef OPENSSL_NO_DH
194 /* Our internal DH_METHOD that we provide pointers to */
195 static DH_METHOD hwcrhk_dh =
208 static RAND_METHOD hwcrhk_rand =
210 /* "nCipher RAND method", */
219 /* Constants used when creating the ENGINE */
220 static const char *engine_hwcrhk_id = "chil";
221 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
223 /* Internal stuff for HWCryptoHook */
225 /* Some structures needed for proper use of thread locks */
226 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
227 into HWCryptoHook_Mutex */
228 struct HWCryptoHook_MutexValue
233 /* hwcryptohook.h has some typedefs that turn
234 struct HWCryptoHook_PassphraseContextValue
235 into HWCryptoHook_PassphraseContext */
236 struct HWCryptoHook_PassphraseContextValue
238 UI_METHOD *ui_method;
242 /* hwcryptohook.h has some typedefs that turn
243 struct HWCryptoHook_CallerContextValue
244 into HWCryptoHook_CallerContext */
245 struct HWCryptoHook_CallerContextValue
247 pem_password_cb *password_callback; /* Deprecated! Only present for
248 backward compatibility! */
249 UI_METHOD *ui_method;
253 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
254 BIGNUM's, so lets define a couple of conversion macros */
255 #define BN2MPI(mp, bn) \
256 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
257 #define MPI2BN(bn, mp) \
258 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
260 static BIO *logstream = NULL;
261 static int disable_mutex_callbacks = 0;
263 /* One might wonder why these are needed, since one can pass down at least
264 a UI_METHOD and a pointer to callback data to the key-loading functions.
265 The thing is that the ModExp and RSAImmed functions can load keys as well,
266 if the data they get is in a special, nCipher-defined format (hint: if you
267 look at the private exponent of the RSA data as a string, you'll see this
268 string: "nCipher KM tool key id", followed by some bytes, followed a key
269 identity string, followed by more bytes. This happens when you use "embed"
270 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
271 any passphrase or caller context, and our functions can't really take any
272 callback data either. Still, the "insert_card" and "get_passphrase"
273 callbacks may be called down the line, and will need to know what user
274 interface callbacks to call, and having callback data from the application
275 may be a nice thing as well, so we need to keep track of that globally. */
276 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
278 /* Stuff to pass to the HWCryptoHook library */
279 static HWCryptoHook_InitInfo hwcrhk_globals = {
280 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
281 &logstream, /* logstream */
282 sizeof(BN_ULONG), /* limbsize */
283 0, /* mslimb first: false for BNs */
284 -1, /* msbyte first: use native */
285 0, /* Max mutexes, 0 = no small limit */
286 0, /* Max simultaneous, 0 = default */
288 /* The next few are mutex stuff: we write wrapper functions
289 around the OS mutex functions. We initialise them to 0
290 here, and change that to actual function pointers in hwcrhk_init()
291 if dynamic locks are supported (that is, if the application
292 programmer has made sure of setting up callbacks bafore starting
293 this engine) *and* if disable_mutex_callbacks hasn't been set by
294 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
295 sizeof(HWCryptoHook_Mutex),
301 /* The next few are condvar stuff: we write wrapper functions
302 round the OS functions. Currently not implemented and not
303 and absolute necessity even in threaded programs, therefore
304 0'ed. Will hopefully be implemented some day, since it
305 enhances the efficiency of HWCryptoHook. */
306 0, /* sizeof(HWCryptoHook_CondVar), */
307 0, /* hwcrhk_cv_init, */
308 0, /* hwcrhk_cv_wait, */
309 0, /* hwcrhk_cv_signal, */
310 0, /* hwcrhk_cv_broadcast, */
311 0, /* hwcrhk_cv_destroy, */
313 hwcrhk_get_pass, /* pass phrase */
314 hwcrhk_insert_card, /* insert a card */
315 hwcrhk_log_message /* Log message */
319 /* Now, to our own code */
321 /* This internal function is used by ENGINE_ncipher() and possibly by the
322 * "dynamic" ENGINE support too */
323 static int bind_helper(ENGINE *e)
325 #ifndef OPENSSL_NO_RSA
326 const RSA_METHOD *meth1;
328 #ifndef OPENSSL_NO_DH
329 const DH_METHOD *meth2;
331 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
332 !ENGINE_set_name(e, engine_hwcrhk_name) ||
333 #ifndef OPENSSL_NO_RSA
334 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
336 #ifndef OPENSSL_NO_DH
337 !ENGINE_set_DH(e, &hwcrhk_dh) ||
339 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
340 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
341 !ENGINE_set_init_function(e, hwcrhk_init) ||
342 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
343 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
344 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
345 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
346 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
349 #ifndef OPENSSL_NO_RSA
350 /* We know that the "PKCS1_SSLeay()" functions hook properly
351 * to the cswift-specific mod_exp and mod_exp_crt so we use
352 * those functions. NB: We don't use ENGINE_openssl() or
353 * anything "more generic" because something like the RSAref
354 * code may not hook properly, and if you own one of these
355 * cards then you have the right to do RSA operations on it
357 meth1 = RSA_PKCS1_SSLeay();
358 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
359 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
360 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
361 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
364 #ifndef OPENSSL_NO_DH
365 /* Much the same for Diffie-Hellman */
366 meth2 = DH_OpenSSL();
367 hwcrhk_dh.generate_key = meth2->generate_key;
368 hwcrhk_dh.compute_key = meth2->compute_key;
371 /* Ensure the hwcrhk error handling is set up */
372 ERR_load_HWCRHK_strings();
376 static ENGINE *engine_ncipher(void)
378 ENGINE *ret = ENGINE_new();
381 if(!bind_helper(ret))
389 void ENGINE_load_chil(void)
391 /* Copied from eng_[openssl|dyn].c */
392 ENGINE *toadd = engine_ncipher();
399 /* This is a process-global DSO handle used for loading and unloading
400 * the HWCryptoHook library. NB: This is only set (or unset) during an
401 * init() or finish() call (reference counts permitting) and they're
402 * operating with global locks, so this should be thread-safe
404 static DSO *hwcrhk_dso = NULL;
405 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
406 #ifndef OPENSSL_NO_RSA
407 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
410 /* These are the function pointers that are (un)set when the library has
411 * successfully (un)loaded. */
412 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
413 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
414 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
415 #ifndef OPENSSL_NO_RSA
416 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
418 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
419 #ifndef OPENSSL_NO_RSA
420 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
421 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
422 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
424 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
426 /* Used in the DSO operations. */
427 static const char *HWCRHK_LIBNAME = NULL;
428 static void free_HWCRHK_LIBNAME(void)
431 OPENSSL_free((void*)HWCRHK_LIBNAME);
432 HWCRHK_LIBNAME = NULL;
434 static const char *get_HWCRHK_LIBNAME(void)
437 return HWCRHK_LIBNAME;
440 static long set_HWCRHK_LIBNAME(const char *name)
442 free_HWCRHK_LIBNAME();
443 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
445 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
446 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
447 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
448 #ifndef OPENSSL_NO_RSA
449 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
451 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
452 #ifndef OPENSSL_NO_RSA
453 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
454 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
455 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
457 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
459 /* HWCryptoHook library functions and mechanics - these are used by the
460 * higher-level functions further down. NB: As and where there's no
461 * error checking, take a look lower down where these functions are
462 * called, the checking and error handling is probably down there. */
464 /* utility function to obtain a context */
465 static int get_context(HWCryptoHook_ContextHandle *hac,
466 HWCryptoHook_CallerContext *cac)
469 HWCryptoHook_ErrMsgBuf rmsg;
472 rmsg.size = sizeof(tempbuf);
474 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
481 /* similarly to release one. */
482 static void release_context(HWCryptoHook_ContextHandle hac)
484 p_hwcrhk_Finish(hac);
487 /* Destructor (complements the "ENGINE_ncipher()" constructor) */
488 static int hwcrhk_destroy(ENGINE *e)
490 free_HWCRHK_LIBNAME();
491 ERR_unload_HWCRHK_strings();
495 /* (de)initialisation functions. */
496 static int hwcrhk_init(ENGINE *e)
498 HWCryptoHook_Init_t *p1;
499 HWCryptoHook_Finish_t *p2;
500 HWCryptoHook_ModExp_t *p3;
501 #ifndef OPENSSL_NO_RSA
502 HWCryptoHook_RSA_t *p4;
503 HWCryptoHook_RSALoadKey_t *p5;
504 HWCryptoHook_RSAGetPublicKey_t *p6;
505 HWCryptoHook_RSAUnloadKey_t *p7;
507 HWCryptoHook_RandomBytes_t *p8;
508 HWCryptoHook_ModExpCRT_t *p9;
510 if(hwcrhk_dso != NULL)
512 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
515 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
516 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
517 if(hwcrhk_dso == NULL)
519 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
522 if(!(p1 = (HWCryptoHook_Init_t *)
523 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
524 !(p2 = (HWCryptoHook_Finish_t *)
525 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
526 !(p3 = (HWCryptoHook_ModExp_t *)
527 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
528 #ifndef OPENSSL_NO_RSA
529 !(p4 = (HWCryptoHook_RSA_t *)
530 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
531 !(p5 = (HWCryptoHook_RSALoadKey_t *)
532 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
533 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
534 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
535 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
536 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
538 !(p8 = (HWCryptoHook_RandomBytes_t *)
539 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
540 !(p9 = (HWCryptoHook_ModExpCRT_t *)
541 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
543 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
546 /* Copy the pointers */
548 p_hwcrhk_Finish = p2;
549 p_hwcrhk_ModExp = p3;
550 #ifndef OPENSSL_NO_RSA
552 p_hwcrhk_RSALoadKey = p5;
553 p_hwcrhk_RSAGetPublicKey = p6;
554 p_hwcrhk_RSAUnloadKey = p7;
556 p_hwcrhk_RandomBytes = p8;
557 p_hwcrhk_ModExpCRT = p9;
559 /* Check if the application decided to support dynamic locks,
560 and if it does, use them. */
561 if (disable_mutex_callbacks == 0 &&
562 CRYPTO_get_dynlock_create_callback() != NULL &&
563 CRYPTO_get_dynlock_lock_callback() != NULL &&
564 CRYPTO_get_dynlock_destroy_callback() != NULL)
566 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
567 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
568 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
569 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
572 /* Try and get a context - if not, we may have a DSO but no
574 if(!get_context(&hwcrhk_context, &password_context))
576 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
579 /* Everything's fine. */
580 #ifndef OPENSSL_NO_RSA
581 if (hndidx_rsa == -1)
582 hndidx_rsa = RSA_get_ex_new_index(0,
583 "nFast HWCryptoHook RSA key handle",
584 NULL, NULL, hwcrhk_ex_free);
589 DSO_free(hwcrhk_dso);
591 p_hwcrhk_Init = NULL;
592 p_hwcrhk_Finish = NULL;
593 p_hwcrhk_ModExp = NULL;
594 #ifndef OPENSSL_NO_RSA
596 p_hwcrhk_RSALoadKey = NULL;
597 p_hwcrhk_RSAGetPublicKey = NULL;
598 p_hwcrhk_RSAUnloadKey = NULL;
600 p_hwcrhk_ModExpCRT = NULL;
601 p_hwcrhk_RandomBytes = NULL;
605 static int hwcrhk_finish(ENGINE *e)
608 free_HWCRHK_LIBNAME();
609 if(hwcrhk_dso == NULL)
611 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
615 release_context(hwcrhk_context);
616 if(!DSO_free(hwcrhk_dso))
618 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
626 p_hwcrhk_Init = NULL;
627 p_hwcrhk_Finish = NULL;
628 p_hwcrhk_ModExp = NULL;
629 #ifndef OPENSSL_NO_RSA
631 p_hwcrhk_RSALoadKey = NULL;
632 p_hwcrhk_RSAGetPublicKey = NULL;
633 p_hwcrhk_RSAUnloadKey = NULL;
635 p_hwcrhk_ModExpCRT = NULL;
636 p_hwcrhk_RandomBytes = NULL;
640 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
646 case HWCRHK_CMD_SO_PATH:
649 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
654 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
657 return set_HWCRHK_LIBNAME((const char *)p);
658 case ENGINE_CTRL_SET_LOGSTREAM:
662 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
668 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
671 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
673 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
675 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
676 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
677 password_context.password_callback = (pem_password_cb *)f;
678 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
680 case ENGINE_CTRL_SET_USER_INTERFACE:
681 case HWCRHK_CMD_SET_USER_INTERFACE:
682 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
683 password_context.ui_method = (UI_METHOD *)p;
684 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
686 case ENGINE_CTRL_SET_CALLBACK_DATA:
687 case HWCRHK_CMD_SET_CALLBACK_DATA:
688 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
689 password_context.callback_data = p;
690 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
692 /* this enables or disables the "SimpleForkCheck" flag used in the
693 * initialisation structure. */
694 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
695 case HWCRHK_CMD_FORK_CHECK:
696 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
698 hwcrhk_globals.flags |=
699 HWCryptoHook_InitFlags_SimpleForkCheck;
701 hwcrhk_globals.flags &=
702 ~HWCryptoHook_InitFlags_SimpleForkCheck;
703 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
705 /* This will prevent the initialisation function from "installing"
706 * the mutex-handling callbacks, even if they are available from
707 * within the library (or were provided to the library from the
708 * calling application). This is to remove any baggage for
709 * applications not using multithreading. */
710 case ENGINE_CTRL_CHIL_NO_LOCKING:
711 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
712 disable_mutex_callbacks = 1;
713 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
715 case HWCRHK_CMD_THREAD_LOCKING:
716 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
717 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
718 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
721 /* The command isn't understood by this engine */
723 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
724 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
732 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
733 UI_METHOD *ui_method, void *callback_data)
735 #ifndef OPENSSL_NO_RSA
738 EVP_PKEY *res = NULL;
739 #ifndef OPENSSL_NO_RSA
740 HWCryptoHook_MPI e, n;
741 HWCryptoHook_RSAKeyHandle *hptr;
743 #if !defined(OPENSSL_NO_RSA)
745 HWCryptoHook_ErrMsgBuf rmsg;
747 HWCryptoHook_PassphraseContext ppctx;
749 #if !defined(OPENSSL_NO_RSA)
751 rmsg.size = sizeof(tempbuf);
756 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
757 HWCRHK_R_NOT_INITIALISED);
760 #ifndef OPENSSL_NO_RSA
761 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
764 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
765 ERR_R_MALLOC_FAILURE);
768 ppctx.ui_method = ui_method;
769 ppctx.callback_data = callback_data;
770 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
773 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
774 HWCRHK_R_CHIL_ERROR);
775 ERR_add_error_data(1,rmsg.buf);
780 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
785 #ifndef OPENSSL_NO_RSA
786 rtmp = RSA_new_method(eng);
787 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
790 rtmp->flags |= RSA_FLAG_EXT_PKEY;
793 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
794 != HWCRYPTOHOOK_ERROR_MPISIZE)
796 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
797 ERR_add_error_data(1,rmsg.buf);
801 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
802 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
806 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
808 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
809 HWCRHK_R_CHIL_ERROR);
810 ERR_add_error_data(1,rmsg.buf);
813 rtmp->e->top = e.size / sizeof(BN_ULONG);
815 rtmp->n->top = n.size / sizeof(BN_ULONG);
818 res = EVP_PKEY_new();
819 EVP_PKEY_assign_RSA(res, rtmp);
823 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
824 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
830 #ifndef OPENSSL_NO_RSA
837 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
838 UI_METHOD *ui_method, void *callback_data)
840 EVP_PKEY *res = NULL;
842 #ifndef OPENSSL_NO_RSA
843 res = hwcrhk_load_privkey(eng, key_id,
844 ui_method, callback_data);
850 #ifndef OPENSSL_NO_RSA
855 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
857 res->pkey.rsa = RSA_new();
858 res->pkey.rsa->n = rsa->n;
859 res->pkey.rsa->e = rsa->e;
862 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
868 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
869 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
880 /* A little mod_exp */
881 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
882 const BIGNUM *m, BN_CTX *ctx)
885 HWCryptoHook_ErrMsgBuf rmsg;
886 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
887 we use them directly, plus a little macro magic. We only
888 thing we need to make sure of is that enough space is allocated. */
889 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
892 to_return = 0; /* expect failure */
894 rmsg.size = sizeof(tempbuf);
898 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
901 /* Prepare the params */
902 bn_expand2(r, m->top); /* Check for error !! */
908 /* Perform the operation */
909 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
911 /* Convert the response */
912 r->top = m_r.size / sizeof(BN_ULONG);
917 /* FIXME: When this error is returned, HWCryptoHook is
918 telling us that falling back to software computation
919 might be a good thing. */
920 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
922 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
926 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
928 ERR_add_error_data(1,rmsg.buf);
937 #ifndef OPENSSL_NO_RSA
938 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
941 HWCryptoHook_ErrMsgBuf rmsg;
942 HWCryptoHook_RSAKeyHandle *hptr;
943 int to_return = 0, ret;
946 rmsg.size = sizeof(tempbuf);
950 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
954 /* This provides support for nForce keys. Since that's opaque data
955 all we do is provide a handle to the proper key and let HWCryptoHook
956 take care of the rest. */
957 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
960 HWCryptoHook_MPI m_a, m_r;
964 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
965 HWCRHK_R_MISSING_KEY_COMPONENTS);
969 /* Prepare the params */
970 bn_expand2(r, rsa->n->top); /* Check for error !! */
974 /* Perform the operation */
975 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
977 /* Convert the response */
978 r->top = m_r.size / sizeof(BN_ULONG);
983 /* FIXME: When this error is returned, HWCryptoHook is
984 telling us that falling back to software computation
985 might be a good thing. */
986 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
988 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
989 HWCRHK_R_REQUEST_FALLBACK);
993 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
994 HWCRHK_R_REQUEST_FAILED);
996 ERR_add_error_data(1,rmsg.buf);
1002 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1004 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1006 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1007 HWCRHK_R_MISSING_KEY_COMPONENTS);
1011 /* Prepare the params */
1012 bn_expand2(r, rsa->n->top); /* Check for error !! */
1014 BN2MPI(m_p, rsa->p);
1015 BN2MPI(m_q, rsa->q);
1016 BN2MPI(m_dmp1, rsa->dmp1);
1017 BN2MPI(m_dmq1, rsa->dmq1);
1018 BN2MPI(m_iqmp, rsa->iqmp);
1021 /* Perform the operation */
1022 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1023 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
1025 /* Convert the response */
1026 r->top = m_r.size / sizeof(BN_ULONG);
1031 /* FIXME: When this error is returned, HWCryptoHook is
1032 telling us that falling back to software computation
1033 might be a good thing. */
1034 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1036 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1037 HWCRHK_R_REQUEST_FALLBACK);
1041 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1042 HWCRHK_R_REQUEST_FAILED);
1044 ERR_add_error_data(1,rmsg.buf);
1048 /* If we're here, we must be here with some semblance of success :-) */
1055 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1056 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1057 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1059 return hwcrhk_mod_exp(r, a, p, m, ctx);
1062 #ifndef OPENSSL_NO_DH
1063 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1064 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1065 const BIGNUM *a, const BIGNUM *p,
1066 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1068 return hwcrhk_mod_exp(r, a, p, m, ctx);
1072 /* Random bytes are good */
1073 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1076 HWCryptoHook_ErrMsgBuf rmsg;
1077 int to_return = 0; /* assume failure */
1081 rmsg.size = sizeof(tempbuf);
1085 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1089 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1092 /* FIXME: When this error is returned, HWCryptoHook is
1093 telling us that falling back to software computation
1094 might be a good thing. */
1095 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1097 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1098 HWCRHK_R_REQUEST_FALLBACK);
1102 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1103 HWCRHK_R_REQUEST_FAILED);
1105 ERR_add_error_data(1,rmsg.buf);
1113 static int hwcrhk_rand_status(void)
1118 /* This cleans up an RSA KM key, called when ex_data is freed */
1120 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1121 int ind,long argl, void *argp)
1124 HWCryptoHook_ErrMsgBuf rmsg;
1125 #ifndef OPENSSL_NO_RSA
1126 HWCryptoHook_RSAKeyHandle *hptr;
1128 #if !defined(OPENSSL_NO_RSA)
1133 rmsg.size = sizeof(tempbuf);
1135 #ifndef OPENSSL_NO_RSA
1136 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1139 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1145 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1146 * these just wrap the POSIX functions and add some logging.
1149 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1150 HWCryptoHook_CallerContext *cactx)
1152 mt->lockid = CRYPTO_get_new_dynlockid();
1153 if (mt->lockid == 0)
1154 return 1; /* failure */
1155 return 0; /* success */
1158 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1160 CRYPTO_w_lock(mt->lockid);
1164 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1166 CRYPTO_w_unlock(mt->lockid);
1169 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1171 CRYPTO_destroy_dynlockid(mt->lockid);
1174 static int hwcrhk_get_pass(const char *prompt_info,
1175 int *len_io, char *buf,
1176 HWCryptoHook_PassphraseContext *ppctx,
1177 HWCryptoHook_CallerContext *cactx)
1179 pem_password_cb *callback = NULL;
1180 void *callback_data = NULL;
1181 UI_METHOD *ui_method = NULL;
1185 if (cactx->ui_method)
1186 ui_method = cactx->ui_method;
1187 if (cactx->password_callback)
1188 callback = cactx->password_callback;
1189 if (cactx->callback_data)
1190 callback_data = cactx->callback_data;
1194 if (ppctx->ui_method)
1196 ui_method = ppctx->ui_method;
1199 if (ppctx->callback_data)
1200 callback_data = ppctx->callback_data;
1202 if (callback == NULL && ui_method == NULL)
1204 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1210 UI *ui = UI_new_method(ui_method);
1214 char *prompt = UI_construct_prompt(ui,
1215 "pass phrase", prompt_info);
1217 ok = UI_add_input_string(ui,prompt,
1218 UI_INPUT_FLAG_DEFAULT_PWD,
1219 buf,0,(*len_io) - 1);
1220 UI_add_user_data(ui, callback_data);
1221 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1228 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1231 *len_io = strlen(buf);
1234 OPENSSL_free(prompt);
1239 *len_io = callback(buf, *len_io, 0, callback_data);
1246 static int hwcrhk_insert_card(const char *prompt_info,
1247 const char *wrong_info,
1248 HWCryptoHook_PassphraseContext *ppctx,
1249 HWCryptoHook_CallerContext *cactx)
1253 void *callback_data = NULL;
1254 UI_METHOD *ui_method = NULL;
1258 if (cactx->ui_method)
1259 ui_method = cactx->ui_method;
1260 if (cactx->callback_data)
1261 callback_data = cactx->callback_data;
1265 if (ppctx->ui_method)
1266 ui_method = ppctx->ui_method;
1267 if (ppctx->callback_data)
1268 callback_data = ppctx->callback_data;
1270 if (ui_method == NULL)
1272 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1273 HWCRHK_R_NO_CALLBACK);
1277 ui = UI_new_method(ui_method);
1285 BIO_snprintf(buf, sizeof(buf)-1,
1286 "Current card: \"%s\"\n", wrong_info);
1287 ok = UI_dup_info_string(ui, buf);
1288 if (ok >= 0 && prompt_info)
1290 BIO_snprintf(buf, sizeof(buf)-1,
1291 "Insert card \"%s\"", prompt_info);
1292 ok = UI_dup_input_boolean(ui, buf,
1293 "\n then hit <enter> or C<enter> to cancel\n",
1294 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1296 UI_add_user_data(ui, callback_data);
1299 ok = UI_process(ui);
1302 if (ok == -2 || (ok >= 0 && answer == 'C'))
1312 static void hwcrhk_log_message(void *logstr, const char *message)
1314 BIO *lstream = NULL;
1316 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1318 lstream=*(BIO **)logstr;
1321 BIO_write(lstream, message, strlen(message));
1323 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1326 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1327 * shared-library. */
1328 #ifdef ENGINE_DYNAMIC_SUPPORT
1329 static int bind_fn(ENGINE *e, const char *id)
1331 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1337 IMPLEMENT_DYNAMIC_CHECK_FN()
1338 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1339 #endif /* ENGINE_DYNAMIC_SUPPORT */
1341 #endif /* !OPENSSL_NO_HW_NCIPHER */
1342 #endif /* !OPENSSL_NO_HW */