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).
62 #include <openssl/crypto.h>
63 #include <openssl/pem.h>
64 #include <openssl/dso.h>
65 #include <openssl/engine.h>
66 #include <openssl/ui.h>
69 #ifndef OPENSSL_NO_HW_NCIPHER
71 /* Attribution notice: nCipher have said several times that it's OK for
72 * us to implement a general interface to their boxes, and recently declared
73 * their HWCryptoHook to be public, and therefore available for us to use.
76 * The hwcryptohook.h included here is from May 2000.
80 #include "hwcryptohook.h"
82 #include "vendor_defns/hwcryptohook.h"
85 #define HWCRHK_LIB_NAME "hwcrhk engine"
86 #include "e_ncipher_err.c"
88 static int hwcrhk_destroy(ENGINE *e);
89 static int hwcrhk_init(ENGINE *e);
90 static int hwcrhk_finish(ENGINE *e);
91 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
93 /* Functions to handle mutexes */
94 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
95 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
96 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
97 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
100 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
101 const BIGNUM *m, BN_CTX *ctx);
103 #ifndef OPENSSL_NO_RSA
105 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa);
107 /* This function is aliased to mod_exp (with the mont stuff dropped). */
108 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
109 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
111 #ifndef OPENSSL_NO_DH
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);
120 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
121 static int hwcrhk_rand_status(void);
124 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
125 UI_METHOD *ui_method, void *callback_data);
126 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
127 UI_METHOD *ui_method, void *callback_data);
128 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
129 int ind,long argl, void *argp);
131 /* Interaction stuff */
132 static int hwcrhk_insert_card(const char *prompt_info,
133 const char *wrong_info,
134 HWCryptoHook_PassphraseContext *ppctx,
135 HWCryptoHook_CallerContext *cactx);
136 static int hwcrhk_get_pass(const char *prompt_info,
137 int *len_io, char *buf,
138 HWCryptoHook_PassphraseContext *ppctx,
139 HWCryptoHook_CallerContext *cactx);
140 static void hwcrhk_log_message(void *logstr, const char *message);
142 /* The definitions for control commands specific to this engine */
143 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
144 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
145 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
146 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
147 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
148 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
151 "Specifies the path to the 'hwcrhk' shared library",
152 ENGINE_CMD_FLAG_STRING},
153 {HWCRHK_CMD_FORK_CHECK,
155 "Turns fork() checking on or off (boolean)",
156 ENGINE_CMD_FLAG_NUMERIC},
157 {HWCRHK_CMD_THREAD_LOCKING,
159 "Turns thread-safe locking on or off (boolean)",
160 ENGINE_CMD_FLAG_NUMERIC},
161 {HWCRHK_CMD_SET_USER_INTERFACE,
162 "SET_USER_INTERFACE",
163 "Set the global user interface (internal)",
164 ENGINE_CMD_FLAG_INTERNAL},
165 {HWCRHK_CMD_SET_CALLBACK_DATA,
167 "Set the global user interface extra data (internal)",
168 ENGINE_CMD_FLAG_INTERNAL},
172 #ifndef OPENSSL_NO_RSA
173 /* Our internal RSA_METHOD that we provide pointers to */
174 static RSA_METHOD hwcrhk_rsa =
176 "nCipher RSA method",
192 #ifndef OPENSSL_NO_DH
193 /* Our internal DH_METHOD that we provide pointers to */
194 static DH_METHOD hwcrhk_dh =
207 static RAND_METHOD hwcrhk_rand =
209 /* "nCipher RAND method", */
218 /* Constants used when creating the ENGINE */
219 static const char *engine_hwcrhk_id = "chil";
220 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
222 /* Internal stuff for HWCryptoHook */
224 /* Some structures needed for proper use of thread locks */
225 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
226 into HWCryptoHook_Mutex */
227 struct HWCryptoHook_MutexValue
232 /* hwcryptohook.h has some typedefs that turn
233 struct HWCryptoHook_PassphraseContextValue
234 into HWCryptoHook_PassphraseContext */
235 struct HWCryptoHook_PassphraseContextValue
237 UI_METHOD *ui_method;
241 /* hwcryptohook.h has some typedefs that turn
242 struct HWCryptoHook_CallerContextValue
243 into HWCryptoHook_CallerContext */
244 struct HWCryptoHook_CallerContextValue
246 pem_password_cb *password_callback; /* Deprecated! Only present for
247 backward compatibility! */
248 UI_METHOD *ui_method;
252 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
253 BIGNUM's, so lets define a couple of conversion macros */
254 #define BN2MPI(mp, bn) \
255 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
256 #define MPI2BN(bn, mp) \
257 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
259 static BIO *logstream = NULL;
260 static int disable_mutex_callbacks = 0;
262 /* One might wonder why these are needed, since one can pass down at least
263 a UI_METHOD and a pointer to callback data to the key-loading functions.
264 The thing is that the ModExp and RSAImmed functions can load keys as well,
265 if the data they get is in a special, nCipher-defined format (hint: if you
266 look at the private exponent of the RSA data as a string, you'll see this
267 string: "nCipher KM tool key id", followed by some bytes, followed a key
268 identity string, followed by more bytes. This happens when you use "embed"
269 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
270 any passphrase or caller context, and our functions can't really take any
271 callback data either. Still, the "insert_card" and "get_passphrase"
272 callbacks may be called down the line, and will need to know what user
273 interface callbacks to call, and having callback data from the application
274 may be a nice thing as well, so we need to keep track of that globally. */
275 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
277 /* Stuff to pass to the HWCryptoHook library */
278 static HWCryptoHook_InitInfo hwcrhk_globals = {
279 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
280 &logstream, /* logstream */
281 sizeof(BN_ULONG), /* limbsize */
282 0, /* mslimb first: false for BNs */
283 -1, /* msbyte first: use native */
284 0, /* Max mutexes, 0 = no small limit */
285 0, /* Max simultaneous, 0 = default */
287 /* The next few are mutex stuff: we write wrapper functions
288 around the OS mutex functions. We initialise them to 0
289 here, and change that to actual function pointers in hwcrhk_init()
290 if dynamic locks are supported (that is, if the application
291 programmer has made sure of setting up callbacks bafore starting
292 this engine) *and* if disable_mutex_callbacks hasn't been set by
293 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
294 sizeof(HWCryptoHook_Mutex),
300 /* The next few are condvar stuff: we write wrapper functions
301 round the OS functions. Currently not implemented and not
302 and absolute necessity even in threaded programs, therefore
303 0'ed. Will hopefully be implemented some day, since it
304 enhances the efficiency of HWCryptoHook. */
305 0, /* sizeof(HWCryptoHook_CondVar), */
306 0, /* hwcrhk_cv_init, */
307 0, /* hwcrhk_cv_wait, */
308 0, /* hwcrhk_cv_signal, */
309 0, /* hwcrhk_cv_broadcast, */
310 0, /* hwcrhk_cv_destroy, */
312 hwcrhk_get_pass, /* pass phrase */
313 hwcrhk_insert_card, /* insert a card */
314 hwcrhk_log_message /* Log message */
318 /* Now, to our own code */
320 /* This internal function is used by ENGINE_ncipher() and possibly by the
321 * "dynamic" ENGINE support too */
322 static int bind_helper(ENGINE *e)
324 #ifndef OPENSSL_NO_RSA
325 const RSA_METHOD *meth1;
327 #ifndef OPENSSL_NO_DH
328 const DH_METHOD *meth2;
330 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
331 !ENGINE_set_name(e, engine_hwcrhk_name) ||
332 #ifndef OPENSSL_NO_RSA
333 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
335 #ifndef OPENSSL_NO_DH
336 !ENGINE_set_DH(e, &hwcrhk_dh) ||
338 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
339 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
340 !ENGINE_set_init_function(e, hwcrhk_init) ||
341 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
342 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
343 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
344 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
345 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
348 #ifndef OPENSSL_NO_RSA
349 /* We know that the "PKCS1_SSLeay()" functions hook properly
350 * to the cswift-specific mod_exp and mod_exp_crt so we use
351 * those functions. NB: We don't use ENGINE_openssl() or
352 * anything "more generic" because something like the RSAref
353 * code may not hook properly, and if you own one of these
354 * cards then you have the right to do RSA operations on it
356 meth1 = RSA_PKCS1_SSLeay();
357 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
358 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
359 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
360 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
363 #ifndef OPENSSL_NO_DH
364 /* Much the same for Diffie-Hellman */
365 meth2 = DH_OpenSSL();
366 hwcrhk_dh.generate_key = meth2->generate_key;
367 hwcrhk_dh.compute_key = meth2->compute_key;
370 /* Ensure the hwcrhk error handling is set up */
371 ERR_load_HWCRHK_strings();
375 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
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();
400 /* This is a process-global DSO handle used for loading and unloading
401 * the HWCryptoHook library. NB: This is only set (or unset) during an
402 * init() or finish() call (reference counts permitting) and they're
403 * operating with global locks, so this should be thread-safe
405 static DSO *hwcrhk_dso = NULL;
406 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
407 #ifndef OPENSSL_NO_RSA
408 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
411 /* These are the function pointers that are (un)set when the library has
412 * successfully (un)loaded. */
413 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
414 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
415 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
416 #ifndef OPENSSL_NO_RSA
417 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
419 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
420 #ifndef OPENSSL_NO_RSA
421 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
422 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
423 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
425 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
427 /* Used in the DSO operations. */
428 static const char *HWCRHK_LIBNAME = NULL;
429 static void free_HWCRHK_LIBNAME(void)
432 OPENSSL_free((void*)HWCRHK_LIBNAME);
433 HWCRHK_LIBNAME = NULL;
435 static const char *get_HWCRHK_LIBNAME(void)
438 return HWCRHK_LIBNAME;
441 static long set_HWCRHK_LIBNAME(const char *name)
443 free_HWCRHK_LIBNAME();
444 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
446 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
447 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
448 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
449 #ifndef OPENSSL_NO_RSA
450 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
452 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
453 #ifndef OPENSSL_NO_RSA
454 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
455 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
456 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
458 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
460 /* HWCryptoHook library functions and mechanics - these are used by the
461 * higher-level functions further down. NB: As and where there's no
462 * error checking, take a look lower down where these functions are
463 * called, the checking and error handling is probably down there. */
465 /* utility function to obtain a context */
466 static int get_context(HWCryptoHook_ContextHandle *hac,
467 HWCryptoHook_CallerContext *cac)
470 HWCryptoHook_ErrMsgBuf rmsg;
473 rmsg.size = sizeof(tempbuf);
475 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
482 /* similarly to release one. */
483 static void release_context(HWCryptoHook_ContextHandle hac)
485 p_hwcrhk_Finish(hac);
488 /* Destructor (complements the "ENGINE_ncipher()" constructor) */
489 static int hwcrhk_destroy(ENGINE *e)
491 free_HWCRHK_LIBNAME();
492 ERR_unload_HWCRHK_strings();
496 /* (de)initialisation functions. */
497 static int hwcrhk_init(ENGINE *e)
499 HWCryptoHook_Init_t *p1;
500 HWCryptoHook_Finish_t *p2;
501 HWCryptoHook_ModExp_t *p3;
502 #ifndef OPENSSL_NO_RSA
503 HWCryptoHook_RSA_t *p4;
504 HWCryptoHook_RSALoadKey_t *p5;
505 HWCryptoHook_RSAGetPublicKey_t *p6;
506 HWCryptoHook_RSAUnloadKey_t *p7;
508 HWCryptoHook_RandomBytes_t *p8;
509 HWCryptoHook_ModExpCRT_t *p9;
511 if(hwcrhk_dso != NULL)
513 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
516 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
517 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
518 if(hwcrhk_dso == NULL)
520 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
523 if(!(p1 = (HWCryptoHook_Init_t *)
524 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
525 !(p2 = (HWCryptoHook_Finish_t *)
526 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
527 !(p3 = (HWCryptoHook_ModExp_t *)
528 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
529 #ifndef OPENSSL_NO_RSA
530 !(p4 = (HWCryptoHook_RSA_t *)
531 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
532 !(p5 = (HWCryptoHook_RSALoadKey_t *)
533 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
534 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
535 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
536 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
537 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
539 !(p8 = (HWCryptoHook_RandomBytes_t *)
540 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
541 !(p9 = (HWCryptoHook_ModExpCRT_t *)
542 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
544 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
547 /* Copy the pointers */
549 p_hwcrhk_Finish = p2;
550 p_hwcrhk_ModExp = p3;
551 #ifndef OPENSSL_NO_RSA
553 p_hwcrhk_RSALoadKey = p5;
554 p_hwcrhk_RSAGetPublicKey = p6;
555 p_hwcrhk_RSAUnloadKey = p7;
557 p_hwcrhk_RandomBytes = p8;
558 p_hwcrhk_ModExpCRT = p9;
560 /* Check if the application decided to support dynamic locks,
561 and if it does, use them. */
562 if (disable_mutex_callbacks == 0 &&
563 CRYPTO_get_dynlock_create_callback() != NULL &&
564 CRYPTO_get_dynlock_lock_callback() != NULL &&
565 CRYPTO_get_dynlock_destroy_callback() != NULL)
567 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
568 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
569 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
570 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
573 /* Try and get a context - if not, we may have a DSO but no
575 if(!get_context(&hwcrhk_context, &password_context))
577 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
580 /* Everything's fine. */
581 #ifndef OPENSSL_NO_RSA
582 if (hndidx_rsa == -1)
583 hndidx_rsa = RSA_get_ex_new_index(0,
584 "nFast HWCryptoHook RSA key handle",
585 NULL, NULL, hwcrhk_ex_free);
590 DSO_free(hwcrhk_dso);
592 p_hwcrhk_Init = NULL;
593 p_hwcrhk_Finish = NULL;
594 p_hwcrhk_ModExp = NULL;
595 #ifndef OPENSSL_NO_RSA
597 p_hwcrhk_RSALoadKey = NULL;
598 p_hwcrhk_RSAGetPublicKey = NULL;
599 p_hwcrhk_RSAUnloadKey = NULL;
601 p_hwcrhk_ModExpCRT = NULL;
602 p_hwcrhk_RandomBytes = NULL;
606 static int hwcrhk_finish(ENGINE *e)
609 free_HWCRHK_LIBNAME();
610 if(hwcrhk_dso == NULL)
612 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
616 release_context(hwcrhk_context);
617 if(!DSO_free(hwcrhk_dso))
619 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
627 p_hwcrhk_Init = NULL;
628 p_hwcrhk_Finish = NULL;
629 p_hwcrhk_ModExp = NULL;
630 #ifndef OPENSSL_NO_RSA
632 p_hwcrhk_RSALoadKey = NULL;
633 p_hwcrhk_RSAGetPublicKey = NULL;
634 p_hwcrhk_RSAUnloadKey = NULL;
636 p_hwcrhk_ModExpCRT = NULL;
637 p_hwcrhk_RandomBytes = NULL;
641 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
647 case HWCRHK_CMD_SO_PATH:
650 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
655 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
658 return set_HWCRHK_LIBNAME((const char *)p);
659 case ENGINE_CTRL_SET_LOGSTREAM:
663 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
669 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
672 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
674 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
676 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
677 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
678 password_context.password_callback = (pem_password_cb *)f;
679 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
681 case ENGINE_CTRL_SET_USER_INTERFACE:
682 case HWCRHK_CMD_SET_USER_INTERFACE:
683 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
684 password_context.ui_method = (UI_METHOD *)p;
685 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
687 case ENGINE_CTRL_SET_CALLBACK_DATA:
688 case HWCRHK_CMD_SET_CALLBACK_DATA:
689 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
690 password_context.callback_data = p;
691 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
693 /* this enables or disables the "SimpleForkCheck" flag used in the
694 * initialisation structure. */
695 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
696 case HWCRHK_CMD_FORK_CHECK:
697 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
699 hwcrhk_globals.flags |=
700 HWCryptoHook_InitFlags_SimpleForkCheck;
702 hwcrhk_globals.flags &=
703 ~HWCryptoHook_InitFlags_SimpleForkCheck;
704 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
706 /* This will prevent the initialisation function from "installing"
707 * the mutex-handling callbacks, even if they are available from
708 * within the library (or were provided to the library from the
709 * calling application). This is to remove any baggage for
710 * applications not using multithreading. */
711 case ENGINE_CTRL_CHIL_NO_LOCKING:
712 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
713 disable_mutex_callbacks = 1;
714 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
716 case HWCRHK_CMD_THREAD_LOCKING:
717 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
718 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
719 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
722 /* The command isn't understood by this engine */
724 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
725 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
733 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
734 UI_METHOD *ui_method, void *callback_data)
736 #ifndef OPENSSL_NO_RSA
739 EVP_PKEY *res = NULL;
740 #ifndef OPENSSL_NO_RSA
741 HWCryptoHook_MPI e, n;
742 HWCryptoHook_RSAKeyHandle *hptr;
744 #if !defined(OPENSSL_NO_RSA)
746 HWCryptoHook_ErrMsgBuf rmsg;
748 HWCryptoHook_PassphraseContext ppctx;
750 #if !defined(OPENSSL_NO_RSA)
752 rmsg.size = sizeof(tempbuf);
757 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
758 HWCRHK_R_NOT_INITIALISED);
761 #ifndef OPENSSL_NO_RSA
762 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
765 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
766 ERR_R_MALLOC_FAILURE);
769 ppctx.ui_method = ui_method;
770 ppctx.callback_data = callback_data;
771 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
774 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
775 HWCRHK_R_CHIL_ERROR);
776 ERR_add_error_data(1,rmsg.buf);
781 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
786 #ifndef OPENSSL_NO_RSA
787 rtmp = RSA_new_method(eng);
788 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
791 rtmp->flags |= RSA_FLAG_EXT_PKEY;
794 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
795 != HWCRYPTOHOOK_ERROR_MPISIZE)
797 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
798 ERR_add_error_data(1,rmsg.buf);
802 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
803 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
807 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
809 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
810 HWCRHK_R_CHIL_ERROR);
811 ERR_add_error_data(1,rmsg.buf);
814 rtmp->e->top = e.size / sizeof(BN_ULONG);
816 rtmp->n->top = n.size / sizeof(BN_ULONG);
819 res = EVP_PKEY_new();
820 EVP_PKEY_assign_RSA(res, rtmp);
824 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
825 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
831 #ifndef OPENSSL_NO_RSA
838 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
839 UI_METHOD *ui_method, void *callback_data)
841 EVP_PKEY *res = NULL;
843 #ifndef OPENSSL_NO_RSA
844 res = hwcrhk_load_privkey(eng, key_id,
845 ui_method, callback_data);
851 #ifndef OPENSSL_NO_RSA
856 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
858 res->pkey.rsa = RSA_new();
859 res->pkey.rsa->n = rsa->n;
860 res->pkey.rsa->e = rsa->e;
863 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
869 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
870 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
881 /* A little mod_exp */
882 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
883 const BIGNUM *m, BN_CTX *ctx)
886 HWCryptoHook_ErrMsgBuf rmsg;
887 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
888 we use them directly, plus a little macro magic. We only
889 thing we need to make sure of is that enough space is allocated. */
890 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
893 to_return = 0; /* expect failure */
895 rmsg.size = sizeof(tempbuf);
899 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
902 /* Prepare the params */
903 bn_expand2(r, m->top); /* Check for error !! */
909 /* Perform the operation */
910 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
912 /* Convert the response */
913 r->top = m_r.size / sizeof(BN_ULONG);
918 /* FIXME: When this error is returned, HWCryptoHook is
919 telling us that falling back to software computation
920 might be a good thing. */
921 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
923 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
927 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
929 ERR_add_error_data(1,rmsg.buf);
938 #ifndef OPENSSL_NO_RSA
939 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
942 HWCryptoHook_ErrMsgBuf rmsg;
943 HWCryptoHook_RSAKeyHandle *hptr;
944 int to_return = 0, ret;
947 rmsg.size = sizeof(tempbuf);
951 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
955 /* This provides support for nForce keys. Since that's opaque data
956 all we do is provide a handle to the proper key and let HWCryptoHook
957 take care of the rest. */
958 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
961 HWCryptoHook_MPI m_a, m_r;
965 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
966 HWCRHK_R_MISSING_KEY_COMPONENTS);
970 /* Prepare the params */
971 bn_expand2(r, rsa->n->top); /* Check for error !! */
975 /* Perform the operation */
976 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
978 /* Convert the response */
979 r->top = m_r.size / sizeof(BN_ULONG);
984 /* FIXME: When this error is returned, HWCryptoHook is
985 telling us that falling back to software computation
986 might be a good thing. */
987 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
989 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
990 HWCRHK_R_REQUEST_FALLBACK);
994 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
995 HWCRHK_R_REQUEST_FAILED);
997 ERR_add_error_data(1,rmsg.buf);
1003 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1005 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1007 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1008 HWCRHK_R_MISSING_KEY_COMPONENTS);
1012 /* Prepare the params */
1013 bn_expand2(r, rsa->n->top); /* Check for error !! */
1015 BN2MPI(m_p, rsa->p);
1016 BN2MPI(m_q, rsa->q);
1017 BN2MPI(m_dmp1, rsa->dmp1);
1018 BN2MPI(m_dmq1, rsa->dmq1);
1019 BN2MPI(m_iqmp, rsa->iqmp);
1022 /* Perform the operation */
1023 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1024 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
1026 /* Convert the response */
1027 r->top = m_r.size / sizeof(BN_ULONG);
1032 /* FIXME: When this error is returned, HWCryptoHook is
1033 telling us that falling back to software computation
1034 might be a good thing. */
1035 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1037 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1038 HWCRHK_R_REQUEST_FALLBACK);
1042 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1043 HWCRHK_R_REQUEST_FAILED);
1045 ERR_add_error_data(1,rmsg.buf);
1049 /* If we're here, we must be here with some semblance of success :-) */
1056 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1057 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1058 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1060 return hwcrhk_mod_exp(r, a, p, m, ctx);
1063 #ifndef OPENSSL_NO_DH
1064 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1065 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1066 const BIGNUM *a, const BIGNUM *p,
1067 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1069 return hwcrhk_mod_exp(r, a, p, m, ctx);
1073 /* Random bytes are good */
1074 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1077 HWCryptoHook_ErrMsgBuf rmsg;
1078 int to_return = 0; /* assume failure */
1082 rmsg.size = sizeof(tempbuf);
1086 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1090 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1093 /* FIXME: When this error is returned, HWCryptoHook is
1094 telling us that falling back to software computation
1095 might be a good thing. */
1096 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1098 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1099 HWCRHK_R_REQUEST_FALLBACK);
1103 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1104 HWCRHK_R_REQUEST_FAILED);
1106 ERR_add_error_data(1,rmsg.buf);
1114 static int hwcrhk_rand_status(void)
1119 /* This cleans up an RSA KM key, called when ex_data is freed */
1121 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1122 int ind,long argl, void *argp)
1125 HWCryptoHook_ErrMsgBuf rmsg;
1126 #ifndef OPENSSL_NO_RSA
1127 HWCryptoHook_RSAKeyHandle *hptr;
1129 #if !defined(OPENSSL_NO_RSA)
1134 rmsg.size = sizeof(tempbuf);
1136 #ifndef OPENSSL_NO_RSA
1137 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1140 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1146 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1147 * these just wrap the POSIX functions and add some logging.
1150 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1151 HWCryptoHook_CallerContext *cactx)
1153 mt->lockid = CRYPTO_get_new_dynlockid();
1154 if (mt->lockid == 0)
1155 return 1; /* failure */
1156 return 0; /* success */
1159 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1161 CRYPTO_w_lock(mt->lockid);
1165 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1167 CRYPTO_w_unlock(mt->lockid);
1170 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1172 CRYPTO_destroy_dynlockid(mt->lockid);
1175 static int hwcrhk_get_pass(const char *prompt_info,
1176 int *len_io, char *buf,
1177 HWCryptoHook_PassphraseContext *ppctx,
1178 HWCryptoHook_CallerContext *cactx)
1180 pem_password_cb *callback = NULL;
1181 void *callback_data = NULL;
1182 UI_METHOD *ui_method = NULL;
1186 if (cactx->ui_method)
1187 ui_method = cactx->ui_method;
1188 if (cactx->password_callback)
1189 callback = cactx->password_callback;
1190 if (cactx->callback_data)
1191 callback_data = cactx->callback_data;
1195 if (ppctx->ui_method)
1197 ui_method = ppctx->ui_method;
1200 if (ppctx->callback_data)
1201 callback_data = ppctx->callback_data;
1203 if (callback == NULL && ui_method == NULL)
1205 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1211 UI *ui = UI_new_method(ui_method);
1215 char *prompt = UI_construct_prompt(ui,
1216 "pass phrase", prompt_info);
1218 ok = UI_add_input_string(ui,prompt,
1219 UI_INPUT_FLAG_DEFAULT_PWD,
1220 buf,0,(*len_io) - 1);
1221 UI_add_user_data(ui, callback_data);
1222 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1229 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1232 *len_io = strlen(buf);
1235 OPENSSL_free(prompt);
1240 *len_io = callback(buf, *len_io, 0, callback_data);
1247 static int hwcrhk_insert_card(const char *prompt_info,
1248 const char *wrong_info,
1249 HWCryptoHook_PassphraseContext *ppctx,
1250 HWCryptoHook_CallerContext *cactx)
1254 void *callback_data = NULL;
1255 UI_METHOD *ui_method = NULL;
1259 if (cactx->ui_method)
1260 ui_method = cactx->ui_method;
1261 if (cactx->callback_data)
1262 callback_data = cactx->callback_data;
1266 if (ppctx->ui_method)
1267 ui_method = ppctx->ui_method;
1268 if (ppctx->callback_data)
1269 callback_data = ppctx->callback_data;
1271 if (ui_method == NULL)
1273 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1274 HWCRHK_R_NO_CALLBACK);
1278 ui = UI_new_method(ui_method);
1286 BIO_snprintf(buf, sizeof(buf)-1,
1287 "Current card: \"%s\"\n", wrong_info);
1288 ok = UI_dup_info_string(ui, buf);
1289 if (ok >= 0 && prompt_info)
1291 BIO_snprintf(buf, sizeof(buf)-1,
1292 "Insert card \"%s\"", prompt_info);
1293 ok = UI_dup_input_boolean(ui, buf,
1294 "\n then hit <enter> or C<enter> to cancel\n",
1295 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1297 UI_add_user_data(ui, callback_data);
1300 ok = UI_process(ui);
1303 if (ok == -2 || (ok >= 0 && answer == 'C'))
1313 static void hwcrhk_log_message(void *logstr, const char *message)
1315 BIO *lstream = NULL;
1317 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1319 lstream=*(BIO **)logstr;
1322 BIO_write(lstream, message, strlen(message));
1324 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1327 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1328 * shared-library. */
1329 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1330 static int bind_fn(ENGINE *e, const char *id)
1332 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1338 IMPLEMENT_DYNAMIC_CHECK_FN()
1339 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1340 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1342 #endif /* !OPENSSL_NO_HW_NCIPHER */
1343 #endif /* !OPENSSL_NO_HW */