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).
61 #include <openssl/crypto.h>
62 #include <openssl/pem.h>
64 #include <openssl/dso.h>
65 #include <openssl/engine.h>
68 #ifndef OPENSSL_NO_HW_NCIPHER
70 /* Attribution notice: nCipher have said several times that it's OK for
71 * us to implement a general interface to their boxes, and recently declared
72 * their HWCryptoHook to be public, and therefore available for us to use.
75 * The hwcryptohook.h included here is from May 2000.
79 #include "hwcryptohook.h"
81 #include "vendor_defns/hwcryptohook.h"
84 static int hwcrhk_init(ENGINE *e);
85 static int hwcrhk_finish(ENGINE *e);
86 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
88 /* Functions to handle mutexes */
89 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
90 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
91 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
92 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
95 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
96 const BIGNUM *m, BN_CTX *ctx);
98 #ifndef OPENSSL_NO_RSA
100 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa);
102 /* This function is aliased to mod_exp (with the mont stuff dropped). */
103 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
104 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
107 /* This function is alised to mod_exp (with the DH and mont dropped). */
108 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
109 const BIGNUM *a, const BIGNUM *p,
110 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
113 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
114 static int hwcrhk_rand_status(void);
117 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
118 const char *passphrase);
119 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
120 const char *passphrase);
121 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
122 int ind,long argl, void *argp);
124 /* Interaction stuff */
125 static int hwcrhk_get_pass(const char *prompt_info,
126 int *len_io, char *buf,
127 HWCryptoHook_PassphraseContext *ppctx,
128 HWCryptoHook_CallerContext *cactx);
129 static void hwcrhk_log_message(void *logstr, const char *message);
131 /* The definitions for control commands specific to this engine */
132 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
133 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
134 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
135 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
138 "Specifies the path to the 'hwcrhk' shared library",
139 ENGINE_CMD_FLAG_STRING},
140 {HWCRHK_CMD_FORK_CHECK,
142 "Turns fork() checking on or off (boolean)",
143 ENGINE_CMD_FLAG_NUMERIC},
144 {HWCRHK_CMD_THREAD_LOCKING,
146 "Turns thread-safe locking on or off (boolean)",
147 ENGINE_CMD_FLAG_NUMERIC},
151 #ifndef OPENSSL_NO_RSA
152 /* Our internal RSA_METHOD that we provide pointers to */
153 static RSA_METHOD hwcrhk_rsa =
155 "nCipher RSA method",
171 #ifndef OPENSSL_NO_DH
172 /* Our internal DH_METHOD that we provide pointers to */
173 static DH_METHOD hwcrhk_dh =
186 static RAND_METHOD hwcrhk_rand =
188 /* "nCipher RAND method", */
197 /* Constants used when creating the ENGINE */
198 static const char *engine_hwcrhk_id = "chil";
199 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
201 /* Internal stuff for HWCryptoHook */
203 /* Some structures needed for proper use of thread locks */
204 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
205 into HWCryptoHook_Mutex */
206 struct HWCryptoHook_MutexValue
211 /* hwcryptohook.h has some typedefs that turn
212 struct HWCryptoHook_PassphraseContextValue
213 into HWCryptoHook_PassphraseContext */
214 struct HWCryptoHook_PassphraseContextValue
219 /* hwcryptohook.h has some typedefs that turn
220 struct HWCryptoHook_CallerContextValue
221 into HWCryptoHook_CallerContext */
222 struct HWCryptoHook_CallerContextValue
227 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
228 BIGNUM's, so lets define a couple of conversion macros */
229 #define BN2MPI(mp, bn) \
230 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
231 #define MPI2BN(bn, mp) \
232 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
234 #if 0 /* Card and password management is not yet supported */
235 /* HWCryptoHook callbacks. insert_card() and get_pass() are not yet
236 defined, because we haven't quite decided on the proper form yet.
237 log_message() just adds an entry in the error stack. I don't know
238 if that's good or bad... */
239 static int insert_card(const char *prompt_info,
240 const char *wrong_info,
241 HWCryptoHook_PassphraseContext *ppctx,
242 HWCryptoHook_CallerContext *cactx);
243 static int get_pass(const char *prompt_info,
244 int *len_io, char *buf,
245 HWCryptoHook_PassphraseContext *ppctx,
246 HWCryptoHook_CallerContext *cactx);
249 static BIO *logstream = NULL;
250 static pem_password_cb *password_callback = NULL;
252 static void *password_callback_userdata = NULL;
254 static int disable_mutex_callbacks = 0;
256 /* Stuff to pass to the HWCryptoHook library */
257 static HWCryptoHook_InitInfo hwcrhk_globals = {
259 &logstream, /* logstream */
260 sizeof(BN_ULONG), /* limbsize */
261 0, /* mslimb first: false for BNs */
262 -1, /* msbyte first: use native */
263 0, /* Max mutexes, 0 = no small limit */
264 0, /* Max simultaneous, 0 = default */
266 /* The next few are mutex stuff: we write wrapper functions
267 around the OS mutex functions. We initialise them to 0
268 here, and change that to actual function pointers in hwcrhk_init()
269 if dynamic locks are supported (that is, if the application
270 programmer has made sure of setting up callbacks bafore starting
271 this engine) *and* if disable_mutex_callbacks hasn't been set by
272 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
273 sizeof(HWCryptoHook_Mutex),
279 /* The next few are condvar stuff: we write wrapper functions
280 round the OS functions. Currently not implemented and not
281 and absolute necessity even in threaded programs, therefore
282 0'ed. Will hopefully be implemented some day, since it
283 enhances the efficiency of HWCryptoHook. */
284 0, /* sizeof(HWCryptoHook_CondVar), */
285 0, /* hwcrhk_cv_init, */
286 0, /* hwcrhk_cv_wait, */
287 0, /* hwcrhk_cv_signal, */
288 0, /* hwcrhk_cv_broadcast, */
289 0, /* hwcrhk_cv_destroy, */
291 hwcrhk_get_pass, /* pass phrase */
292 0, /* insert_card, */ /* insert a card */
293 hwcrhk_log_message /* Log message */
297 /* Now, to our own code */
299 /* As this is only ever called once, there's no need for locking
300 * (indeed - the lock will already be held by our caller!!!) */
301 ENGINE *ENGINE_ncipher()
303 #ifndef OPENSSL_NO_RSA
304 const RSA_METHOD *meth1;
306 #ifndef OPENSSL_NO_DH
307 const DH_METHOD *meth2;
309 ENGINE *ret = ENGINE_new();
312 if(!ENGINE_set_id(ret, engine_hwcrhk_id) ||
313 !ENGINE_set_name(ret, engine_hwcrhk_name) ||
314 #ifndef OPENSSL_NO_RSA
315 !ENGINE_set_RSA(ret, &hwcrhk_rsa) ||
317 #ifndef OPENSSL_NO_DH
318 !ENGINE_set_DH(ret, &hwcrhk_dh) ||
320 !ENGINE_set_RAND(ret, &hwcrhk_rand) ||
321 !ENGINE_set_BN_mod_exp(ret, hwcrhk_mod_exp) ||
322 !ENGINE_set_init_function(ret, hwcrhk_init) ||
323 !ENGINE_set_finish_function(ret, hwcrhk_finish) ||
324 !ENGINE_set_ctrl_function(ret, hwcrhk_ctrl) ||
325 !ENGINE_set_load_privkey_function(ret, hwcrhk_load_privkey) ||
326 !ENGINE_set_load_pubkey_function(ret, hwcrhk_load_pubkey) ||
327 !ENGINE_set_cmd_defns(ret, hwcrhk_cmd_defns))
333 #ifndef OPENSSL_NO_RSA
334 /* We know that the "PKCS1_SSLeay()" functions hook properly
335 * to the cswift-specific mod_exp and mod_exp_crt so we use
336 * those functions. NB: We don't use ENGINE_openssl() or
337 * anything "more generic" because something like the RSAref
338 * code may not hook properly, and if you own one of these
339 * cards then you have the right to do RSA operations on it
341 meth1 = RSA_PKCS1_SSLeay();
342 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
343 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
344 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
345 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
348 #ifndef OPENSSL_NO_DH
349 /* Much the same for Diffie-Hellman */
350 meth2 = DH_OpenSSL();
351 hwcrhk_dh.generate_key = meth2->generate_key;
352 hwcrhk_dh.compute_key = meth2->compute_key;
357 /* This is a process-global DSO handle used for loading and unloading
358 * the HWCryptoHook library. NB: This is only set (or unset) during an
359 * init() or finish() call (reference counts permitting) and they're
360 * operating with global locks, so this should be thread-safe
362 static DSO *hwcrhk_dso = NULL;
363 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
364 #ifndef OPENSSL_NO_RSA
365 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
368 /* These are the function pointers that are (un)set when the library has
369 * successfully (un)loaded. */
370 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
371 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
372 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
373 #ifndef OPENSSL_NO_RSA
374 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
376 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
377 #ifndef OPENSSL_NO_RSA
378 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
379 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
380 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
382 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
384 /* Used in the DSO operations. */
385 static const char def_HWCRHK_LIBNAME[] = "nfhwcrhk";
386 static const char *HWCRHK_LIBNAME = def_HWCRHK_LIBNAME;
387 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
388 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
389 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
390 #ifndef OPENSSL_NO_RSA
391 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
393 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
394 #ifndef OPENSSL_NO_RSA
395 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
396 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
397 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
399 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
401 /* HWCryptoHook library functions and mechanics - these are used by the
402 * higher-level functions further down. NB: As and where there's no
403 * error checking, take a look lower down where these functions are
404 * called, the checking and error handling is probably down there. */
406 /* utility function to obtain a context */
407 static int get_context(HWCryptoHook_ContextHandle *hac)
410 HWCryptoHook_ErrMsgBuf rmsg;
415 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
422 /* similarly to release one. */
423 static void release_context(HWCryptoHook_ContextHandle hac)
425 p_hwcrhk_Finish(hac);
428 /* (de)initialisation functions. */
429 static int hwcrhk_init(ENGINE *e)
431 HWCryptoHook_Init_t *p1;
432 HWCryptoHook_Finish_t *p2;
433 HWCryptoHook_ModExp_t *p3;
434 #ifndef OPENSSL_NO_RSA
435 HWCryptoHook_RSA_t *p4;
436 HWCryptoHook_RSALoadKey_t *p5;
437 HWCryptoHook_RSAGetPublicKey_t *p6;
438 HWCryptoHook_RSAUnloadKey_t *p7;
440 HWCryptoHook_RandomBytes_t *p8;
441 HWCryptoHook_ModExpCRT_t *p9;
443 if(hwcrhk_dso != NULL)
445 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_ALREADY_LOADED);
448 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
449 hwcrhk_dso = DSO_load(NULL, HWCRHK_LIBNAME, NULL, 0);
450 if(hwcrhk_dso == NULL)
452 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
455 if(!(p1 = (HWCryptoHook_Init_t *)
456 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
457 !(p2 = (HWCryptoHook_Finish_t *)
458 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
459 !(p3 = (HWCryptoHook_ModExp_t *)
460 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
461 #ifndef OPENSSL_NO_RSA
462 !(p4 = (HWCryptoHook_RSA_t *)
463 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
464 !(p5 = (HWCryptoHook_RSALoadKey_t *)
465 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
466 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
467 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
468 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
469 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
471 !(p8 = (HWCryptoHook_RandomBytes_t *)
472 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
473 !(p9 = (HWCryptoHook_ModExpCRT_t *)
474 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
476 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
479 /* Copy the pointers */
481 p_hwcrhk_Finish = p2;
482 p_hwcrhk_ModExp = p3;
483 #ifndef OPENSSL_NO_RSA
485 p_hwcrhk_RSALoadKey = p5;
486 p_hwcrhk_RSAGetPublicKey = p6;
487 p_hwcrhk_RSAUnloadKey = p7;
489 p_hwcrhk_RandomBytes = p8;
490 p_hwcrhk_ModExpCRT = p9;
492 /* Check if the application decided to support dynamic locks,
493 and if it does, use them. */
494 if (disable_mutex_callbacks == 0 &&
495 CRYPTO_get_dynlock_create_callback() != NULL &&
496 CRYPTO_get_dynlock_lock_callback() != NULL &&
497 CRYPTO_get_dynlock_destroy_callback() != NULL)
499 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
500 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
501 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
502 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
505 /* Try and get a context - if not, we may have a DSO but no
507 if(!get_context(&hwcrhk_context))
509 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_UNIT_FAILURE);
512 /* Everything's fine. */
513 #ifndef OPENSSL_NO_RSA
514 if (hndidx_rsa == -1)
515 hndidx_rsa = RSA_get_ex_new_index(0,
516 "nFast HWCryptoHook RSA key handle",
517 NULL, NULL, hwcrhk_ex_free);
522 DSO_free(hwcrhk_dso);
524 p_hwcrhk_Init = NULL;
525 p_hwcrhk_Finish = NULL;
526 p_hwcrhk_ModExp = NULL;
527 #ifndef OPENSSL_NO_RSA
529 p_hwcrhk_RSALoadKey = NULL;
530 p_hwcrhk_RSAGetPublicKey = NULL;
531 p_hwcrhk_RSAUnloadKey = NULL;
533 p_hwcrhk_ModExpCRT = NULL;
534 p_hwcrhk_RandomBytes = NULL;
538 static int hwcrhk_finish(ENGINE *e)
541 if(hwcrhk_dso == NULL)
543 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_NOT_LOADED);
547 release_context(hwcrhk_context);
548 if(!DSO_free(hwcrhk_dso))
550 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_DSO_FAILURE);
558 p_hwcrhk_Init = NULL;
559 p_hwcrhk_Finish = NULL;
560 p_hwcrhk_ModExp = NULL;
561 #ifndef OPENSSL_NO_RSA
563 p_hwcrhk_RSALoadKey = NULL;
564 p_hwcrhk_RSAGetPublicKey = NULL;
565 p_hwcrhk_RSAUnloadKey = NULL;
567 p_hwcrhk_ModExpCRT = NULL;
568 p_hwcrhk_RandomBytes = NULL;
572 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
578 case HWCRHK_CMD_SO_PATH:
581 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_ALREADY_LOADED);
586 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
589 HWCRHK_LIBNAME = (const char *)p;
591 case ENGINE_CTRL_SET_LOGSTREAM:
595 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
601 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
604 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_BIO_WAS_FREED);
606 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
608 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
609 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
610 password_callback = (pem_password_cb *)f;
611 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
613 /* this enables or disables the "SimpleForkCheck" flag used in the
614 * initialisation structure. */
615 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
616 case HWCRHK_CMD_FORK_CHECK:
617 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
619 hwcrhk_globals.flags |=
620 HWCryptoHook_InitFlags_SimpleForkCheck;
622 hwcrhk_globals.flags &=
623 ~HWCryptoHook_InitFlags_SimpleForkCheck;
624 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
626 /* This will prevent the initialisation function from "installing"
627 * the mutex-handling callbacks, even if they are available from
628 * within the library (or were provided to the library from the
629 * calling application). This is to remove any baggage for
630 * applications not using multithreading. */
631 case ENGINE_CTRL_CHIL_NO_LOCKING:
632 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
633 disable_mutex_callbacks = 1;
634 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
636 case HWCRHK_CMD_THREAD_LOCKING:
637 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
638 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
639 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
642 /* The command isn't understood by this engine */
644 ENGINEerr(ENGINE_F_HWCRHK_CTRL,
645 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
653 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
654 const char *passphrase)
656 #ifndef OPENSSL_NO_RSA
659 EVP_PKEY *res = NULL;
660 #ifndef OPENSSL_NO_RSA
661 HWCryptoHook_MPI e, n;
662 HWCryptoHook_RSAKeyHandle *hptr;
664 #if !defined(OPENSSL_NO_RSA)
665 HWCryptoHook_ErrMsgBuf rmsg;
670 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
671 ENGINE_R_NOT_INITIALISED);
674 #ifndef OPENSSL_NO_RSA
675 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
678 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
679 ERR_R_MALLOC_FAILURE);
682 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
685 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
686 ENGINE_R_CHIL_ERROR);
687 ERR_add_error_data(1,rmsg.buf);
692 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
697 #ifndef OPENSSL_NO_RSA
698 rtmp = RSA_new_method(eng);
699 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
702 rtmp->flags |= RSA_FLAG_EXT_PKEY;
705 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
706 != HWCRYPTOHOOK_ERROR_MPISIZE)
708 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,ENGINE_R_CHIL_ERROR);
709 ERR_add_error_data(1,rmsg.buf);
713 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
714 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
718 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
720 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
721 ENGINE_R_CHIL_ERROR);
722 ERR_add_error_data(1,rmsg.buf);
725 rtmp->e->top = e.size / sizeof(BN_ULONG);
727 rtmp->n->top = n.size / sizeof(BN_ULONG);
730 res = EVP_PKEY_new();
731 EVP_PKEY_assign_RSA(res, rtmp);
735 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
736 ENGINE_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
742 #ifndef OPENSSL_NO_RSA
749 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
750 const char *passphrase)
752 EVP_PKEY *res = NULL;
754 #ifndef OPENSSL_NO_RSA
755 res = hwcrhk_load_privkey(eng, key_id, passphrase);
761 #ifndef OPENSSL_NO_RSA
766 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
768 res->pkey.rsa = RSA_new();
769 res->pkey.rsa->n = rsa->n;
770 res->pkey.rsa->e = rsa->e;
771 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
776 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
777 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
788 /* A little mod_exp */
789 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
790 const BIGNUM *m, BN_CTX *ctx)
793 HWCryptoHook_ErrMsgBuf rmsg;
794 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
795 we use them directly, plus a little macro magic. We only
796 thing we need to make sure of is that enough space is allocated. */
797 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
800 to_return = 0; /* expect failure */
806 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
809 /* Prepare the params */
810 bn_expand2(r, m->top); /* Check for error !! */
816 /* Perform the operation */
817 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
819 /* Convert the response */
820 r->top = m_r.size / sizeof(BN_ULONG);
825 /* FIXME: When this error is returned, HWCryptoHook is
826 telling us that falling back to software computation
827 might be a good thing. */
828 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
830 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
834 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FAILED);
836 ERR_add_error_data(1,rmsg.buf);
845 #ifndef OPENSSL_NO_RSA
846 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
849 HWCryptoHook_ErrMsgBuf rmsg;
850 HWCryptoHook_RSAKeyHandle *hptr;
851 int to_return = 0, ret;
855 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
859 /* This provides support for nForce keys. Since that's opaque data
860 all we do is provide a handle to the proper key and let HWCryptoHook
861 take care of the rest. */
862 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
865 HWCryptoHook_MPI m_a, m_r;
869 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
870 ENGINE_R_MISSING_KEY_COMPONENTS);
877 /* Prepare the params */
878 bn_expand2(r, rsa->n->top); /* Check for error !! */
882 /* Perform the operation */
883 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
885 /* Convert the response */
886 r->top = m_r.size / sizeof(BN_ULONG);
891 /* FIXME: When this error is returned, HWCryptoHook is
892 telling us that falling back to software computation
893 might be a good thing. */
894 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
896 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
900 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
902 ERR_add_error_data(1,rmsg.buf);
908 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
910 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
912 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
913 ENGINE_R_MISSING_KEY_COMPONENTS);
920 /* Prepare the params */
921 bn_expand2(r, rsa->n->top); /* Check for error !! */
925 BN2MPI(m_dmp1, rsa->dmp1);
926 BN2MPI(m_dmq1, rsa->dmq1);
927 BN2MPI(m_iqmp, rsa->iqmp);
930 /* Perform the operation */
931 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
932 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
934 /* Convert the response */
935 r->top = m_r.size / sizeof(BN_ULONG);
940 /* FIXME: When this error is returned, HWCryptoHook is
941 telling us that falling back to software computation
942 might be a good thing. */
943 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
945 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
949 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
951 ERR_add_error_data(1,rmsg.buf);
955 /* If we're here, we must be here with some semblance of success :-) */
962 /* This function is aliased to mod_exp (with the mont stuff dropped). */
963 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
964 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
966 return hwcrhk_mod_exp(r, a, p, m, ctx);
969 /* This function is aliased to mod_exp (with the dh and mont dropped). */
970 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
971 const BIGNUM *a, const BIGNUM *p,
972 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
974 return hwcrhk_mod_exp(r, a, p, m, ctx);
977 /* Random bytes are good */
978 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
981 HWCryptoHook_ErrMsgBuf rmsg;
982 int to_return = 0; /* assume failure */
990 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_NOT_INITIALISED);
994 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
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 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FALLBACK);
1006 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FAILED);
1008 ERR_add_error_data(1,rmsg.buf);
1016 static int hwcrhk_rand_status(void)
1021 /* This cleans up an RSA KM key, called when ex_data is freed */
1023 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1024 int ind,long argl, void *argp)
1027 HWCryptoHook_ErrMsgBuf rmsg;
1028 #ifndef OPENSSL_NO_RSA
1029 HWCryptoHook_RSAKeyHandle *hptr;
1031 #if !defined(OPENSSL_NO_RSA)
1038 #ifndef OPENSSL_NO_RSA
1039 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1042 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1048 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1049 * these just wrap the POSIX functions and add some logging.
1052 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1053 HWCryptoHook_CallerContext *cactx)
1055 mt->lockid = CRYPTO_get_new_dynlockid();
1056 if (mt->lockid == 0)
1061 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1063 CRYPTO_w_lock(mt->lockid);
1067 void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1069 CRYPTO_w_unlock(mt->lockid);
1072 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1074 CRYPTO_destroy_dynlockid(mt->lockid);
1077 static int hwcrhk_get_pass(const char *prompt_info,
1078 int *len_io, char *buf,
1079 HWCryptoHook_PassphraseContext *ppctx,
1080 HWCryptoHook_CallerContext *cactx)
1085 if (password_callback == NULL)
1087 ENGINEerr(ENGINE_F_HWCRHK_GET_PASS,ENGINE_R_NO_CALLBACK);
1092 strncpy(prompt, "Card: \"", sizeof(prompt));
1094 strncpy(prompt + l, prompt_info, sizeof(prompt) - l);
1095 l += strlen(prompt_info);
1096 if (l + 2 < sizeof(prompt))
1098 strncpy(prompt + l, "\"\n", sizeof(prompt) - l);
1102 if (l < sizeof(prompt) - 1)
1104 strncpy(prompt, "Enter Passphrase <enter to cancel>:",
1105 sizeof(prompt) - l);
1110 /* I know, passing on the prompt instead of the user data *is*
1111 a bad thing. However, that's all we have right now.
1112 -- Richard Levitte */
1113 *len_io = password_callback(buf, *len_io, 0, prompt);
1119 static void hwcrhk_log_message(void *logstr, const char *message)
1121 BIO *lstream = NULL;
1123 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1125 lstream=*(BIO **)logstr;
1128 BIO_write(lstream, message, strlen(message));
1130 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1133 #endif /* !OPENSSL_NO_HW_NCIPHER */
1134 #endif /* !OPENSSL_NO_HW */