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 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>
65 #include <openssl/dso.h>
66 #include <openssl/engine.h>
67 #include <openssl/ui.h>
70 #ifndef OPENSSL_NO_HW_NCIPHER
72 /* Attribution notice: nCipher have said several times that it's OK for
73 * us to implement a general interface to their boxes, and recently declared
74 * their HWCryptoHook to be public, and therefore available for us to use.
77 * The hwcryptohook.h included here is from May 2000.
81 #include "hwcryptohook.h"
83 #include "vendor_defns/hwcryptohook.h"
86 static int hwcrhk_init(ENGINE *e);
87 static int hwcrhk_finish(ENGINE *e);
88 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
90 /* Functions to handle mutexes */
91 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
92 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
93 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
94 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
97 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
98 const BIGNUM *m, BN_CTX *ctx);
100 #ifndef OPENSSL_NO_RSA
102 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa);
104 /* This function is aliased to mod_exp (with the mont stuff dropped). */
105 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
106 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
109 /* This function is alised to mod_exp (with the DH and mont dropped). */
110 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
111 const BIGNUM *a, const BIGNUM *p,
112 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
115 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
116 static int hwcrhk_rand_status(void);
119 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
120 UI_METHOD *ui_method, void *callback_data);
121 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
122 UI_METHOD *ui_method, void *callback_data);
123 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
124 int ind,long argl, void *argp);
126 /* Interaction stuff */
127 static int hwcrhk_insert_card(const char *prompt_info,
128 const char *wrong_info,
129 HWCryptoHook_PassphraseContext *ppctx,
130 HWCryptoHook_CallerContext *cactx);
131 static int hwcrhk_get_pass(const char *prompt_info,
132 int *len_io, char *buf,
133 HWCryptoHook_PassphraseContext *ppctx,
134 HWCryptoHook_CallerContext *cactx);
135 static void hwcrhk_log_message(void *logstr, const char *message);
137 /* The definitions for control commands specific to this engine */
138 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
139 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
140 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
141 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
142 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
143 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
146 "Specifies the path to the 'hwcrhk' shared library",
147 ENGINE_CMD_FLAG_STRING},
148 {HWCRHK_CMD_FORK_CHECK,
150 "Turns fork() checking on or off (boolean)",
151 ENGINE_CMD_FLAG_NUMERIC},
152 {HWCRHK_CMD_THREAD_LOCKING,
154 "Turns thread-safe locking on or off (boolean)",
155 ENGINE_CMD_FLAG_NUMERIC},
156 {HWCRHK_CMD_SET_USER_INTERFACE,
157 "SET_USER_INTERFACE",
158 "Set the global user interface (internal)",
159 ENGINE_CMD_FLAG_INTERNAL},
160 {HWCRHK_CMD_SET_CALLBACK_DATA,
162 "Set the global user interface extra data (internal)",
163 ENGINE_CMD_FLAG_INTERNAL},
167 #ifndef OPENSSL_NO_RSA
168 /* Our internal RSA_METHOD that we provide pointers to */
169 static RSA_METHOD hwcrhk_rsa =
171 "nCipher RSA method",
187 #ifndef OPENSSL_NO_DH
188 /* Our internal DH_METHOD that we provide pointers to */
189 static DH_METHOD hwcrhk_dh =
202 static RAND_METHOD hwcrhk_rand =
204 /* "nCipher RAND method", */
213 /* Constants used when creating the ENGINE */
214 static const char *engine_hwcrhk_id = "chil";
215 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
217 /* Internal stuff for HWCryptoHook */
219 /* Some structures needed for proper use of thread locks */
220 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
221 into HWCryptoHook_Mutex */
222 struct HWCryptoHook_MutexValue
227 /* hwcryptohook.h has some typedefs that turn
228 struct HWCryptoHook_PassphraseContextValue
229 into HWCryptoHook_PassphraseContext */
230 struct HWCryptoHook_PassphraseContextValue
232 UI_METHOD *ui_method;
236 /* hwcryptohook.h has some typedefs that turn
237 struct HWCryptoHook_CallerContextValue
238 into HWCryptoHook_CallerContext */
239 struct HWCryptoHook_CallerContextValue
241 pem_password_cb *password_callback; /* Deprecated! Only present for
242 backward compatibility! */
243 UI_METHOD *ui_method;
247 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
248 BIGNUM's, so lets define a couple of conversion macros */
249 #define BN2MPI(mp, bn) \
250 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
251 #define MPI2BN(bn, mp) \
252 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
254 static BIO *logstream = NULL;
255 static int disable_mutex_callbacks = 0;
257 /* One might wonder why these are needed, since one can pass down at least
258 a UI_METHOD and a pointer to callback data to the key-loading functions.
259 The thing is that the ModExp and RSAImmed functions can load keys as well,
260 if the data they get is in a special, nCipher-defined format (hint: if you
261 look at the private exponent of the RSA data as a string, you'll see this
262 string: "nCipher KM tool key id", followed by some bytes, followed a key
263 identity string, followed by more bytes. This happens when you use "embed"
264 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
265 any passphrase or caller context, and our functions can't really take any
266 callback data either. Still, the "insert_card" and "get_passphrase"
267 callbacks may be called down the line, and will need to know what user
268 interface callbacks to call, and having callback data from the application
269 may be a nice thing as well, so we need to keep track of that globally. */
270 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
272 /* Stuff to pass to the HWCryptoHook library */
273 static HWCryptoHook_InitInfo hwcrhk_globals = {
275 &logstream, /* logstream */
276 sizeof(BN_ULONG), /* limbsize */
277 0, /* mslimb first: false for BNs */
278 -1, /* msbyte first: use native */
279 0, /* Max mutexes, 0 = no small limit */
280 0, /* Max simultaneous, 0 = default */
282 /* The next few are mutex stuff: we write wrapper functions
283 around the OS mutex functions. We initialise them to 0
284 here, and change that to actual function pointers in hwcrhk_init()
285 if dynamic locks are supported (that is, if the application
286 programmer has made sure of setting up callbacks bafore starting
287 this engine) *and* if disable_mutex_callbacks hasn't been set by
288 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
289 sizeof(HWCryptoHook_Mutex),
295 /* The next few are condvar stuff: we write wrapper functions
296 round the OS functions. Currently not implemented and not
297 and absolute necessity even in threaded programs, therefore
298 0'ed. Will hopefully be implemented some day, since it
299 enhances the efficiency of HWCryptoHook. */
300 0, /* sizeof(HWCryptoHook_CondVar), */
301 0, /* hwcrhk_cv_init, */
302 0, /* hwcrhk_cv_wait, */
303 0, /* hwcrhk_cv_signal, */
304 0, /* hwcrhk_cv_broadcast, */
305 0, /* hwcrhk_cv_destroy, */
307 hwcrhk_get_pass, /* pass phrase */
308 hwcrhk_insert_card, /* insert a card */
309 hwcrhk_log_message /* Log message */
313 /* Now, to our own code */
315 /* As this is only ever called once, there's no need for locking
316 * (indeed - the lock will already be held by our caller!!!) */
317 ENGINE *ENGINE_ncipher()
319 #ifndef OPENSSL_NO_RSA
320 const RSA_METHOD *meth1;
322 #ifndef OPENSSL_NO_DH
323 const DH_METHOD *meth2;
325 ENGINE *ret = ENGINE_new();
328 if(!ENGINE_set_id(ret, engine_hwcrhk_id) ||
329 !ENGINE_set_name(ret, engine_hwcrhk_name) ||
330 #ifndef OPENSSL_NO_RSA
331 !ENGINE_set_RSA(ret, &hwcrhk_rsa) ||
333 #ifndef OPENSSL_NO_DH
334 !ENGINE_set_DH(ret, &hwcrhk_dh) ||
336 !ENGINE_set_RAND(ret, &hwcrhk_rand) ||
337 !ENGINE_set_BN_mod_exp(ret, hwcrhk_mod_exp) ||
338 !ENGINE_set_init_function(ret, hwcrhk_init) ||
339 !ENGINE_set_finish_function(ret, hwcrhk_finish) ||
340 !ENGINE_set_ctrl_function(ret, hwcrhk_ctrl) ||
341 !ENGINE_set_load_privkey_function(ret, hwcrhk_load_privkey) ||
342 !ENGINE_set_load_pubkey_function(ret, hwcrhk_load_pubkey) ||
343 !ENGINE_set_cmd_defns(ret, hwcrhk_cmd_defns))
349 #ifndef OPENSSL_NO_RSA
350 /* We know that the "PKCS1_SSLeay()" functions hook properly
351 * to the cswift-specific mod_exp and mod_exp_crt so we use
352 * those functions. NB: We don't use ENGINE_openssl() or
353 * anything "more generic" because something like the RSAref
354 * code may not hook properly, and if you own one of these
355 * cards then you have the right to do RSA operations on it
357 meth1 = RSA_PKCS1_SSLeay();
358 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
359 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
360 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
361 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
364 #ifndef OPENSSL_NO_DH
365 /* Much the same for Diffie-Hellman */
366 meth2 = DH_OpenSSL();
367 hwcrhk_dh.generate_key = meth2->generate_key;
368 hwcrhk_dh.compute_key = meth2->compute_key;
373 /* This is a process-global DSO handle used for loading and unloading
374 * the HWCryptoHook library. NB: This is only set (or unset) during an
375 * init() or finish() call (reference counts permitting) and they're
376 * operating with global locks, so this should be thread-safe
378 static DSO *hwcrhk_dso = NULL;
379 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
380 #ifndef OPENSSL_NO_RSA
381 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
384 /* These are the function pointers that are (un)set when the library has
385 * successfully (un)loaded. */
386 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
387 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
388 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
389 #ifndef OPENSSL_NO_RSA
390 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
392 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
393 #ifndef OPENSSL_NO_RSA
394 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
395 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
396 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
398 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
400 /* Used in the DSO operations. */
401 static const char def_HWCRHK_LIBNAME[] = "nfhwcrhk";
402 static const char *HWCRHK_LIBNAME = def_HWCRHK_LIBNAME;
403 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
404 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
405 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
406 #ifndef OPENSSL_NO_RSA
407 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
409 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
410 #ifndef OPENSSL_NO_RSA
411 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
412 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
413 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
415 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
417 /* HWCryptoHook library functions and mechanics - these are used by the
418 * higher-level functions further down. NB: As and where there's no
419 * error checking, take a look lower down where these functions are
420 * called, the checking and error handling is probably down there. */
422 /* utility function to obtain a context */
423 static int get_context(HWCryptoHook_ContextHandle *hac,
424 HWCryptoHook_CallerContext *cac)
427 HWCryptoHook_ErrMsgBuf rmsg;
432 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
439 /* similarly to release one. */
440 static void release_context(HWCryptoHook_ContextHandle hac)
442 p_hwcrhk_Finish(hac);
445 /* (de)initialisation functions. */
446 static int hwcrhk_init(ENGINE *e)
448 HWCryptoHook_Init_t *p1;
449 HWCryptoHook_Finish_t *p2;
450 HWCryptoHook_ModExp_t *p3;
451 #ifndef OPENSSL_NO_RSA
452 HWCryptoHook_RSA_t *p4;
453 HWCryptoHook_RSALoadKey_t *p5;
454 HWCryptoHook_RSAGetPublicKey_t *p6;
455 HWCryptoHook_RSAUnloadKey_t *p7;
457 HWCryptoHook_RandomBytes_t *p8;
458 HWCryptoHook_ModExpCRT_t *p9;
460 if(hwcrhk_dso != NULL)
462 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_ALREADY_LOADED);
465 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
466 hwcrhk_dso = DSO_load(NULL, HWCRHK_LIBNAME, NULL, 0);
467 if(hwcrhk_dso == NULL)
469 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
472 if(!(p1 = (HWCryptoHook_Init_t *)
473 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
474 !(p2 = (HWCryptoHook_Finish_t *)
475 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
476 !(p3 = (HWCryptoHook_ModExp_t *)
477 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
478 #ifndef OPENSSL_NO_RSA
479 !(p4 = (HWCryptoHook_RSA_t *)
480 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
481 !(p5 = (HWCryptoHook_RSALoadKey_t *)
482 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
483 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
484 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
485 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
486 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
488 !(p8 = (HWCryptoHook_RandomBytes_t *)
489 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
490 !(p9 = (HWCryptoHook_ModExpCRT_t *)
491 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
493 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
496 /* Copy the pointers */
498 p_hwcrhk_Finish = p2;
499 p_hwcrhk_ModExp = p3;
500 #ifndef OPENSSL_NO_RSA
502 p_hwcrhk_RSALoadKey = p5;
503 p_hwcrhk_RSAGetPublicKey = p6;
504 p_hwcrhk_RSAUnloadKey = p7;
506 p_hwcrhk_RandomBytes = p8;
507 p_hwcrhk_ModExpCRT = p9;
509 /* Check if the application decided to support dynamic locks,
510 and if it does, use them. */
511 if (disable_mutex_callbacks == 0 &&
512 CRYPTO_get_dynlock_create_callback() != NULL &&
513 CRYPTO_get_dynlock_lock_callback() != NULL &&
514 CRYPTO_get_dynlock_destroy_callback() != NULL)
516 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
517 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
518 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
519 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
522 /* Try and get a context - if not, we may have a DSO but no
524 if(!get_context(&hwcrhk_context, &password_context))
526 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_UNIT_FAILURE);
529 /* Everything's fine. */
530 #ifndef OPENSSL_NO_RSA
531 if (hndidx_rsa == -1)
532 hndidx_rsa = RSA_get_ex_new_index(0,
533 "nFast HWCryptoHook RSA key handle",
534 NULL, NULL, hwcrhk_ex_free);
539 DSO_free(hwcrhk_dso);
541 p_hwcrhk_Init = NULL;
542 p_hwcrhk_Finish = NULL;
543 p_hwcrhk_ModExp = NULL;
544 #ifndef OPENSSL_NO_RSA
546 p_hwcrhk_RSALoadKey = NULL;
547 p_hwcrhk_RSAGetPublicKey = NULL;
548 p_hwcrhk_RSAUnloadKey = NULL;
550 p_hwcrhk_ModExpCRT = NULL;
551 p_hwcrhk_RandomBytes = NULL;
555 static int hwcrhk_finish(ENGINE *e)
558 if(hwcrhk_dso == NULL)
560 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_NOT_LOADED);
564 release_context(hwcrhk_context);
565 if(!DSO_free(hwcrhk_dso))
567 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_DSO_FAILURE);
575 p_hwcrhk_Init = NULL;
576 p_hwcrhk_Finish = NULL;
577 p_hwcrhk_ModExp = NULL;
578 #ifndef OPENSSL_NO_RSA
580 p_hwcrhk_RSALoadKey = NULL;
581 p_hwcrhk_RSAGetPublicKey = NULL;
582 p_hwcrhk_RSAUnloadKey = NULL;
584 p_hwcrhk_ModExpCRT = NULL;
585 p_hwcrhk_RandomBytes = NULL;
589 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
595 case HWCRHK_CMD_SO_PATH:
598 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_ALREADY_LOADED);
603 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
606 HWCRHK_LIBNAME = (const char *)p;
608 case ENGINE_CTRL_SET_LOGSTREAM:
612 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
618 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
621 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_BIO_WAS_FREED);
623 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
625 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
626 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
627 password_context.password_callback = (pem_password_cb *)f;
628 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
630 case ENGINE_CTRL_SET_USER_INTERFACE:
631 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
632 password_context.ui_method = (UI_METHOD *)p;
633 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
635 case ENGINE_CTRL_SET_CALLBACK_DATA:
636 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
637 password_context.callback_data = p;
638 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
640 /* this enables or disables the "SimpleForkCheck" flag used in the
641 * initialisation structure. */
642 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
643 case HWCRHK_CMD_FORK_CHECK:
644 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
646 hwcrhk_globals.flags |=
647 HWCryptoHook_InitFlags_SimpleForkCheck;
649 hwcrhk_globals.flags &=
650 ~HWCryptoHook_InitFlags_SimpleForkCheck;
651 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
653 /* This will prevent the initialisation function from "installing"
654 * the mutex-handling callbacks, even if they are available from
655 * within the library (or were provided to the library from the
656 * calling application). This is to remove any baggage for
657 * applications not using multithreading. */
658 case ENGINE_CTRL_CHIL_NO_LOCKING:
659 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
660 disable_mutex_callbacks = 1;
661 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
663 case HWCRHK_CMD_THREAD_LOCKING:
664 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
665 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
666 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
669 /* The command isn't understood by this engine */
671 ENGINEerr(ENGINE_F_HWCRHK_CTRL,
672 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
680 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
681 UI_METHOD *ui_method, void *callback_data)
683 #ifndef OPENSSL_NO_RSA
686 EVP_PKEY *res = NULL;
687 #ifndef OPENSSL_NO_RSA
688 HWCryptoHook_MPI e, n;
689 HWCryptoHook_RSAKeyHandle *hptr;
691 #if !defined(OPENSSL_NO_RSA)
692 HWCryptoHook_ErrMsgBuf rmsg;
694 HWCryptoHook_PassphraseContext ppctx;
698 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
699 ENGINE_R_NOT_INITIALISED);
702 #ifndef OPENSSL_NO_RSA
703 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
706 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
707 ERR_R_MALLOC_FAILURE);
710 ppctx.ui_method = ui_method;
711 ppctx.callback_data = callback_data;
712 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
715 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
716 ENGINE_R_CHIL_ERROR);
717 ERR_add_error_data(1,rmsg.buf);
722 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
727 #ifndef OPENSSL_NO_RSA
728 rtmp = RSA_new_method(eng);
729 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
732 rtmp->flags |= RSA_FLAG_EXT_PKEY;
735 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
736 != HWCRYPTOHOOK_ERROR_MPISIZE)
738 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,ENGINE_R_CHIL_ERROR);
739 ERR_add_error_data(1,rmsg.buf);
743 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
744 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
748 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
750 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
751 ENGINE_R_CHIL_ERROR);
752 ERR_add_error_data(1,rmsg.buf);
755 rtmp->e->top = e.size / sizeof(BN_ULONG);
757 rtmp->n->top = n.size / sizeof(BN_ULONG);
760 res = EVP_PKEY_new();
761 EVP_PKEY_assign_RSA(res, rtmp);
765 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
766 ENGINE_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
772 #ifndef OPENSSL_NO_RSA
779 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
780 UI_METHOD *ui_method, void *callback_data)
782 EVP_PKEY *res = NULL;
784 #ifndef OPENSSL_NO_RSA
785 res = hwcrhk_load_privkey(eng, key_id,
786 ui_method, callback_data);
792 #ifndef OPENSSL_NO_RSA
797 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
799 res->pkey.rsa = RSA_new();
800 res->pkey.rsa->n = rsa->n;
801 res->pkey.rsa->e = rsa->e;
802 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
807 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
808 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
819 /* A little mod_exp */
820 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
821 const BIGNUM *m, BN_CTX *ctx)
824 HWCryptoHook_ErrMsgBuf rmsg;
825 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
826 we use them directly, plus a little macro magic. We only
827 thing we need to make sure of is that enough space is allocated. */
828 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
831 to_return = 0; /* expect failure */
837 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
840 /* Prepare the params */
841 bn_expand2(r, m->top); /* Check for error !! */
847 /* Perform the operation */
848 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
850 /* Convert the response */
851 r->top = m_r.size / sizeof(BN_ULONG);
856 /* FIXME: When this error is returned, HWCryptoHook is
857 telling us that falling back to software computation
858 might be a good thing. */
859 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
861 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
865 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FAILED);
867 ERR_add_error_data(1,rmsg.buf);
876 #ifndef OPENSSL_NO_RSA
877 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
880 HWCryptoHook_ErrMsgBuf rmsg;
881 HWCryptoHook_RSAKeyHandle *hptr;
882 int to_return = 0, ret;
886 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
890 /* This provides support for nForce keys. Since that's opaque data
891 all we do is provide a handle to the proper key and let HWCryptoHook
892 take care of the rest. */
893 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
896 HWCryptoHook_MPI m_a, m_r;
900 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
901 ENGINE_R_MISSING_KEY_COMPONENTS);
908 /* Prepare the params */
909 bn_expand2(r, rsa->n->top); /* Check for error !! */
913 /* Perform the operation */
914 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
916 /* Convert the response */
917 r->top = m_r.size / sizeof(BN_ULONG);
922 /* FIXME: When this error is returned, HWCryptoHook is
923 telling us that falling back to software computation
924 might be a good thing. */
925 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
927 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
931 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
933 ERR_add_error_data(1,rmsg.buf);
939 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
941 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
943 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
944 ENGINE_R_MISSING_KEY_COMPONENTS);
951 /* Prepare the params */
952 bn_expand2(r, rsa->n->top); /* Check for error !! */
956 BN2MPI(m_dmp1, rsa->dmp1);
957 BN2MPI(m_dmq1, rsa->dmq1);
958 BN2MPI(m_iqmp, rsa->iqmp);
961 /* Perform the operation */
962 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
963 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
965 /* Convert the response */
966 r->top = m_r.size / sizeof(BN_ULONG);
971 /* FIXME: When this error is returned, HWCryptoHook is
972 telling us that falling back to software computation
973 might be a good thing. */
974 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
976 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
980 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
982 ERR_add_error_data(1,rmsg.buf);
986 /* If we're here, we must be here with some semblance of success :-) */
993 /* This function is aliased to mod_exp (with the mont stuff dropped). */
994 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
995 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
997 return hwcrhk_mod_exp(r, a, p, m, ctx);
1000 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1001 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1002 const BIGNUM *a, const BIGNUM *p,
1003 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1005 return hwcrhk_mod_exp(r, a, p, m, ctx);
1008 /* Random bytes are good */
1009 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1012 HWCryptoHook_ErrMsgBuf rmsg;
1013 int to_return = 0; /* assume failure */
1021 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_NOT_INITIALISED);
1025 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1028 /* FIXME: When this error is returned, HWCryptoHook is
1029 telling us that falling back to software computation
1030 might be a good thing. */
1031 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1033 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FALLBACK);
1037 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FAILED);
1039 ERR_add_error_data(1,rmsg.buf);
1047 static int hwcrhk_rand_status(void)
1052 /* This cleans up an RSA KM key, called when ex_data is freed */
1054 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1055 int ind,long argl, void *argp)
1058 HWCryptoHook_ErrMsgBuf rmsg;
1059 #ifndef OPENSSL_NO_RSA
1060 HWCryptoHook_RSAKeyHandle *hptr;
1062 #if !defined(OPENSSL_NO_RSA)
1069 #ifndef OPENSSL_NO_RSA
1070 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1073 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1079 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1080 * these just wrap the POSIX functions and add some logging.
1083 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1084 HWCryptoHook_CallerContext *cactx)
1086 mt->lockid = CRYPTO_get_new_dynlockid();
1087 if (mt->lockid == 0)
1092 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1094 CRYPTO_w_lock(mt->lockid);
1098 void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1100 CRYPTO_w_unlock(mt->lockid);
1103 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1105 CRYPTO_destroy_dynlockid(mt->lockid);
1108 static int hwcrhk_get_pass(const char *prompt_info,
1109 int *len_io, char *buf,
1110 HWCryptoHook_PassphraseContext *ppctx,
1111 HWCryptoHook_CallerContext *cactx)
1113 pem_password_cb *callback = NULL;
1114 void *callback_data = NULL;
1115 UI_METHOD *ui_method = NULL;
1119 if (cactx->ui_method)
1120 ui_method = cactx->ui_method;
1121 if (cactx->password_callback)
1122 callback = cactx->password_callback;
1123 if (cactx->callback_data)
1124 callback_data = cactx->callback_data;
1128 if (ppctx->ui_method)
1130 ui_method = ppctx->ui_method;
1133 if (ppctx->callback_data)
1134 callback_data = ppctx->callback_data;
1136 if (callback == NULL && ui_method == NULL)
1138 ENGINEerr(ENGINE_F_HWCRHK_GET_PASS,ENGINE_R_NO_CALLBACK);
1144 UI *ui = UI_new_method(ui_method);
1148 char *prompt = UI_construct_prompt(ui,
1149 "pass phrase", prompt_info);
1151 ok = UI_add_input_string(ui,prompt,
1152 UI_INPUT_FLAG_DEFAULT_PWD,
1153 buf,0,(*len_io) - 1);
1154 UI_add_user_data(ui, callback_data);
1155 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1162 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1165 *len_io = strlen(buf);
1168 OPENSSL_free(prompt);
1173 *len_io = callback(buf, *len_io, 0, callback_data);
1180 static int hwcrhk_insert_card(const char *prompt_info,
1181 const char *wrong_info,
1182 HWCryptoHook_PassphraseContext *ppctx,
1183 HWCryptoHook_CallerContext *cactx)
1187 void *callback_data = NULL;
1188 UI_METHOD *ui_method = NULL;
1192 if (cactx->ui_method)
1193 ui_method = cactx->ui_method;
1194 if (cactx->callback_data)
1195 callback_data = cactx->callback_data;
1199 if (ppctx->ui_method)
1200 ui_method = ppctx->ui_method;
1201 if (ppctx->callback_data)
1202 callback_data = ppctx->callback_data;
1204 if (ui_method == NULL)
1206 ENGINEerr(ENGINE_F_HWCRHK_INSERT_CARD,ENGINE_R_NO_CALLBACK);
1210 ui = UI_new_method(ui_method);
1218 BIO_snprintf(buf, sizeof(buf)-1,
1219 "Current card: \"%s\"\n", wrong_info);
1220 ok = UI_dup_info_string(ui, buf);
1221 if (ok >= 0 && prompt_info)
1223 BIO_snprintf(buf, sizeof(buf)-1,
1224 "Insert card \"%s\"", prompt_info);
1225 ok = UI_dup_input_boolean(ui, buf,
1226 "\n then hit <enter> or C<enter> to cancel\n",
1227 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1229 UI_add_user_data(ui, callback_data);
1232 ok = UI_process(ui);
1235 if (ok == -2 || (ok >= 0 && answer == 'C'))
1245 static void hwcrhk_log_message(void *logstr, const char *message)
1247 BIO *lstream = NULL;
1249 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1251 lstream=*(BIO **)logstr;
1254 BIO_write(lstream, message, strlen(message));
1256 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1259 #endif /* !OPENSSL_NO_HW_NCIPHER */
1260 #endif /* !OPENSSL_NO_HW */