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)(void));
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",
193 #ifndef OPENSSL_NO_DH
194 /* Our internal DH_METHOD that we provide pointers to */
195 static DH_METHOD hwcrhk_dh =
209 static RAND_METHOD hwcrhk_rand =
211 /* "nCipher RAND method", */
220 /* Constants used when creating the ENGINE */
221 static const char *engine_hwcrhk_id = "chil";
222 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
224 /* Internal stuff for HWCryptoHook */
226 /* Some structures needed for proper use of thread locks */
227 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
228 into HWCryptoHook_Mutex */
229 struct HWCryptoHook_MutexValue
234 /* hwcryptohook.h has some typedefs that turn
235 struct HWCryptoHook_PassphraseContextValue
236 into HWCryptoHook_PassphraseContext */
237 struct HWCryptoHook_PassphraseContextValue
239 UI_METHOD *ui_method;
243 /* hwcryptohook.h has some typedefs that turn
244 struct HWCryptoHook_CallerContextValue
245 into HWCryptoHook_CallerContext */
246 struct HWCryptoHook_CallerContextValue
248 pem_password_cb *password_callback; /* Deprecated! Only present for
249 backward compatibility! */
250 UI_METHOD *ui_method;
254 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
255 BIGNUM's, so lets define a couple of conversion macros */
256 #define BN2MPI(mp, bn) \
257 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
258 #define MPI2BN(bn, mp) \
259 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
261 static BIO *logstream = NULL;
262 static int disable_mutex_callbacks = 0;
264 /* One might wonder why these are needed, since one can pass down at least
265 a UI_METHOD and a pointer to callback data to the key-loading functions.
266 The thing is that the ModExp and RSAImmed functions can load keys as well,
267 if the data they get is in a special, nCipher-defined format (hint: if you
268 look at the private exponent of the RSA data as a string, you'll see this
269 string: "nCipher KM tool key id", followed by some bytes, followed a key
270 identity string, followed by more bytes. This happens when you use "embed"
271 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
272 any passphrase or caller context, and our functions can't really take any
273 callback data either. Still, the "insert_card" and "get_passphrase"
274 callbacks may be called down the line, and will need to know what user
275 interface callbacks to call, and having callback data from the application
276 may be a nice thing as well, so we need to keep track of that globally. */
277 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
279 /* Stuff to pass to the HWCryptoHook library */
280 static HWCryptoHook_InitInfo hwcrhk_globals = {
281 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
282 &logstream, /* logstream */
283 sizeof(BN_ULONG), /* limbsize */
284 0, /* mslimb first: false for BNs */
285 -1, /* msbyte first: use native */
286 0, /* Max mutexes, 0 = no small limit */
287 0, /* Max simultaneous, 0 = default */
289 /* The next few are mutex stuff: we write wrapper functions
290 around the OS mutex functions. We initialise them to 0
291 here, and change that to actual function pointers in hwcrhk_init()
292 if dynamic locks are supported (that is, if the application
293 programmer has made sure of setting up callbacks bafore starting
294 this engine) *and* if disable_mutex_callbacks hasn't been set by
295 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
296 sizeof(HWCryptoHook_Mutex),
302 /* The next few are condvar stuff: we write wrapper functions
303 round the OS functions. Currently not implemented and not
304 and absolute necessity even in threaded programs, therefore
305 0'ed. Will hopefully be implemented some day, since it
306 enhances the efficiency of HWCryptoHook. */
307 0, /* sizeof(HWCryptoHook_CondVar), */
308 0, /* hwcrhk_cv_init, */
309 0, /* hwcrhk_cv_wait, */
310 0, /* hwcrhk_cv_signal, */
311 0, /* hwcrhk_cv_broadcast, */
312 0, /* hwcrhk_cv_destroy, */
314 hwcrhk_get_pass, /* pass phrase */
315 hwcrhk_insert_card, /* insert a card */
316 hwcrhk_log_message /* Log message */
320 /* Now, to our own code */
322 /* This internal function is used by ENGINE_ncipher() and possibly by the
323 * "dynamic" ENGINE support too */
324 static int bind_helper(ENGINE *e)
326 #ifndef OPENSSL_NO_RSA
327 const RSA_METHOD *meth1;
329 #ifndef OPENSSL_NO_DH
330 const DH_METHOD *meth2;
332 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
333 !ENGINE_set_name(e, engine_hwcrhk_name) ||
334 #ifndef OPENSSL_NO_RSA
335 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
337 #ifndef OPENSSL_NO_DH
338 !ENGINE_set_DH(e, &hwcrhk_dh) ||
340 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
341 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
342 !ENGINE_set_init_function(e, hwcrhk_init) ||
343 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
344 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
345 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
346 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
347 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
350 #ifndef OPENSSL_NO_RSA
351 /* We know that the "PKCS1_SSLeay()" functions hook properly
352 * to the cswift-specific mod_exp and mod_exp_crt so we use
353 * those functions. NB: We don't use ENGINE_openssl() or
354 * anything "more generic" because something like the RSAref
355 * code may not hook properly, and if you own one of these
356 * cards then you have the right to do RSA operations on it
358 meth1 = RSA_PKCS1_SSLeay();
359 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
360 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
361 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
362 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
365 #ifndef OPENSSL_NO_DH
366 /* Much the same for Diffie-Hellman */
367 meth2 = DH_OpenSSL();
368 hwcrhk_dh.generate_key = meth2->generate_key;
369 hwcrhk_dh.compute_key = meth2->compute_key;
372 /* Ensure the hwcrhk error handling is set up */
373 ERR_load_HWCRHK_strings();
377 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
378 static ENGINE *engine_ncipher(void)
380 ENGINE *ret = ENGINE_new();
383 if(!bind_helper(ret))
391 void ENGINE_load_chil(void)
393 /* Copied from eng_[openssl|dyn].c */
394 ENGINE *toadd = engine_ncipher();
402 /* This is a process-global DSO handle used for loading and unloading
403 * the HWCryptoHook library. NB: This is only set (or unset) during an
404 * init() or finish() call (reference counts permitting) and they're
405 * operating with global locks, so this should be thread-safe
407 static DSO *hwcrhk_dso = NULL;
408 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
409 #ifndef OPENSSL_NO_RSA
410 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
413 /* These are the function pointers that are (un)set when the library has
414 * successfully (un)loaded. */
415 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
416 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
417 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
418 #ifndef OPENSSL_NO_RSA
419 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
421 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
422 #ifndef OPENSSL_NO_RSA
423 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
424 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
425 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
427 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
429 /* Used in the DSO operations. */
430 static const char *HWCRHK_LIBNAME = NULL;
431 static void free_HWCRHK_LIBNAME(void)
434 OPENSSL_free((void*)HWCRHK_LIBNAME);
435 HWCRHK_LIBNAME = NULL;
437 static const char *get_HWCRHK_LIBNAME(void)
440 return HWCRHK_LIBNAME;
443 static long set_HWCRHK_LIBNAME(const char *name)
445 free_HWCRHK_LIBNAME();
446 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
448 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
449 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
450 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
451 #ifndef OPENSSL_NO_RSA
452 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
454 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
455 #ifndef OPENSSL_NO_RSA
456 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
457 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
458 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
460 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
462 /* HWCryptoHook library functions and mechanics - these are used by the
463 * higher-level functions further down. NB: As and where there's no
464 * error checking, take a look lower down where these functions are
465 * called, the checking and error handling is probably down there. */
467 /* utility function to obtain a context */
468 static int get_context(HWCryptoHook_ContextHandle *hac,
469 HWCryptoHook_CallerContext *cac)
472 HWCryptoHook_ErrMsgBuf rmsg;
475 rmsg.size = sizeof(tempbuf);
477 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
484 /* similarly to release one. */
485 static void release_context(HWCryptoHook_ContextHandle hac)
487 p_hwcrhk_Finish(hac);
490 /* Destructor (complements the "ENGINE_ncipher()" constructor) */
491 static int hwcrhk_destroy(ENGINE *e)
493 free_HWCRHK_LIBNAME();
494 ERR_unload_HWCRHK_strings();
498 /* (de)initialisation functions. */
499 static int hwcrhk_init(ENGINE *e)
501 HWCryptoHook_Init_t *p1;
502 HWCryptoHook_Finish_t *p2;
503 HWCryptoHook_ModExp_t *p3;
504 #ifndef OPENSSL_NO_RSA
505 HWCryptoHook_RSA_t *p4;
506 HWCryptoHook_RSALoadKey_t *p5;
507 HWCryptoHook_RSAGetPublicKey_t *p6;
508 HWCryptoHook_RSAUnloadKey_t *p7;
510 HWCryptoHook_RandomBytes_t *p8;
511 HWCryptoHook_ModExpCRT_t *p9;
513 if(hwcrhk_dso != NULL)
515 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
518 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
519 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
520 if(hwcrhk_dso == NULL)
522 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
525 if(!(p1 = (HWCryptoHook_Init_t *)
526 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
527 !(p2 = (HWCryptoHook_Finish_t *)
528 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
529 !(p3 = (HWCryptoHook_ModExp_t *)
530 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
531 #ifndef OPENSSL_NO_RSA
532 !(p4 = (HWCryptoHook_RSA_t *)
533 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
534 !(p5 = (HWCryptoHook_RSALoadKey_t *)
535 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
536 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
537 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
538 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
539 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
541 !(p8 = (HWCryptoHook_RandomBytes_t *)
542 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
543 !(p9 = (HWCryptoHook_ModExpCRT_t *)
544 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
546 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
549 /* Copy the pointers */
551 p_hwcrhk_Finish = p2;
552 p_hwcrhk_ModExp = p3;
553 #ifndef OPENSSL_NO_RSA
555 p_hwcrhk_RSALoadKey = p5;
556 p_hwcrhk_RSAGetPublicKey = p6;
557 p_hwcrhk_RSAUnloadKey = p7;
559 p_hwcrhk_RandomBytes = p8;
560 p_hwcrhk_ModExpCRT = p9;
562 /* Check if the application decided to support dynamic locks,
563 and if it does, use them. */
564 if (disable_mutex_callbacks == 0)
566 if (CRYPTO_get_dynlock_create_callback() != NULL &&
567 CRYPTO_get_dynlock_lock_callback() != NULL &&
568 CRYPTO_get_dynlock_destroy_callback() != NULL)
570 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
571 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
572 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
573 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
575 else if (CRYPTO_get_locking_callback() != NULL)
577 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_LOCKING_MISSING);
578 ERR_add_error_data(1,"You HAVE to add dynamic locking callbacks via CRYPTO_set_dynlock_{create,lock,destroy}_callback()");
583 /* Try and get a context - if not, we may have a DSO but no
585 if(!get_context(&hwcrhk_context, &password_context))
587 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
590 /* Everything's fine. */
591 #ifndef OPENSSL_NO_RSA
592 if (hndidx_rsa == -1)
593 hndidx_rsa = RSA_get_ex_new_index(0,
594 "nFast HWCryptoHook RSA key handle",
595 NULL, NULL, hwcrhk_ex_free);
600 DSO_free(hwcrhk_dso);
602 p_hwcrhk_Init = NULL;
603 p_hwcrhk_Finish = NULL;
604 p_hwcrhk_ModExp = NULL;
605 #ifndef OPENSSL_NO_RSA
607 p_hwcrhk_RSALoadKey = NULL;
608 p_hwcrhk_RSAGetPublicKey = NULL;
609 p_hwcrhk_RSAUnloadKey = NULL;
611 p_hwcrhk_ModExpCRT = NULL;
612 p_hwcrhk_RandomBytes = NULL;
616 static int hwcrhk_finish(ENGINE *e)
619 free_HWCRHK_LIBNAME();
620 if(hwcrhk_dso == NULL)
622 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
626 release_context(hwcrhk_context);
627 if(!DSO_free(hwcrhk_dso))
629 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
637 p_hwcrhk_Init = NULL;
638 p_hwcrhk_Finish = NULL;
639 p_hwcrhk_ModExp = NULL;
640 #ifndef OPENSSL_NO_RSA
642 p_hwcrhk_RSALoadKey = NULL;
643 p_hwcrhk_RSAGetPublicKey = NULL;
644 p_hwcrhk_RSAUnloadKey = NULL;
646 p_hwcrhk_ModExpCRT = NULL;
647 p_hwcrhk_RandomBytes = NULL;
651 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
657 case HWCRHK_CMD_SO_PATH:
660 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
665 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
668 return set_HWCRHK_LIBNAME((const char *)p);
669 case ENGINE_CTRL_SET_LOGSTREAM:
673 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
679 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
682 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
684 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
686 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
687 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
688 password_context.password_callback = (pem_password_cb *)f;
689 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
691 case ENGINE_CTRL_SET_USER_INTERFACE:
692 case HWCRHK_CMD_SET_USER_INTERFACE:
693 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
694 password_context.ui_method = (UI_METHOD *)p;
695 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
697 case ENGINE_CTRL_SET_CALLBACK_DATA:
698 case HWCRHK_CMD_SET_CALLBACK_DATA:
699 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
700 password_context.callback_data = p;
701 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
703 /* this enables or disables the "SimpleForkCheck" flag used in the
704 * initialisation structure. */
705 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
706 case HWCRHK_CMD_FORK_CHECK:
707 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
709 hwcrhk_globals.flags |=
710 HWCryptoHook_InitFlags_SimpleForkCheck;
712 hwcrhk_globals.flags &=
713 ~HWCryptoHook_InitFlags_SimpleForkCheck;
714 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
716 /* This will prevent the initialisation function from "installing"
717 * the mutex-handling callbacks, even if they are available from
718 * within the library (or were provided to the library from the
719 * calling application). This is to remove any baggage for
720 * applications not using multithreading. */
721 case ENGINE_CTRL_CHIL_NO_LOCKING:
722 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
723 disable_mutex_callbacks = 1;
724 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
726 case HWCRHK_CMD_THREAD_LOCKING:
727 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
728 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
729 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
732 /* The command isn't understood by this engine */
734 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
735 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
743 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
744 UI_METHOD *ui_method, void *callback_data)
746 #ifndef OPENSSL_NO_RSA
749 EVP_PKEY *res = NULL;
750 #ifndef OPENSSL_NO_RSA
751 HWCryptoHook_MPI e, n;
752 HWCryptoHook_RSAKeyHandle *hptr;
754 #if !defined(OPENSSL_NO_RSA)
756 HWCryptoHook_ErrMsgBuf rmsg;
758 HWCryptoHook_PassphraseContext ppctx;
760 #if !defined(OPENSSL_NO_RSA)
762 rmsg.size = sizeof(tempbuf);
767 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
768 HWCRHK_R_NOT_INITIALISED);
771 #ifndef OPENSSL_NO_RSA
772 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
775 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
776 ERR_R_MALLOC_FAILURE);
779 ppctx.ui_method = ui_method;
780 ppctx.callback_data = callback_data;
781 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
784 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
785 HWCRHK_R_CHIL_ERROR);
786 ERR_add_error_data(1,rmsg.buf);
791 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
796 #ifndef OPENSSL_NO_RSA
797 rtmp = RSA_new_method(eng);
798 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
801 rtmp->flags |= RSA_FLAG_EXT_PKEY;
804 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
805 != HWCRYPTOHOOK_ERROR_MPISIZE)
807 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
808 ERR_add_error_data(1,rmsg.buf);
812 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
813 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
817 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
819 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
820 HWCRHK_R_CHIL_ERROR);
821 ERR_add_error_data(1,rmsg.buf);
824 rtmp->e->top = e.size / sizeof(BN_ULONG);
826 rtmp->n->top = n.size / sizeof(BN_ULONG);
829 res = EVP_PKEY_new();
830 EVP_PKEY_assign_RSA(res, rtmp);
834 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
835 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
841 #ifndef OPENSSL_NO_RSA
848 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
849 UI_METHOD *ui_method, void *callback_data)
851 EVP_PKEY *res = NULL;
853 #ifndef OPENSSL_NO_RSA
854 res = hwcrhk_load_privkey(eng, key_id,
855 ui_method, callback_data);
861 #ifndef OPENSSL_NO_RSA
866 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
868 res->pkey.rsa = RSA_new();
869 res->pkey.rsa->n = rsa->n;
870 res->pkey.rsa->e = rsa->e;
873 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
879 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
880 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
891 /* A little mod_exp */
892 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
893 const BIGNUM *m, BN_CTX *ctx)
896 HWCryptoHook_ErrMsgBuf rmsg;
897 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
898 we use them directly, plus a little macro magic. We only
899 thing we need to make sure of is that enough space is allocated. */
900 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
903 to_return = 0; /* expect failure */
905 rmsg.size = sizeof(tempbuf);
909 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
912 /* Prepare the params */
913 bn_expand2(r, m->top); /* Check for error !! */
919 /* Perform the operation */
920 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
922 /* Convert the response */
923 r->top = m_r.size / sizeof(BN_ULONG);
928 /* FIXME: When this error is returned, HWCryptoHook is
929 telling us that falling back to software computation
930 might be a good thing. */
931 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
933 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
937 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
939 ERR_add_error_data(1,rmsg.buf);
948 #ifndef OPENSSL_NO_RSA
949 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
952 HWCryptoHook_ErrMsgBuf rmsg;
953 HWCryptoHook_RSAKeyHandle *hptr;
954 int to_return = 0, ret;
957 rmsg.size = sizeof(tempbuf);
961 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
965 /* This provides support for nForce keys. Since that's opaque data
966 all we do is provide a handle to the proper key and let HWCryptoHook
967 take care of the rest. */
968 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
971 HWCryptoHook_MPI m_a, m_r;
975 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
976 HWCRHK_R_MISSING_KEY_COMPONENTS);
980 /* Prepare the params */
981 bn_expand2(r, rsa->n->top); /* Check for error !! */
985 /* Perform the operation */
986 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
988 /* Convert the response */
989 r->top = m_r.size / sizeof(BN_ULONG);
994 /* FIXME: When this error is returned, HWCryptoHook is
995 telling us that falling back to software computation
996 might be a good thing. */
997 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
999 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1000 HWCRHK_R_REQUEST_FALLBACK);
1004 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1005 HWCRHK_R_REQUEST_FAILED);
1007 ERR_add_error_data(1,rmsg.buf);
1013 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1015 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1017 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1018 HWCRHK_R_MISSING_KEY_COMPONENTS);
1022 /* Prepare the params */
1023 bn_expand2(r, rsa->n->top); /* Check for error !! */
1025 BN2MPI(m_p, rsa->p);
1026 BN2MPI(m_q, rsa->q);
1027 BN2MPI(m_dmp1, rsa->dmp1);
1028 BN2MPI(m_dmq1, rsa->dmq1);
1029 BN2MPI(m_iqmp, rsa->iqmp);
1032 /* Perform the operation */
1033 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1034 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1036 /* Convert the response */
1037 r->top = m_r.size / sizeof(BN_ULONG);
1042 /* FIXME: When this error is returned, HWCryptoHook is
1043 telling us that falling back to software computation
1044 might be a good thing. */
1045 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1047 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1048 HWCRHK_R_REQUEST_FALLBACK);
1052 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1053 HWCRHK_R_REQUEST_FAILED);
1055 ERR_add_error_data(1,rmsg.buf);
1059 /* If we're here, we must be here with some semblance of success :-) */
1066 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1067 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1068 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1070 return hwcrhk_mod_exp(r, a, p, m, ctx);
1073 #ifndef OPENSSL_NO_DH
1074 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1075 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1076 const BIGNUM *a, const BIGNUM *p,
1077 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1079 return hwcrhk_mod_exp(r, a, p, m, ctx);
1083 /* Random bytes are good */
1084 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1087 HWCryptoHook_ErrMsgBuf rmsg;
1088 int to_return = 0; /* assume failure */
1092 rmsg.size = sizeof(tempbuf);
1096 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1100 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1103 /* FIXME: When this error is returned, HWCryptoHook is
1104 telling us that falling back to software computation
1105 might be a good thing. */
1106 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1108 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1109 HWCRHK_R_REQUEST_FALLBACK);
1113 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1114 HWCRHK_R_REQUEST_FAILED);
1116 ERR_add_error_data(1,rmsg.buf);
1124 static int hwcrhk_rand_status(void)
1129 /* This cleans up an RSA KM key, called when ex_data is freed */
1131 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1132 int ind,long argl, void *argp)
1135 HWCryptoHook_ErrMsgBuf rmsg;
1136 #ifndef OPENSSL_NO_RSA
1137 HWCryptoHook_RSAKeyHandle *hptr;
1139 #if !defined(OPENSSL_NO_RSA)
1144 rmsg.size = sizeof(tempbuf);
1146 #ifndef OPENSSL_NO_RSA
1147 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1150 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1156 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1157 * these just wrap the POSIX functions and add some logging.
1160 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1161 HWCryptoHook_CallerContext *cactx)
1163 mt->lockid = CRYPTO_get_new_dynlockid();
1164 if (mt->lockid == 0)
1165 return 1; /* failure */
1166 return 0; /* success */
1169 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1171 CRYPTO_w_lock(mt->lockid);
1175 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1177 CRYPTO_w_unlock(mt->lockid);
1180 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1182 CRYPTO_destroy_dynlockid(mt->lockid);
1185 static int hwcrhk_get_pass(const char *prompt_info,
1186 int *len_io, char *buf,
1187 HWCryptoHook_PassphraseContext *ppctx,
1188 HWCryptoHook_CallerContext *cactx)
1190 pem_password_cb *callback = NULL;
1191 void *callback_data = NULL;
1192 UI_METHOD *ui_method = NULL;
1196 if (cactx->ui_method)
1197 ui_method = cactx->ui_method;
1198 if (cactx->password_callback)
1199 callback = cactx->password_callback;
1200 if (cactx->callback_data)
1201 callback_data = cactx->callback_data;
1205 if (ppctx->ui_method)
1207 ui_method = ppctx->ui_method;
1210 if (ppctx->callback_data)
1211 callback_data = ppctx->callback_data;
1213 if (callback == NULL && ui_method == NULL)
1215 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1221 UI *ui = UI_new_method(ui_method);
1225 char *prompt = UI_construct_prompt(ui,
1226 "pass phrase", prompt_info);
1228 ok = UI_add_input_string(ui,prompt,
1229 UI_INPUT_FLAG_DEFAULT_PWD,
1230 buf,0,(*len_io) - 1);
1231 UI_add_user_data(ui, callback_data);
1232 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1239 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1242 *len_io = strlen(buf);
1245 OPENSSL_free(prompt);
1250 *len_io = callback(buf, *len_io, 0, callback_data);
1257 static int hwcrhk_insert_card(const char *prompt_info,
1258 const char *wrong_info,
1259 HWCryptoHook_PassphraseContext *ppctx,
1260 HWCryptoHook_CallerContext *cactx)
1264 void *callback_data = NULL;
1265 UI_METHOD *ui_method = NULL;
1269 if (cactx->ui_method)
1270 ui_method = cactx->ui_method;
1271 if (cactx->callback_data)
1272 callback_data = cactx->callback_data;
1276 if (ppctx->ui_method)
1277 ui_method = ppctx->ui_method;
1278 if (ppctx->callback_data)
1279 callback_data = ppctx->callback_data;
1281 if (ui_method == NULL)
1283 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1284 HWCRHK_R_NO_CALLBACK);
1288 ui = UI_new_method(ui_method);
1296 BIO_snprintf(buf, sizeof(buf)-1,
1297 "Current card: \"%s\"\n", wrong_info);
1298 ok = UI_dup_info_string(ui, buf);
1299 if (ok >= 0 && prompt_info)
1301 BIO_snprintf(buf, sizeof(buf)-1,
1302 "Insert card \"%s\"", prompt_info);
1303 ok = UI_dup_input_boolean(ui, buf,
1304 "\n then hit <enter> or C<enter> to cancel\n",
1305 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1307 UI_add_user_data(ui, callback_data);
1310 ok = UI_process(ui);
1313 if (ok == -2 || (ok >= 0 && answer == 'C'))
1323 static void hwcrhk_log_message(void *logstr, const char *message)
1325 BIO *lstream = NULL;
1327 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1329 lstream=*(BIO **)logstr;
1332 BIO_printf(lstream, "%s\n", message);
1334 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1337 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1338 * shared-library. */
1339 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1340 static int bind_fn(ENGINE *e, const char *id)
1342 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1348 IMPLEMENT_DYNAMIC_CHECK_FN()
1349 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1350 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1352 #endif /* !OPENSSL_NO_HW_NCIPHER */
1353 #endif /* !OPENSSL_NO_HW */