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>
67 #include <openssl/rand.h>
68 #include <openssl/rsa.h>
69 #include <openssl/dh.h>
70 #include <openssl/bn.h>
73 #ifndef OPENSSL_NO_HW_NCIPHER
75 /* Attribution notice: nCipher have said several times that it's OK for
76 * us to implement a general interface to their boxes, and recently declared
77 * their HWCryptoHook to be public, and therefore available for us to use.
80 * The hwcryptohook.h included here is from May 2000.
84 #include "hwcryptohook.h"
86 #include "vendor_defns/hwcryptohook.h"
89 #define HWCRHK_LIB_NAME "hwcrhk engine"
90 #include "e_ncipher_err.c"
92 static int hwcrhk_destroy(ENGINE *e);
93 static int hwcrhk_init(ENGINE *e);
94 static int hwcrhk_finish(ENGINE *e);
95 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
97 /* Functions to handle mutexes */
98 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
99 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
100 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
101 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
104 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
105 const BIGNUM *m, BN_CTX *ctx);
107 #ifndef OPENSSL_NO_RSA
109 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
111 /* This function is aliased to mod_exp (with the mont stuff dropped). */
112 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
113 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
115 #ifndef OPENSSL_NO_DH
117 /* This function is alised to mod_exp (with the DH and mont dropped). */
118 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
119 const BIGNUM *a, const BIGNUM *p,
120 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
124 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
125 static int hwcrhk_rand_status(void);
128 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
129 UI_METHOD *ui_method, void *callback_data);
130 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
131 UI_METHOD *ui_method, void *callback_data);
132 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
133 int ind,long argl, void *argp);
135 /* Interaction stuff */
136 static int hwcrhk_insert_card(const char *prompt_info,
137 const char *wrong_info,
138 HWCryptoHook_PassphraseContext *ppctx,
139 HWCryptoHook_CallerContext *cactx);
140 static int hwcrhk_get_pass(const char *prompt_info,
141 int *len_io, char *buf,
142 HWCryptoHook_PassphraseContext *ppctx,
143 HWCryptoHook_CallerContext *cactx);
144 static void hwcrhk_log_message(void *logstr, const char *message);
146 /* The definitions for control commands specific to this engine */
147 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
148 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
149 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
150 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
151 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
152 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
155 "Specifies the path to the 'hwcrhk' shared library",
156 ENGINE_CMD_FLAG_STRING},
157 {HWCRHK_CMD_FORK_CHECK,
159 "Turns fork() checking on or off (boolean)",
160 ENGINE_CMD_FLAG_NUMERIC},
161 {HWCRHK_CMD_THREAD_LOCKING,
163 "Turns thread-safe locking on or off (boolean)",
164 ENGINE_CMD_FLAG_NUMERIC},
165 {HWCRHK_CMD_SET_USER_INTERFACE,
166 "SET_USER_INTERFACE",
167 "Set the global user interface (internal)",
168 ENGINE_CMD_FLAG_INTERNAL},
169 {HWCRHK_CMD_SET_CALLBACK_DATA,
171 "Set the global user interface extra data (internal)",
172 ENGINE_CMD_FLAG_INTERNAL},
176 #ifndef OPENSSL_NO_RSA
177 /* Our internal RSA_METHOD that we provide pointers to */
178 static RSA_METHOD hwcrhk_rsa =
180 "nCipher RSA method",
197 #ifndef OPENSSL_NO_DH
198 /* Our internal DH_METHOD that we provide pointers to */
199 static DH_METHOD hwcrhk_dh =
213 static RAND_METHOD hwcrhk_rand =
215 /* "nCipher RAND method", */
224 /* Constants used when creating the ENGINE */
225 static const char *engine_hwcrhk_id = "chil";
226 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
228 /* Internal stuff for HWCryptoHook */
230 /* Some structures needed for proper use of thread locks */
231 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
232 into HWCryptoHook_Mutex */
233 struct HWCryptoHook_MutexValue
238 /* hwcryptohook.h has some typedefs that turn
239 struct HWCryptoHook_PassphraseContextValue
240 into HWCryptoHook_PassphraseContext */
241 struct HWCryptoHook_PassphraseContextValue
243 UI_METHOD *ui_method;
247 /* hwcryptohook.h has some typedefs that turn
248 struct HWCryptoHook_CallerContextValue
249 into HWCryptoHook_CallerContext */
250 struct HWCryptoHook_CallerContextValue
252 pem_password_cb *password_callback; /* Deprecated! Only present for
253 backward compatibility! */
254 UI_METHOD *ui_method;
258 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
259 BIGNUM's, so lets define a couple of conversion macros */
260 #define BN2MPI(mp, bn) \
261 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
262 #define MPI2BN(bn, mp) \
263 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
265 static BIO *logstream = NULL;
266 static int disable_mutex_callbacks = 0;
268 /* One might wonder why these are needed, since one can pass down at least
269 a UI_METHOD and a pointer to callback data to the key-loading functions.
270 The thing is that the ModExp and RSAImmed functions can load keys as well,
271 if the data they get is in a special, nCipher-defined format (hint: if you
272 look at the private exponent of the RSA data as a string, you'll see this
273 string: "nCipher KM tool key id", followed by some bytes, followed a key
274 identity string, followed by more bytes. This happens when you use "embed"
275 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
276 any passphrase or caller context, and our functions can't really take any
277 callback data either. Still, the "insert_card" and "get_passphrase"
278 callbacks may be called down the line, and will need to know what user
279 interface callbacks to call, and having callback data from the application
280 may be a nice thing as well, so we need to keep track of that globally. */
281 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
283 /* Stuff to pass to the HWCryptoHook library */
284 static HWCryptoHook_InitInfo hwcrhk_globals = {
285 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
286 &logstream, /* logstream */
287 sizeof(BN_ULONG), /* limbsize */
288 0, /* mslimb first: false for BNs */
289 -1, /* msbyte first: use native */
290 0, /* Max mutexes, 0 = no small limit */
291 0, /* Max simultaneous, 0 = default */
293 /* The next few are mutex stuff: we write wrapper functions
294 around the OS mutex functions. We initialise them to 0
295 here, and change that to actual function pointers in hwcrhk_init()
296 if dynamic locks are supported (that is, if the application
297 programmer has made sure of setting up callbacks bafore starting
298 this engine) *and* if disable_mutex_callbacks hasn't been set by
299 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
300 sizeof(HWCryptoHook_Mutex),
306 /* The next few are condvar stuff: we write wrapper functions
307 round the OS functions. Currently not implemented and not
308 and absolute necessity even in threaded programs, therefore
309 0'ed. Will hopefully be implemented some day, since it
310 enhances the efficiency of HWCryptoHook. */
311 0, /* sizeof(HWCryptoHook_CondVar), */
312 0, /* hwcrhk_cv_init, */
313 0, /* hwcrhk_cv_wait, */
314 0, /* hwcrhk_cv_signal, */
315 0, /* hwcrhk_cv_broadcast, */
316 0, /* hwcrhk_cv_destroy, */
318 hwcrhk_get_pass, /* pass phrase */
319 hwcrhk_insert_card, /* insert a card */
320 hwcrhk_log_message /* Log message */
324 /* Now, to our own code */
326 /* This internal function is used by ENGINE_ncipher() and possibly by the
327 * "dynamic" ENGINE support too */
328 static int bind_helper(ENGINE *e)
330 #ifndef OPENSSL_NO_RSA
331 const RSA_METHOD *meth1;
333 #ifndef OPENSSL_NO_DH
334 const DH_METHOD *meth2;
336 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
337 !ENGINE_set_name(e, engine_hwcrhk_name) ||
338 #ifndef OPENSSL_NO_RSA
339 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
341 #ifndef OPENSSL_NO_DH
342 !ENGINE_set_DH(e, &hwcrhk_dh) ||
344 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
345 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
346 !ENGINE_set_init_function(e, hwcrhk_init) ||
347 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
348 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
349 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
350 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
351 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
354 #ifndef OPENSSL_NO_RSA
355 /* We know that the "PKCS1_SSLeay()" functions hook properly
356 * to the cswift-specific mod_exp and mod_exp_crt so we use
357 * those functions. NB: We don't use ENGINE_openssl() or
358 * anything "more generic" because something like the RSAref
359 * code may not hook properly, and if you own one of these
360 * cards then you have the right to do RSA operations on it
362 meth1 = RSA_PKCS1_SSLeay();
363 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
364 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
365 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
366 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
369 #ifndef OPENSSL_NO_DH
370 /* Much the same for Diffie-Hellman */
371 meth2 = DH_OpenSSL();
372 hwcrhk_dh.generate_key = meth2->generate_key;
373 hwcrhk_dh.compute_key = meth2->compute_key;
376 /* Ensure the hwcrhk error handling is set up */
377 ERR_load_HWCRHK_strings();
381 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
382 static ENGINE *engine_ncipher(void)
384 ENGINE *ret = ENGINE_new();
387 if(!bind_helper(ret))
395 void ENGINE_load_chil(void)
397 /* Copied from eng_[openssl|dyn].c */
398 ENGINE *toadd = engine_ncipher();
406 /* This is a process-global DSO handle used for loading and unloading
407 * the HWCryptoHook library. NB: This is only set (or unset) during an
408 * init() or finish() call (reference counts permitting) and they're
409 * operating with global locks, so this should be thread-safe
411 static DSO *hwcrhk_dso = NULL;
412 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
413 #ifndef OPENSSL_NO_RSA
414 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
417 /* These are the function pointers that are (un)set when the library has
418 * successfully (un)loaded. */
419 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
420 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
421 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
422 #ifndef OPENSSL_NO_RSA
423 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
425 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
426 #ifndef OPENSSL_NO_RSA
427 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
428 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
429 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
431 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
433 /* Used in the DSO operations. */
434 static const char *HWCRHK_LIBNAME = NULL;
435 static void free_HWCRHK_LIBNAME(void)
438 OPENSSL_free((void*)HWCRHK_LIBNAME);
439 HWCRHK_LIBNAME = NULL;
441 static const char *get_HWCRHK_LIBNAME(void)
444 return HWCRHK_LIBNAME;
447 static long set_HWCRHK_LIBNAME(const char *name)
449 free_HWCRHK_LIBNAME();
450 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
452 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
453 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
454 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
455 #ifndef OPENSSL_NO_RSA
456 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
458 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
459 #ifndef OPENSSL_NO_RSA
460 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
461 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
462 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
464 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
466 /* HWCryptoHook library functions and mechanics - these are used by the
467 * higher-level functions further down. NB: As and where there's no
468 * error checking, take a look lower down where these functions are
469 * called, the checking and error handling is probably down there. */
471 /* utility function to obtain a context */
472 static int get_context(HWCryptoHook_ContextHandle *hac,
473 HWCryptoHook_CallerContext *cac)
476 HWCryptoHook_ErrMsgBuf rmsg;
479 rmsg.size = sizeof(tempbuf);
481 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
488 /* similarly to release one. */
489 static void release_context(HWCryptoHook_ContextHandle hac)
491 p_hwcrhk_Finish(hac);
494 /* Destructor (complements the "ENGINE_ncipher()" constructor) */
495 static int hwcrhk_destroy(ENGINE *e)
497 free_HWCRHK_LIBNAME();
498 ERR_unload_HWCRHK_strings();
502 /* (de)initialisation functions. */
503 static int hwcrhk_init(ENGINE *e)
505 HWCryptoHook_Init_t *p1;
506 HWCryptoHook_Finish_t *p2;
507 HWCryptoHook_ModExp_t *p3;
508 #ifndef OPENSSL_NO_RSA
509 HWCryptoHook_RSA_t *p4;
510 HWCryptoHook_RSALoadKey_t *p5;
511 HWCryptoHook_RSAGetPublicKey_t *p6;
512 HWCryptoHook_RSAUnloadKey_t *p7;
514 HWCryptoHook_RandomBytes_t *p8;
515 HWCryptoHook_ModExpCRT_t *p9;
517 if(hwcrhk_dso != NULL)
519 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
522 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
523 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
524 if(hwcrhk_dso == NULL)
526 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
529 if(!(p1 = (HWCryptoHook_Init_t *)
530 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
531 !(p2 = (HWCryptoHook_Finish_t *)
532 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
533 !(p3 = (HWCryptoHook_ModExp_t *)
534 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
535 #ifndef OPENSSL_NO_RSA
536 !(p4 = (HWCryptoHook_RSA_t *)
537 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
538 !(p5 = (HWCryptoHook_RSALoadKey_t *)
539 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
540 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
541 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
542 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
543 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
545 !(p8 = (HWCryptoHook_RandomBytes_t *)
546 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
547 !(p9 = (HWCryptoHook_ModExpCRT_t *)
548 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
550 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
553 /* Copy the pointers */
555 p_hwcrhk_Finish = p2;
556 p_hwcrhk_ModExp = p3;
557 #ifndef OPENSSL_NO_RSA
559 p_hwcrhk_RSALoadKey = p5;
560 p_hwcrhk_RSAGetPublicKey = p6;
561 p_hwcrhk_RSAUnloadKey = p7;
563 p_hwcrhk_RandomBytes = p8;
564 p_hwcrhk_ModExpCRT = p9;
566 /* Check if the application decided to support dynamic locks,
567 and if it does, use them. */
568 if (disable_mutex_callbacks == 0)
570 if (CRYPTO_get_dynlock_create_callback() != NULL &&
571 CRYPTO_get_dynlock_lock_callback() != NULL &&
572 CRYPTO_get_dynlock_destroy_callback() != NULL)
574 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
575 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
576 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
577 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
579 else if (CRYPTO_get_locking_callback() != NULL)
581 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_LOCKING_MISSING);
582 ERR_add_error_data(1,"You HAVE to add dynamic locking callbacks via CRYPTO_set_dynlock_{create,lock,destroy}_callback()");
587 /* Try and get a context - if not, we may have a DSO but no
589 if(!get_context(&hwcrhk_context, &password_context))
591 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
594 /* Everything's fine. */
595 #ifndef OPENSSL_NO_RSA
596 if (hndidx_rsa == -1)
597 hndidx_rsa = RSA_get_ex_new_index(0,
598 "nFast HWCryptoHook RSA key handle",
599 NULL, NULL, hwcrhk_ex_free);
604 DSO_free(hwcrhk_dso);
606 p_hwcrhk_Init = NULL;
607 p_hwcrhk_Finish = NULL;
608 p_hwcrhk_ModExp = NULL;
609 #ifndef OPENSSL_NO_RSA
611 p_hwcrhk_RSALoadKey = NULL;
612 p_hwcrhk_RSAGetPublicKey = NULL;
613 p_hwcrhk_RSAUnloadKey = NULL;
615 p_hwcrhk_ModExpCRT = NULL;
616 p_hwcrhk_RandomBytes = NULL;
620 static int hwcrhk_finish(ENGINE *e)
623 free_HWCRHK_LIBNAME();
624 if(hwcrhk_dso == NULL)
626 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
630 release_context(hwcrhk_context);
631 if(!DSO_free(hwcrhk_dso))
633 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
641 p_hwcrhk_Init = NULL;
642 p_hwcrhk_Finish = NULL;
643 p_hwcrhk_ModExp = NULL;
644 #ifndef OPENSSL_NO_RSA
646 p_hwcrhk_RSALoadKey = NULL;
647 p_hwcrhk_RSAGetPublicKey = NULL;
648 p_hwcrhk_RSAUnloadKey = NULL;
650 p_hwcrhk_ModExpCRT = NULL;
651 p_hwcrhk_RandomBytes = NULL;
655 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
661 case HWCRHK_CMD_SO_PATH:
664 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
669 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
672 return set_HWCRHK_LIBNAME((const char *)p);
673 case ENGINE_CTRL_SET_LOGSTREAM:
677 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
683 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
686 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
688 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
690 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
691 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
692 password_context.password_callback = (pem_password_cb *)f;
693 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
695 case ENGINE_CTRL_SET_USER_INTERFACE:
696 case HWCRHK_CMD_SET_USER_INTERFACE:
697 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
698 password_context.ui_method = (UI_METHOD *)p;
699 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
701 case ENGINE_CTRL_SET_CALLBACK_DATA:
702 case HWCRHK_CMD_SET_CALLBACK_DATA:
703 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
704 password_context.callback_data = p;
705 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
707 /* this enables or disables the "SimpleForkCheck" flag used in the
708 * initialisation structure. */
709 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
710 case HWCRHK_CMD_FORK_CHECK:
711 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
713 hwcrhk_globals.flags |=
714 HWCryptoHook_InitFlags_SimpleForkCheck;
716 hwcrhk_globals.flags &=
717 ~HWCryptoHook_InitFlags_SimpleForkCheck;
718 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
720 /* This will prevent the initialisation function from "installing"
721 * the mutex-handling callbacks, even if they are available from
722 * within the library (or were provided to the library from the
723 * calling application). This is to remove any baggage for
724 * applications not using multithreading. */
725 case ENGINE_CTRL_CHIL_NO_LOCKING:
726 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
727 disable_mutex_callbacks = 1;
728 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
730 case HWCRHK_CMD_THREAD_LOCKING:
731 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
732 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
733 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
736 /* The command isn't understood by this engine */
738 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
739 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
747 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
748 UI_METHOD *ui_method, void *callback_data)
750 #ifndef OPENSSL_NO_RSA
753 EVP_PKEY *res = NULL;
754 #ifndef OPENSSL_NO_RSA
755 HWCryptoHook_MPI e, n;
756 HWCryptoHook_RSAKeyHandle *hptr;
758 #if !defined(OPENSSL_NO_RSA)
760 HWCryptoHook_ErrMsgBuf rmsg;
762 HWCryptoHook_PassphraseContext ppctx;
764 #if !defined(OPENSSL_NO_RSA)
766 rmsg.size = sizeof(tempbuf);
771 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
772 HWCRHK_R_NOT_INITIALISED);
775 #ifndef OPENSSL_NO_RSA
776 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
779 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
780 ERR_R_MALLOC_FAILURE);
783 ppctx.ui_method = ui_method;
784 ppctx.callback_data = callback_data;
785 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
788 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
789 HWCRHK_R_CHIL_ERROR);
790 ERR_add_error_data(1,rmsg.buf);
795 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
800 #ifndef OPENSSL_NO_RSA
801 rtmp = RSA_new_method(eng);
802 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
805 rtmp->flags |= RSA_FLAG_EXT_PKEY;
808 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
809 != HWCRYPTOHOOK_ERROR_MPISIZE)
811 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
812 ERR_add_error_data(1,rmsg.buf);
816 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
817 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
821 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
823 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
824 HWCRHK_R_CHIL_ERROR);
825 ERR_add_error_data(1,rmsg.buf);
828 rtmp->e->top = e.size / sizeof(BN_ULONG);
830 rtmp->n->top = n.size / sizeof(BN_ULONG);
833 res = EVP_PKEY_new();
834 EVP_PKEY_assign_RSA(res, rtmp);
838 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
839 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
845 #ifndef OPENSSL_NO_RSA
852 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
853 UI_METHOD *ui_method, void *callback_data)
855 EVP_PKEY *res = NULL;
857 #ifndef OPENSSL_NO_RSA
858 res = hwcrhk_load_privkey(eng, key_id,
859 ui_method, callback_data);
865 #ifndef OPENSSL_NO_RSA
870 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
872 res->pkey.rsa = RSA_new();
873 res->pkey.rsa->n = rsa->n;
874 res->pkey.rsa->e = rsa->e;
877 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
883 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
884 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
895 /* A little mod_exp */
896 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
897 const BIGNUM *m, BN_CTX *ctx)
900 HWCryptoHook_ErrMsgBuf rmsg;
901 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
902 we use them directly, plus a little macro magic. We only
903 thing we need to make sure of is that enough space is allocated. */
904 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
907 to_return = 0; /* expect failure */
909 rmsg.size = sizeof(tempbuf);
913 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
916 /* Prepare the params */
917 bn_expand2(r, m->top); /* Check for error !! */
923 /* Perform the operation */
924 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
926 /* Convert the response */
927 r->top = m_r.size / sizeof(BN_ULONG);
932 /* FIXME: When this error is returned, HWCryptoHook is
933 telling us that falling back to software computation
934 might be a good thing. */
935 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
937 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
941 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
943 ERR_add_error_data(1,rmsg.buf);
952 #ifndef OPENSSL_NO_RSA
953 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
956 HWCryptoHook_ErrMsgBuf rmsg;
957 HWCryptoHook_RSAKeyHandle *hptr;
958 int to_return = 0, ret;
961 rmsg.size = sizeof(tempbuf);
965 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
969 /* This provides support for nForce keys. Since that's opaque data
970 all we do is provide a handle to the proper key and let HWCryptoHook
971 take care of the rest. */
972 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
975 HWCryptoHook_MPI m_a, m_r;
979 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
980 HWCRHK_R_MISSING_KEY_COMPONENTS);
984 /* Prepare the params */
985 bn_expand2(r, rsa->n->top); /* Check for error !! */
989 /* Perform the operation */
990 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
992 /* Convert the response */
993 r->top = m_r.size / sizeof(BN_ULONG);
998 /* FIXME: When this error is returned, HWCryptoHook is
999 telling us that falling back to software computation
1000 might be a good thing. */
1001 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1003 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1004 HWCRHK_R_REQUEST_FALLBACK);
1008 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1009 HWCRHK_R_REQUEST_FAILED);
1011 ERR_add_error_data(1,rmsg.buf);
1017 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1019 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1021 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1022 HWCRHK_R_MISSING_KEY_COMPONENTS);
1026 /* Prepare the params */
1027 bn_expand2(r, rsa->n->top); /* Check for error !! */
1029 BN2MPI(m_p, rsa->p);
1030 BN2MPI(m_q, rsa->q);
1031 BN2MPI(m_dmp1, rsa->dmp1);
1032 BN2MPI(m_dmq1, rsa->dmq1);
1033 BN2MPI(m_iqmp, rsa->iqmp);
1036 /* Perform the operation */
1037 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1038 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1040 /* Convert the response */
1041 r->top = m_r.size / sizeof(BN_ULONG);
1046 /* FIXME: When this error is returned, HWCryptoHook is
1047 telling us that falling back to software computation
1048 might be a good thing. */
1049 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1051 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1052 HWCRHK_R_REQUEST_FALLBACK);
1056 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1057 HWCRHK_R_REQUEST_FAILED);
1059 ERR_add_error_data(1,rmsg.buf);
1063 /* If we're here, we must be here with some semblance of success :-) */
1070 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1071 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1072 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1074 return hwcrhk_mod_exp(r, a, p, m, ctx);
1077 #ifndef OPENSSL_NO_DH
1078 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1079 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1080 const BIGNUM *a, const BIGNUM *p,
1081 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1083 return hwcrhk_mod_exp(r, a, p, m, ctx);
1087 /* Random bytes are good */
1088 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1091 HWCryptoHook_ErrMsgBuf rmsg;
1092 int to_return = 0; /* assume failure */
1096 rmsg.size = sizeof(tempbuf);
1100 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1104 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1107 /* FIXME: When this error is returned, HWCryptoHook is
1108 telling us that falling back to software computation
1109 might be a good thing. */
1110 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1112 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1113 HWCRHK_R_REQUEST_FALLBACK);
1117 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1118 HWCRHK_R_REQUEST_FAILED);
1120 ERR_add_error_data(1,rmsg.buf);
1128 static int hwcrhk_rand_status(void)
1133 /* This cleans up an RSA KM key, called when ex_data is freed */
1135 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1136 int ind,long argl, void *argp)
1139 HWCryptoHook_ErrMsgBuf rmsg;
1140 #ifndef OPENSSL_NO_RSA
1141 HWCryptoHook_RSAKeyHandle *hptr;
1143 #if !defined(OPENSSL_NO_RSA)
1148 rmsg.size = sizeof(tempbuf);
1150 #ifndef OPENSSL_NO_RSA
1151 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1154 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1160 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1161 * these just wrap the POSIX functions and add some logging.
1164 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1165 HWCryptoHook_CallerContext *cactx)
1167 mt->lockid = CRYPTO_get_new_dynlockid();
1168 if (mt->lockid == 0)
1169 return 1; /* failure */
1170 return 0; /* success */
1173 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1175 CRYPTO_w_lock(mt->lockid);
1179 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1181 CRYPTO_w_unlock(mt->lockid);
1184 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1186 CRYPTO_destroy_dynlockid(mt->lockid);
1189 static int hwcrhk_get_pass(const char *prompt_info,
1190 int *len_io, char *buf,
1191 HWCryptoHook_PassphraseContext *ppctx,
1192 HWCryptoHook_CallerContext *cactx)
1194 pem_password_cb *callback = NULL;
1195 void *callback_data = NULL;
1196 UI_METHOD *ui_method = NULL;
1200 if (cactx->ui_method)
1201 ui_method = cactx->ui_method;
1202 if (cactx->password_callback)
1203 callback = cactx->password_callback;
1204 if (cactx->callback_data)
1205 callback_data = cactx->callback_data;
1209 if (ppctx->ui_method)
1211 ui_method = ppctx->ui_method;
1214 if (ppctx->callback_data)
1215 callback_data = ppctx->callback_data;
1217 if (callback == NULL && ui_method == NULL)
1219 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1225 UI *ui = UI_new_method(ui_method);
1229 char *prompt = UI_construct_prompt(ui,
1230 "pass phrase", prompt_info);
1232 ok = UI_add_input_string(ui,prompt,
1233 UI_INPUT_FLAG_DEFAULT_PWD,
1234 buf,0,(*len_io) - 1);
1235 UI_add_user_data(ui, callback_data);
1236 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1243 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1246 *len_io = strlen(buf);
1249 OPENSSL_free(prompt);
1254 *len_io = callback(buf, *len_io, 0, callback_data);
1261 static int hwcrhk_insert_card(const char *prompt_info,
1262 const char *wrong_info,
1263 HWCryptoHook_PassphraseContext *ppctx,
1264 HWCryptoHook_CallerContext *cactx)
1268 void *callback_data = NULL;
1269 UI_METHOD *ui_method = NULL;
1273 if (cactx->ui_method)
1274 ui_method = cactx->ui_method;
1275 if (cactx->callback_data)
1276 callback_data = cactx->callback_data;
1280 if (ppctx->ui_method)
1281 ui_method = ppctx->ui_method;
1282 if (ppctx->callback_data)
1283 callback_data = ppctx->callback_data;
1285 if (ui_method == NULL)
1287 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1288 HWCRHK_R_NO_CALLBACK);
1292 ui = UI_new_method(ui_method);
1300 BIO_snprintf(buf, sizeof(buf)-1,
1301 "Current card: \"%s\"\n", wrong_info);
1302 ok = UI_dup_info_string(ui, buf);
1303 if (ok >= 0 && prompt_info)
1305 BIO_snprintf(buf, sizeof(buf)-1,
1306 "Insert card \"%s\"", prompt_info);
1307 ok = UI_dup_input_boolean(ui, buf,
1308 "\n then hit <enter> or C<enter> to cancel\n",
1309 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1311 UI_add_user_data(ui, callback_data);
1314 ok = UI_process(ui);
1317 if (ok == -2 || (ok >= 0 && answer == 'C'))
1327 static void hwcrhk_log_message(void *logstr, const char *message)
1329 BIO *lstream = NULL;
1331 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1333 lstream=*(BIO **)logstr;
1336 BIO_printf(lstream, "%s\n", message);
1338 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1341 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1342 * shared-library. */
1343 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1344 static int bind_fn(ENGINE *e, const char *id)
1346 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1352 IMPLEMENT_DYNAMIC_CHECK_FN()
1353 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1354 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1356 #endif /* !OPENSSL_NO_HW_NCIPHER */
1357 #endif /* !OPENSSL_NO_HW */