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>
72 #ifndef OPENSSL_NO_HW_NCIPHER
74 /* Attribution notice: nCipher have said several times that it's OK for
75 * us to implement a general interface to their boxes, and recently declared
76 * their HWCryptoHook to be public, and therefore available for us to use.
79 * The hwcryptohook.h included here is from May 2000.
83 #include "hwcryptohook.h"
85 #include "vendor_defns/hwcryptohook.h"
88 #define HWCRHK_LIB_NAME "hwcrhk engine"
89 #include "e_ncipher_err.c"
91 static int hwcrhk_destroy(ENGINE *e);
92 static int hwcrhk_init(ENGINE *e);
93 static int hwcrhk_finish(ENGINE *e);
94 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
96 /* Functions to handle mutexes */
97 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
98 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
99 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
100 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
103 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
104 const BIGNUM *m, BN_CTX *ctx);
106 #ifndef OPENSSL_NO_RSA
108 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
110 /* This function is aliased to mod_exp (with the mont stuff dropped). */
111 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
112 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
114 #ifndef OPENSSL_NO_DH
116 /* This function is alised to mod_exp (with the DH and mont dropped). */
117 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
118 const BIGNUM *a, const BIGNUM *p,
119 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
123 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
124 static int hwcrhk_rand_status(void);
127 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
128 UI_METHOD *ui_method, void *callback_data);
129 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
130 UI_METHOD *ui_method, void *callback_data);
131 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
132 int ind,long argl, void *argp);
134 /* Interaction stuff */
135 static int hwcrhk_insert_card(const char *prompt_info,
136 const char *wrong_info,
137 HWCryptoHook_PassphraseContext *ppctx,
138 HWCryptoHook_CallerContext *cactx);
139 static int hwcrhk_get_pass(const char *prompt_info,
140 int *len_io, char *buf,
141 HWCryptoHook_PassphraseContext *ppctx,
142 HWCryptoHook_CallerContext *cactx);
143 static void hwcrhk_log_message(void *logstr, const char *message);
145 /* The definitions for control commands specific to this engine */
146 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
147 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
148 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
149 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
150 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
151 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
154 "Specifies the path to the 'hwcrhk' shared library",
155 ENGINE_CMD_FLAG_STRING},
156 {HWCRHK_CMD_FORK_CHECK,
158 "Turns fork() checking on or off (boolean)",
159 ENGINE_CMD_FLAG_NUMERIC},
160 {HWCRHK_CMD_THREAD_LOCKING,
162 "Turns thread-safe locking on or off (boolean)",
163 ENGINE_CMD_FLAG_NUMERIC},
164 {HWCRHK_CMD_SET_USER_INTERFACE,
165 "SET_USER_INTERFACE",
166 "Set the global user interface (internal)",
167 ENGINE_CMD_FLAG_INTERNAL},
168 {HWCRHK_CMD_SET_CALLBACK_DATA,
170 "Set the global user interface extra data (internal)",
171 ENGINE_CMD_FLAG_INTERNAL},
175 #ifndef OPENSSL_NO_RSA
176 /* Our internal RSA_METHOD that we provide pointers to */
177 static RSA_METHOD hwcrhk_rsa =
179 "nCipher RSA method",
196 #ifndef OPENSSL_NO_DH
197 /* Our internal DH_METHOD that we provide pointers to */
198 static DH_METHOD hwcrhk_dh =
212 static RAND_METHOD hwcrhk_rand =
214 /* "nCipher RAND method", */
223 /* Constants used when creating the ENGINE */
224 static const char *engine_hwcrhk_id = "chil";
225 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
227 /* Internal stuff for HWCryptoHook */
229 /* Some structures needed for proper use of thread locks */
230 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
231 into HWCryptoHook_Mutex */
232 struct HWCryptoHook_MutexValue
237 /* hwcryptohook.h has some typedefs that turn
238 struct HWCryptoHook_PassphraseContextValue
239 into HWCryptoHook_PassphraseContext */
240 struct HWCryptoHook_PassphraseContextValue
242 UI_METHOD *ui_method;
246 /* hwcryptohook.h has some typedefs that turn
247 struct HWCryptoHook_CallerContextValue
248 into HWCryptoHook_CallerContext */
249 struct HWCryptoHook_CallerContextValue
251 pem_password_cb *password_callback; /* Deprecated! Only present for
252 backward compatibility! */
253 UI_METHOD *ui_method;
257 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
258 BIGNUM's, so lets define a couple of conversion macros */
259 #define BN2MPI(mp, bn) \
260 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
261 #define MPI2BN(bn, mp) \
262 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
264 static BIO *logstream = NULL;
265 static int disable_mutex_callbacks = 0;
267 /* One might wonder why these are needed, since one can pass down at least
268 a UI_METHOD and a pointer to callback data to the key-loading functions.
269 The thing is that the ModExp and RSAImmed functions can load keys as well,
270 if the data they get is in a special, nCipher-defined format (hint: if you
271 look at the private exponent of the RSA data as a string, you'll see this
272 string: "nCipher KM tool key id", followed by some bytes, followed a key
273 identity string, followed by more bytes. This happens when you use "embed"
274 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
275 any passphrase or caller context, and our functions can't really take any
276 callback data either. Still, the "insert_card" and "get_passphrase"
277 callbacks may be called down the line, and will need to know what user
278 interface callbacks to call, and having callback data from the application
279 may be a nice thing as well, so we need to keep track of that globally. */
280 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
282 /* Stuff to pass to the HWCryptoHook library */
283 static HWCryptoHook_InitInfo hwcrhk_globals = {
284 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
285 &logstream, /* logstream */
286 sizeof(BN_ULONG), /* limbsize */
287 0, /* mslimb first: false for BNs */
288 -1, /* msbyte first: use native */
289 0, /* Max mutexes, 0 = no small limit */
290 0, /* Max simultaneous, 0 = default */
292 /* The next few are mutex stuff: we write wrapper functions
293 around the OS mutex functions. We initialise them to 0
294 here, and change that to actual function pointers in hwcrhk_init()
295 if dynamic locks are supported (that is, if the application
296 programmer has made sure of setting up callbacks bafore starting
297 this engine) *and* if disable_mutex_callbacks hasn't been set by
298 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
299 sizeof(HWCryptoHook_Mutex),
305 /* The next few are condvar stuff: we write wrapper functions
306 round the OS functions. Currently not implemented and not
307 and absolute necessity even in threaded programs, therefore
308 0'ed. Will hopefully be implemented some day, since it
309 enhances the efficiency of HWCryptoHook. */
310 0, /* sizeof(HWCryptoHook_CondVar), */
311 0, /* hwcrhk_cv_init, */
312 0, /* hwcrhk_cv_wait, */
313 0, /* hwcrhk_cv_signal, */
314 0, /* hwcrhk_cv_broadcast, */
315 0, /* hwcrhk_cv_destroy, */
317 hwcrhk_get_pass, /* pass phrase */
318 hwcrhk_insert_card, /* insert a card */
319 hwcrhk_log_message /* Log message */
323 /* Now, to our own code */
325 /* This internal function is used by ENGINE_ncipher() and possibly by the
326 * "dynamic" ENGINE support too */
327 static int bind_helper(ENGINE *e)
329 #ifndef OPENSSL_NO_RSA
330 const RSA_METHOD *meth1;
332 #ifndef OPENSSL_NO_DH
333 const DH_METHOD *meth2;
335 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
336 !ENGINE_set_name(e, engine_hwcrhk_name) ||
337 #ifndef OPENSSL_NO_RSA
338 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
340 #ifndef OPENSSL_NO_DH
341 !ENGINE_set_DH(e, &hwcrhk_dh) ||
343 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
344 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
345 !ENGINE_set_init_function(e, hwcrhk_init) ||
346 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
347 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
348 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
349 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
350 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
353 #ifndef OPENSSL_NO_RSA
354 /* We know that the "PKCS1_SSLeay()" functions hook properly
355 * to the cswift-specific mod_exp and mod_exp_crt so we use
356 * those functions. NB: We don't use ENGINE_openssl() or
357 * anything "more generic" because something like the RSAref
358 * code may not hook properly, and if you own one of these
359 * cards then you have the right to do RSA operations on it
361 meth1 = RSA_PKCS1_SSLeay();
362 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
363 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
364 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
365 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
368 #ifndef OPENSSL_NO_DH
369 /* Much the same for Diffie-Hellman */
370 meth2 = DH_OpenSSL();
371 hwcrhk_dh.generate_key = meth2->generate_key;
372 hwcrhk_dh.compute_key = meth2->compute_key;
375 /* Ensure the hwcrhk error handling is set up */
376 ERR_load_HWCRHK_strings();
380 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
381 static ENGINE *engine_ncipher(void)
383 ENGINE *ret = ENGINE_new();
386 if(!bind_helper(ret))
394 void ENGINE_load_chil(void)
396 /* Copied from eng_[openssl|dyn].c */
397 ENGINE *toadd = engine_ncipher();
405 /* This is a process-global DSO handle used for loading and unloading
406 * the HWCryptoHook library. NB: This is only set (or unset) during an
407 * init() or finish() call (reference counts permitting) and they're
408 * operating with global locks, so this should be thread-safe
410 static DSO *hwcrhk_dso = NULL;
411 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
412 #ifndef OPENSSL_NO_RSA
413 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
416 /* These are the function pointers that are (un)set when the library has
417 * successfully (un)loaded. */
418 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
419 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
420 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
421 #ifndef OPENSSL_NO_RSA
422 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
424 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
425 #ifndef OPENSSL_NO_RSA
426 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
427 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
428 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
430 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
432 /* Used in the DSO operations. */
433 static const char *HWCRHK_LIBNAME = NULL;
434 static void free_HWCRHK_LIBNAME(void)
437 OPENSSL_free((void*)HWCRHK_LIBNAME);
438 HWCRHK_LIBNAME = NULL;
440 static const char *get_HWCRHK_LIBNAME(void)
443 return HWCRHK_LIBNAME;
446 static long set_HWCRHK_LIBNAME(const char *name)
448 free_HWCRHK_LIBNAME();
449 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
451 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
452 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
453 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
454 #ifndef OPENSSL_NO_RSA
455 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
457 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
458 #ifndef OPENSSL_NO_RSA
459 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
460 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
461 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
463 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
465 /* HWCryptoHook library functions and mechanics - these are used by the
466 * higher-level functions further down. NB: As and where there's no
467 * error checking, take a look lower down where these functions are
468 * called, the checking and error handling is probably down there. */
470 /* utility function to obtain a context */
471 static int get_context(HWCryptoHook_ContextHandle *hac,
472 HWCryptoHook_CallerContext *cac)
475 HWCryptoHook_ErrMsgBuf rmsg;
478 rmsg.size = sizeof(tempbuf);
480 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
487 /* similarly to release one. */
488 static void release_context(HWCryptoHook_ContextHandle hac)
490 p_hwcrhk_Finish(hac);
493 /* Destructor (complements the "ENGINE_ncipher()" constructor) */
494 static int hwcrhk_destroy(ENGINE *e)
496 free_HWCRHK_LIBNAME();
497 ERR_unload_HWCRHK_strings();
501 /* (de)initialisation functions. */
502 static int hwcrhk_init(ENGINE *e)
504 HWCryptoHook_Init_t *p1;
505 HWCryptoHook_Finish_t *p2;
506 HWCryptoHook_ModExp_t *p3;
507 #ifndef OPENSSL_NO_RSA
508 HWCryptoHook_RSA_t *p4;
509 HWCryptoHook_RSALoadKey_t *p5;
510 HWCryptoHook_RSAGetPublicKey_t *p6;
511 HWCryptoHook_RSAUnloadKey_t *p7;
513 HWCryptoHook_RandomBytes_t *p8;
514 HWCryptoHook_ModExpCRT_t *p9;
516 if(hwcrhk_dso != NULL)
518 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
521 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
522 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
523 if(hwcrhk_dso == NULL)
525 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
528 if(!(p1 = (HWCryptoHook_Init_t *)
529 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
530 !(p2 = (HWCryptoHook_Finish_t *)
531 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
532 !(p3 = (HWCryptoHook_ModExp_t *)
533 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
534 #ifndef OPENSSL_NO_RSA
535 !(p4 = (HWCryptoHook_RSA_t *)
536 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
537 !(p5 = (HWCryptoHook_RSALoadKey_t *)
538 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
539 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
540 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
541 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
542 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
544 !(p8 = (HWCryptoHook_RandomBytes_t *)
545 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
546 !(p9 = (HWCryptoHook_ModExpCRT_t *)
547 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
549 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
552 /* Copy the pointers */
554 p_hwcrhk_Finish = p2;
555 p_hwcrhk_ModExp = p3;
556 #ifndef OPENSSL_NO_RSA
558 p_hwcrhk_RSALoadKey = p5;
559 p_hwcrhk_RSAGetPublicKey = p6;
560 p_hwcrhk_RSAUnloadKey = p7;
562 p_hwcrhk_RandomBytes = p8;
563 p_hwcrhk_ModExpCRT = p9;
565 /* Check if the application decided to support dynamic locks,
566 and if it does, use them. */
567 if (disable_mutex_callbacks == 0)
569 if (CRYPTO_get_dynlock_create_callback() != NULL &&
570 CRYPTO_get_dynlock_lock_callback() != NULL &&
571 CRYPTO_get_dynlock_destroy_callback() != NULL)
573 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
574 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
575 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
576 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
578 else if (CRYPTO_get_locking_callback() != NULL)
580 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_LOCKING_MISSING);
581 ERR_add_error_data(1,"You HAVE to add dynamic locking callbacks via CRYPTO_set_dynlock_{create,lock,destroy}_callback()");
586 /* Try and get a context - if not, we may have a DSO but no
588 if(!get_context(&hwcrhk_context, &password_context))
590 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
593 /* Everything's fine. */
594 #ifndef OPENSSL_NO_RSA
595 if (hndidx_rsa == -1)
596 hndidx_rsa = RSA_get_ex_new_index(0,
597 "nFast HWCryptoHook RSA key handle",
598 NULL, NULL, hwcrhk_ex_free);
603 DSO_free(hwcrhk_dso);
605 p_hwcrhk_Init = NULL;
606 p_hwcrhk_Finish = NULL;
607 p_hwcrhk_ModExp = NULL;
608 #ifndef OPENSSL_NO_RSA
610 p_hwcrhk_RSALoadKey = NULL;
611 p_hwcrhk_RSAGetPublicKey = NULL;
612 p_hwcrhk_RSAUnloadKey = NULL;
614 p_hwcrhk_ModExpCRT = NULL;
615 p_hwcrhk_RandomBytes = NULL;
619 static int hwcrhk_finish(ENGINE *e)
622 free_HWCRHK_LIBNAME();
623 if(hwcrhk_dso == NULL)
625 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
629 release_context(hwcrhk_context);
630 if(!DSO_free(hwcrhk_dso))
632 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
640 p_hwcrhk_Init = NULL;
641 p_hwcrhk_Finish = NULL;
642 p_hwcrhk_ModExp = NULL;
643 #ifndef OPENSSL_NO_RSA
645 p_hwcrhk_RSALoadKey = NULL;
646 p_hwcrhk_RSAGetPublicKey = NULL;
647 p_hwcrhk_RSAUnloadKey = NULL;
649 p_hwcrhk_ModExpCRT = NULL;
650 p_hwcrhk_RandomBytes = NULL;
654 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
660 case HWCRHK_CMD_SO_PATH:
663 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
668 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
671 return set_HWCRHK_LIBNAME((const char *)p);
672 case ENGINE_CTRL_SET_LOGSTREAM:
676 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
682 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
685 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
687 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
689 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
690 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
691 password_context.password_callback = (pem_password_cb *)f;
692 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
694 case ENGINE_CTRL_SET_USER_INTERFACE:
695 case HWCRHK_CMD_SET_USER_INTERFACE:
696 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
697 password_context.ui_method = (UI_METHOD *)p;
698 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
700 case ENGINE_CTRL_SET_CALLBACK_DATA:
701 case HWCRHK_CMD_SET_CALLBACK_DATA:
702 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
703 password_context.callback_data = p;
704 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
706 /* this enables or disables the "SimpleForkCheck" flag used in the
707 * initialisation structure. */
708 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
709 case HWCRHK_CMD_FORK_CHECK:
710 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
712 hwcrhk_globals.flags |=
713 HWCryptoHook_InitFlags_SimpleForkCheck;
715 hwcrhk_globals.flags &=
716 ~HWCryptoHook_InitFlags_SimpleForkCheck;
717 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
719 /* This will prevent the initialisation function from "installing"
720 * the mutex-handling callbacks, even if they are available from
721 * within the library (or were provided to the library from the
722 * calling application). This is to remove any baggage for
723 * applications not using multithreading. */
724 case ENGINE_CTRL_CHIL_NO_LOCKING:
725 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
726 disable_mutex_callbacks = 1;
727 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
729 case HWCRHK_CMD_THREAD_LOCKING:
730 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
731 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
732 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
735 /* The command isn't understood by this engine */
737 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
738 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
746 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
747 UI_METHOD *ui_method, void *callback_data)
749 #ifndef OPENSSL_NO_RSA
752 EVP_PKEY *res = NULL;
753 #ifndef OPENSSL_NO_RSA
754 HWCryptoHook_MPI e, n;
755 HWCryptoHook_RSAKeyHandle *hptr;
757 #if !defined(OPENSSL_NO_RSA)
759 HWCryptoHook_ErrMsgBuf rmsg;
761 HWCryptoHook_PassphraseContext ppctx;
763 #if !defined(OPENSSL_NO_RSA)
765 rmsg.size = sizeof(tempbuf);
770 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
771 HWCRHK_R_NOT_INITIALISED);
774 #ifndef OPENSSL_NO_RSA
775 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
778 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
779 ERR_R_MALLOC_FAILURE);
782 ppctx.ui_method = ui_method;
783 ppctx.callback_data = callback_data;
784 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
787 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
788 HWCRHK_R_CHIL_ERROR);
789 ERR_add_error_data(1,rmsg.buf);
794 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
799 #ifndef OPENSSL_NO_RSA
800 rtmp = RSA_new_method(eng);
801 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
804 rtmp->flags |= RSA_FLAG_EXT_PKEY;
807 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
808 != HWCRYPTOHOOK_ERROR_MPISIZE)
810 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
811 ERR_add_error_data(1,rmsg.buf);
815 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
816 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
820 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
822 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
823 HWCRHK_R_CHIL_ERROR);
824 ERR_add_error_data(1,rmsg.buf);
827 rtmp->e->top = e.size / sizeof(BN_ULONG);
829 rtmp->n->top = n.size / sizeof(BN_ULONG);
832 res = EVP_PKEY_new();
833 EVP_PKEY_assign_RSA(res, rtmp);
837 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
838 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
844 #ifndef OPENSSL_NO_RSA
851 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
852 UI_METHOD *ui_method, void *callback_data)
854 EVP_PKEY *res = NULL;
856 #ifndef OPENSSL_NO_RSA
857 res = hwcrhk_load_privkey(eng, key_id,
858 ui_method, callback_data);
864 #ifndef OPENSSL_NO_RSA
869 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
871 res->pkey.rsa = RSA_new();
872 res->pkey.rsa->n = rsa->n;
873 res->pkey.rsa->e = rsa->e;
876 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
882 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
883 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
894 /* A little mod_exp */
895 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
896 const BIGNUM *m, BN_CTX *ctx)
899 HWCryptoHook_ErrMsgBuf rmsg;
900 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
901 we use them directly, plus a little macro magic. We only
902 thing we need to make sure of is that enough space is allocated. */
903 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
906 to_return = 0; /* expect failure */
908 rmsg.size = sizeof(tempbuf);
912 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
915 /* Prepare the params */
916 bn_expand2(r, m->top); /* Check for error !! */
922 /* Perform the operation */
923 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
925 /* Convert the response */
926 r->top = m_r.size / sizeof(BN_ULONG);
931 /* FIXME: When this error is returned, HWCryptoHook is
932 telling us that falling back to software computation
933 might be a good thing. */
934 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
936 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
940 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
942 ERR_add_error_data(1,rmsg.buf);
951 #ifndef OPENSSL_NO_RSA
952 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
955 HWCryptoHook_ErrMsgBuf rmsg;
956 HWCryptoHook_RSAKeyHandle *hptr;
957 int to_return = 0, ret;
960 rmsg.size = sizeof(tempbuf);
964 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
968 /* This provides support for nForce keys. Since that's opaque data
969 all we do is provide a handle to the proper key and let HWCryptoHook
970 take care of the rest. */
971 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
974 HWCryptoHook_MPI m_a, m_r;
978 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
979 HWCRHK_R_MISSING_KEY_COMPONENTS);
983 /* Prepare the params */
984 bn_expand2(r, rsa->n->top); /* Check for error !! */
988 /* Perform the operation */
989 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
991 /* Convert the response */
992 r->top = m_r.size / sizeof(BN_ULONG);
997 /* FIXME: When this error is returned, HWCryptoHook is
998 telling us that falling back to software computation
999 might be a good thing. */
1000 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1002 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1003 HWCRHK_R_REQUEST_FALLBACK);
1007 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1008 HWCRHK_R_REQUEST_FAILED);
1010 ERR_add_error_data(1,rmsg.buf);
1016 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1018 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1020 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1021 HWCRHK_R_MISSING_KEY_COMPONENTS);
1025 /* Prepare the params */
1026 bn_expand2(r, rsa->n->top); /* Check for error !! */
1028 BN2MPI(m_p, rsa->p);
1029 BN2MPI(m_q, rsa->q);
1030 BN2MPI(m_dmp1, rsa->dmp1);
1031 BN2MPI(m_dmq1, rsa->dmq1);
1032 BN2MPI(m_iqmp, rsa->iqmp);
1035 /* Perform the operation */
1036 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1037 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1039 /* Convert the response */
1040 r->top = m_r.size / sizeof(BN_ULONG);
1045 /* FIXME: When this error is returned, HWCryptoHook is
1046 telling us that falling back to software computation
1047 might be a good thing. */
1048 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1050 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1051 HWCRHK_R_REQUEST_FALLBACK);
1055 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1056 HWCRHK_R_REQUEST_FAILED);
1058 ERR_add_error_data(1,rmsg.buf);
1062 /* If we're here, we must be here with some semblance of success :-) */
1069 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1070 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1071 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1073 return hwcrhk_mod_exp(r, a, p, m, ctx);
1076 #ifndef OPENSSL_NO_DH
1077 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1078 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1079 const BIGNUM *a, const BIGNUM *p,
1080 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1082 return hwcrhk_mod_exp(r, a, p, m, ctx);
1086 /* Random bytes are good */
1087 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1090 HWCryptoHook_ErrMsgBuf rmsg;
1091 int to_return = 0; /* assume failure */
1095 rmsg.size = sizeof(tempbuf);
1099 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1103 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1106 /* FIXME: When this error is returned, HWCryptoHook is
1107 telling us that falling back to software computation
1108 might be a good thing. */
1109 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1111 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1112 HWCRHK_R_REQUEST_FALLBACK);
1116 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1117 HWCRHK_R_REQUEST_FAILED);
1119 ERR_add_error_data(1,rmsg.buf);
1127 static int hwcrhk_rand_status(void)
1132 /* This cleans up an RSA KM key, called when ex_data is freed */
1134 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1135 int ind,long argl, void *argp)
1138 HWCryptoHook_ErrMsgBuf rmsg;
1139 #ifndef OPENSSL_NO_RSA
1140 HWCryptoHook_RSAKeyHandle *hptr;
1142 #if !defined(OPENSSL_NO_RSA)
1147 rmsg.size = sizeof(tempbuf);
1149 #ifndef OPENSSL_NO_RSA
1150 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1153 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1159 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1160 * these just wrap the POSIX functions and add some logging.
1163 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1164 HWCryptoHook_CallerContext *cactx)
1166 mt->lockid = CRYPTO_get_new_dynlockid();
1167 if (mt->lockid == 0)
1168 return 1; /* failure */
1169 return 0; /* success */
1172 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1174 CRYPTO_w_lock(mt->lockid);
1178 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1180 CRYPTO_w_unlock(mt->lockid);
1183 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1185 CRYPTO_destroy_dynlockid(mt->lockid);
1188 static int hwcrhk_get_pass(const char *prompt_info,
1189 int *len_io, char *buf,
1190 HWCryptoHook_PassphraseContext *ppctx,
1191 HWCryptoHook_CallerContext *cactx)
1193 pem_password_cb *callback = NULL;
1194 void *callback_data = NULL;
1195 UI_METHOD *ui_method = NULL;
1199 if (cactx->ui_method)
1200 ui_method = cactx->ui_method;
1201 if (cactx->password_callback)
1202 callback = cactx->password_callback;
1203 if (cactx->callback_data)
1204 callback_data = cactx->callback_data;
1208 if (ppctx->ui_method)
1210 ui_method = ppctx->ui_method;
1213 if (ppctx->callback_data)
1214 callback_data = ppctx->callback_data;
1216 if (callback == NULL && ui_method == NULL)
1218 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1224 UI *ui = UI_new_method(ui_method);
1228 char *prompt = UI_construct_prompt(ui,
1229 "pass phrase", prompt_info);
1231 ok = UI_add_input_string(ui,prompt,
1232 UI_INPUT_FLAG_DEFAULT_PWD,
1233 buf,0,(*len_io) - 1);
1234 UI_add_user_data(ui, callback_data);
1235 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1242 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1245 *len_io = strlen(buf);
1248 OPENSSL_free(prompt);
1253 *len_io = callback(buf, *len_io, 0, callback_data);
1260 static int hwcrhk_insert_card(const char *prompt_info,
1261 const char *wrong_info,
1262 HWCryptoHook_PassphraseContext *ppctx,
1263 HWCryptoHook_CallerContext *cactx)
1267 void *callback_data = NULL;
1268 UI_METHOD *ui_method = NULL;
1272 if (cactx->ui_method)
1273 ui_method = cactx->ui_method;
1274 if (cactx->callback_data)
1275 callback_data = cactx->callback_data;
1279 if (ppctx->ui_method)
1280 ui_method = ppctx->ui_method;
1281 if (ppctx->callback_data)
1282 callback_data = ppctx->callback_data;
1284 if (ui_method == NULL)
1286 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1287 HWCRHK_R_NO_CALLBACK);
1291 ui = UI_new_method(ui_method);
1299 BIO_snprintf(buf, sizeof(buf)-1,
1300 "Current card: \"%s\"\n", wrong_info);
1301 ok = UI_dup_info_string(ui, buf);
1302 if (ok >= 0 && prompt_info)
1304 BIO_snprintf(buf, sizeof(buf)-1,
1305 "Insert card \"%s\"", prompt_info);
1306 ok = UI_dup_input_boolean(ui, buf,
1307 "\n then hit <enter> or C<enter> to cancel\n",
1308 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1310 UI_add_user_data(ui, callback_data);
1313 ok = UI_process(ui);
1316 if (ok == -2 || (ok >= 0 && answer == 'C'))
1326 static void hwcrhk_log_message(void *logstr, const char *message)
1328 BIO *lstream = NULL;
1330 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1332 lstream=*(BIO **)logstr;
1335 BIO_printf(lstream, "%s\n", message);
1337 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1340 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1341 * shared-library. */
1342 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1343 static int bind_fn(ENGINE *e, const char *id)
1345 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1351 IMPLEMENT_DYNAMIC_CHECK_FN()
1352 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1353 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1355 #endif /* !OPENSSL_NO_HW_NCIPHER */
1356 #endif /* !OPENSSL_NO_HW */