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)
564 if (CRYPTO_get_dynlock_create_callback() != NULL &&
565 CRYPTO_get_dynlock_lock_callback() != NULL &&
566 CRYPTO_get_dynlock_destroy_callback() != NULL)
568 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
569 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
570 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
571 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
573 else if (CRYPTO_get_locking_callback() != NULL)
575 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_LOCKING_MISSING);
576 ERR_add_error_data(1,"You HAVE to add dynamic locking callbacks via CRYPTO_set_dynlock_{create,lock,destroy}_callback()");
581 /* Try and get a context - if not, we may have a DSO but no
583 if(!get_context(&hwcrhk_context, &password_context))
585 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
588 /* Everything's fine. */
589 #ifndef OPENSSL_NO_RSA
590 if (hndidx_rsa == -1)
591 hndidx_rsa = RSA_get_ex_new_index(0,
592 "nFast HWCryptoHook RSA key handle",
593 NULL, NULL, hwcrhk_ex_free);
598 DSO_free(hwcrhk_dso);
600 p_hwcrhk_Init = NULL;
601 p_hwcrhk_Finish = NULL;
602 p_hwcrhk_ModExp = NULL;
603 #ifndef OPENSSL_NO_RSA
605 p_hwcrhk_RSALoadKey = NULL;
606 p_hwcrhk_RSAGetPublicKey = NULL;
607 p_hwcrhk_RSAUnloadKey = NULL;
609 p_hwcrhk_ModExpCRT = NULL;
610 p_hwcrhk_RandomBytes = NULL;
614 static int hwcrhk_finish(ENGINE *e)
617 free_HWCRHK_LIBNAME();
618 if(hwcrhk_dso == NULL)
620 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
624 release_context(hwcrhk_context);
625 if(!DSO_free(hwcrhk_dso))
627 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
635 p_hwcrhk_Init = NULL;
636 p_hwcrhk_Finish = NULL;
637 p_hwcrhk_ModExp = NULL;
638 #ifndef OPENSSL_NO_RSA
640 p_hwcrhk_RSALoadKey = NULL;
641 p_hwcrhk_RSAGetPublicKey = NULL;
642 p_hwcrhk_RSAUnloadKey = NULL;
644 p_hwcrhk_ModExpCRT = NULL;
645 p_hwcrhk_RandomBytes = NULL;
649 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
655 case HWCRHK_CMD_SO_PATH:
658 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
663 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
666 return set_HWCRHK_LIBNAME((const char *)p);
667 case ENGINE_CTRL_SET_LOGSTREAM:
671 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
677 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
680 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
682 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
684 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
685 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
686 password_context.password_callback = (pem_password_cb *)f;
687 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
689 case ENGINE_CTRL_SET_USER_INTERFACE:
690 case HWCRHK_CMD_SET_USER_INTERFACE:
691 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
692 password_context.ui_method = (UI_METHOD *)p;
693 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
695 case ENGINE_CTRL_SET_CALLBACK_DATA:
696 case HWCRHK_CMD_SET_CALLBACK_DATA:
697 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
698 password_context.callback_data = p;
699 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
701 /* this enables or disables the "SimpleForkCheck" flag used in the
702 * initialisation structure. */
703 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
704 case HWCRHK_CMD_FORK_CHECK:
705 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
707 hwcrhk_globals.flags |=
708 HWCryptoHook_InitFlags_SimpleForkCheck;
710 hwcrhk_globals.flags &=
711 ~HWCryptoHook_InitFlags_SimpleForkCheck;
712 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
714 /* This will prevent the initialisation function from "installing"
715 * the mutex-handling callbacks, even if they are available from
716 * within the library (or were provided to the library from the
717 * calling application). This is to remove any baggage for
718 * applications not using multithreading. */
719 case ENGINE_CTRL_CHIL_NO_LOCKING:
720 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
721 disable_mutex_callbacks = 1;
722 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
724 case HWCRHK_CMD_THREAD_LOCKING:
725 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
726 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
727 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
730 /* The command isn't understood by this engine */
732 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
733 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
741 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
742 UI_METHOD *ui_method, void *callback_data)
744 #ifndef OPENSSL_NO_RSA
747 EVP_PKEY *res = NULL;
748 #ifndef OPENSSL_NO_RSA
749 HWCryptoHook_MPI e, n;
750 HWCryptoHook_RSAKeyHandle *hptr;
752 #if !defined(OPENSSL_NO_RSA)
754 HWCryptoHook_ErrMsgBuf rmsg;
756 HWCryptoHook_PassphraseContext ppctx;
758 #if !defined(OPENSSL_NO_RSA)
760 rmsg.size = sizeof(tempbuf);
765 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
766 HWCRHK_R_NOT_INITIALISED);
769 #ifndef OPENSSL_NO_RSA
770 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
773 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
774 ERR_R_MALLOC_FAILURE);
777 ppctx.ui_method = ui_method;
778 ppctx.callback_data = callback_data;
779 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
782 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
783 HWCRHK_R_CHIL_ERROR);
784 ERR_add_error_data(1,rmsg.buf);
789 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
794 #ifndef OPENSSL_NO_RSA
795 rtmp = RSA_new_method(eng);
796 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
799 rtmp->flags |= RSA_FLAG_EXT_PKEY;
802 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
803 != HWCRYPTOHOOK_ERROR_MPISIZE)
805 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
806 ERR_add_error_data(1,rmsg.buf);
810 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
811 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
815 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
817 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
818 HWCRHK_R_CHIL_ERROR);
819 ERR_add_error_data(1,rmsg.buf);
822 rtmp->e->top = e.size / sizeof(BN_ULONG);
824 rtmp->n->top = n.size / sizeof(BN_ULONG);
827 res = EVP_PKEY_new();
828 EVP_PKEY_assign_RSA(res, rtmp);
832 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
833 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
839 #ifndef OPENSSL_NO_RSA
846 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
847 UI_METHOD *ui_method, void *callback_data)
849 EVP_PKEY *res = NULL;
851 #ifndef OPENSSL_NO_RSA
852 res = hwcrhk_load_privkey(eng, key_id,
853 ui_method, callback_data);
859 #ifndef OPENSSL_NO_RSA
864 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
866 res->pkey.rsa = RSA_new();
867 res->pkey.rsa->n = rsa->n;
868 res->pkey.rsa->e = rsa->e;
871 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
877 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
878 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
889 /* A little mod_exp */
890 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
891 const BIGNUM *m, BN_CTX *ctx)
894 HWCryptoHook_ErrMsgBuf rmsg;
895 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
896 we use them directly, plus a little macro magic. We only
897 thing we need to make sure of is that enough space is allocated. */
898 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
901 to_return = 0; /* expect failure */
903 rmsg.size = sizeof(tempbuf);
907 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
910 /* Prepare the params */
911 bn_expand2(r, m->top); /* Check for error !! */
917 /* Perform the operation */
918 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
920 /* Convert the response */
921 r->top = m_r.size / sizeof(BN_ULONG);
926 /* FIXME: When this error is returned, HWCryptoHook is
927 telling us that falling back to software computation
928 might be a good thing. */
929 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
931 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
935 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
937 ERR_add_error_data(1,rmsg.buf);
946 #ifndef OPENSSL_NO_RSA
947 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
950 HWCryptoHook_ErrMsgBuf rmsg;
951 HWCryptoHook_RSAKeyHandle *hptr;
952 int to_return = 0, ret;
955 rmsg.size = sizeof(tempbuf);
959 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
963 /* This provides support for nForce keys. Since that's opaque data
964 all we do is provide a handle to the proper key and let HWCryptoHook
965 take care of the rest. */
966 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
969 HWCryptoHook_MPI m_a, m_r;
973 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
974 HWCRHK_R_MISSING_KEY_COMPONENTS);
978 /* Prepare the params */
979 bn_expand2(r, rsa->n->top); /* Check for error !! */
983 /* Perform the operation */
984 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
986 /* Convert the response */
987 r->top = m_r.size / sizeof(BN_ULONG);
992 /* FIXME: When this error is returned, HWCryptoHook is
993 telling us that falling back to software computation
994 might be a good thing. */
995 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
997 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
998 HWCRHK_R_REQUEST_FALLBACK);
1002 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1003 HWCRHK_R_REQUEST_FAILED);
1005 ERR_add_error_data(1,rmsg.buf);
1011 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1013 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1015 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1016 HWCRHK_R_MISSING_KEY_COMPONENTS);
1020 /* Prepare the params */
1021 bn_expand2(r, rsa->n->top); /* Check for error !! */
1023 BN2MPI(m_p, rsa->p);
1024 BN2MPI(m_q, rsa->q);
1025 BN2MPI(m_dmp1, rsa->dmp1);
1026 BN2MPI(m_dmq1, rsa->dmq1);
1027 BN2MPI(m_iqmp, rsa->iqmp);
1030 /* Perform the operation */
1031 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1032 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1034 /* Convert the response */
1035 r->top = m_r.size / sizeof(BN_ULONG);
1040 /* FIXME: When this error is returned, HWCryptoHook is
1041 telling us that falling back to software computation
1042 might be a good thing. */
1043 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1045 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1046 HWCRHK_R_REQUEST_FALLBACK);
1050 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1051 HWCRHK_R_REQUEST_FAILED);
1053 ERR_add_error_data(1,rmsg.buf);
1057 /* If we're here, we must be here with some semblance of success :-) */
1064 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1065 static int hwcrhk_mod_exp_mont(BIGNUM *r, 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);
1071 #ifndef OPENSSL_NO_DH
1072 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1073 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1074 const BIGNUM *a, const BIGNUM *p,
1075 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1077 return hwcrhk_mod_exp(r, a, p, m, ctx);
1081 /* Random bytes are good */
1082 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1085 HWCryptoHook_ErrMsgBuf rmsg;
1086 int to_return = 0; /* assume failure */
1090 rmsg.size = sizeof(tempbuf);
1094 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1098 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1101 /* FIXME: When this error is returned, HWCryptoHook is
1102 telling us that falling back to software computation
1103 might be a good thing. */
1104 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1106 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1107 HWCRHK_R_REQUEST_FALLBACK);
1111 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1112 HWCRHK_R_REQUEST_FAILED);
1114 ERR_add_error_data(1,rmsg.buf);
1122 static int hwcrhk_rand_status(void)
1127 /* This cleans up an RSA KM key, called when ex_data is freed */
1129 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1130 int ind,long argl, void *argp)
1133 HWCryptoHook_ErrMsgBuf rmsg;
1134 #ifndef OPENSSL_NO_RSA
1135 HWCryptoHook_RSAKeyHandle *hptr;
1137 #if !defined(OPENSSL_NO_RSA)
1142 rmsg.size = sizeof(tempbuf);
1144 #ifndef OPENSSL_NO_RSA
1145 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1148 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1154 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1155 * these just wrap the POSIX functions and add some logging.
1158 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1159 HWCryptoHook_CallerContext *cactx)
1161 mt->lockid = CRYPTO_get_new_dynlockid();
1162 if (mt->lockid == 0)
1163 return 1; /* failure */
1164 return 0; /* success */
1167 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1169 CRYPTO_w_lock(mt->lockid);
1173 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1175 CRYPTO_w_unlock(mt->lockid);
1178 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1180 CRYPTO_destroy_dynlockid(mt->lockid);
1183 static int hwcrhk_get_pass(const char *prompt_info,
1184 int *len_io, char *buf,
1185 HWCryptoHook_PassphraseContext *ppctx,
1186 HWCryptoHook_CallerContext *cactx)
1188 pem_password_cb *callback = NULL;
1189 void *callback_data = NULL;
1190 UI_METHOD *ui_method = NULL;
1194 if (cactx->ui_method)
1195 ui_method = cactx->ui_method;
1196 if (cactx->password_callback)
1197 callback = cactx->password_callback;
1198 if (cactx->callback_data)
1199 callback_data = cactx->callback_data;
1203 if (ppctx->ui_method)
1205 ui_method = ppctx->ui_method;
1208 if (ppctx->callback_data)
1209 callback_data = ppctx->callback_data;
1211 if (callback == NULL && ui_method == NULL)
1213 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1219 UI *ui = UI_new_method(ui_method);
1223 char *prompt = UI_construct_prompt(ui,
1224 "pass phrase", prompt_info);
1226 ok = UI_add_input_string(ui,prompt,
1227 UI_INPUT_FLAG_DEFAULT_PWD,
1228 buf,0,(*len_io) - 1);
1229 UI_add_user_data(ui, callback_data);
1230 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1237 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1240 *len_io = strlen(buf);
1243 OPENSSL_free(prompt);
1248 *len_io = callback(buf, *len_io, 0, callback_data);
1255 static int hwcrhk_insert_card(const char *prompt_info,
1256 const char *wrong_info,
1257 HWCryptoHook_PassphraseContext *ppctx,
1258 HWCryptoHook_CallerContext *cactx)
1262 void *callback_data = NULL;
1263 UI_METHOD *ui_method = NULL;
1267 if (cactx->ui_method)
1268 ui_method = cactx->ui_method;
1269 if (cactx->callback_data)
1270 callback_data = cactx->callback_data;
1274 if (ppctx->ui_method)
1275 ui_method = ppctx->ui_method;
1276 if (ppctx->callback_data)
1277 callback_data = ppctx->callback_data;
1279 if (ui_method == NULL)
1281 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1282 HWCRHK_R_NO_CALLBACK);
1286 ui = UI_new_method(ui_method);
1294 BIO_snprintf(buf, sizeof(buf)-1,
1295 "Current card: \"%s\"\n", wrong_info);
1296 ok = UI_dup_info_string(ui, buf);
1297 if (ok >= 0 && prompt_info)
1299 BIO_snprintf(buf, sizeof(buf)-1,
1300 "Insert card \"%s\"", prompt_info);
1301 ok = UI_dup_input_boolean(ui, buf,
1302 "\n then hit <enter> or C<enter> to cancel\n",
1303 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1305 UI_add_user_data(ui, callback_data);
1308 ok = UI_process(ui);
1311 if (ok == -2 || (ok >= 0 && answer == 'C'))
1321 static void hwcrhk_log_message(void *logstr, const char *message)
1323 BIO *lstream = NULL;
1325 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1327 lstream=*(BIO **)logstr;
1330 BIO_printf(lstream, "%s\n", message);
1332 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1335 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1336 * shared-library. */
1337 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1338 static int bind_fn(ENGINE *e, const char *id)
1340 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1346 IMPLEMENT_DYNAMIC_CHECK_FN()
1347 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1348 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1350 #endif /* !OPENSSL_NO_HW_NCIPHER */
1351 #endif /* !OPENSSL_NO_HW */