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>
69 #ifndef OPENSSL_NO_HW_NCIPHER
71 /* Attribution notice: nCipher have said several times that it's OK for
72 * us to implement a general interface to their boxes, and recently declared
73 * their HWCryptoHook to be public, and therefore available for us to use.
76 * The hwcryptohook.h included here is from May 2000.
80 #include "hwcryptohook.h"
82 #include "vendor_defns/hwcryptohook.h"
85 static int hwcrhk_init(ENGINE *e);
86 static int hwcrhk_finish(ENGINE *e);
87 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
89 /* Functions to handle mutexes */
90 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
91 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
92 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
93 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
96 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
97 const BIGNUM *m, BN_CTX *ctx);
99 #ifndef OPENSSL_NO_RSA
101 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa);
103 /* This function is aliased to mod_exp (with the mont stuff dropped). */
104 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
105 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
108 /* This function is alised to mod_exp (with the DH and mont dropped). */
109 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
110 const BIGNUM *a, const BIGNUM *p,
111 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
114 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
115 static int hwcrhk_rand_status(void);
118 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
119 pem_password_cb *callback, void *callback_data);
120 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
121 pem_password_cb *callback, void *callback_data);
122 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
123 int ind,long argl, void *argp);
125 /* Interaction stuff */
126 static int hwcrhk_get_pass(const char *prompt_info,
127 int *len_io, char *buf,
128 HWCryptoHook_PassphraseContext *ppctx,
129 HWCryptoHook_CallerContext *cactx);
130 static void hwcrhk_log_message(void *logstr, const char *message);
132 /* The definitions for control commands specific to this engine */
133 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
134 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
135 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
136 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
139 "Specifies the path to the 'hwcrhk' shared library",
140 ENGINE_CMD_FLAG_STRING},
141 {HWCRHK_CMD_FORK_CHECK,
143 "Turns fork() checking on or off (boolean)",
144 ENGINE_CMD_FLAG_NUMERIC},
145 {HWCRHK_CMD_THREAD_LOCKING,
147 "Turns thread-safe locking on or off (boolean)",
148 ENGINE_CMD_FLAG_NUMERIC},
152 #ifndef OPENSSL_NO_RSA
153 /* Our internal RSA_METHOD that we provide pointers to */
154 static RSA_METHOD hwcrhk_rsa =
156 "nCipher RSA method",
172 #ifndef OPENSSL_NO_DH
173 /* Our internal DH_METHOD that we provide pointers to */
174 static DH_METHOD hwcrhk_dh =
187 static RAND_METHOD hwcrhk_rand =
189 /* "nCipher RAND method", */
198 /* Constants used when creating the ENGINE */
199 static const char *engine_hwcrhk_id = "chil";
200 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
202 /* Internal stuff for HWCryptoHook */
204 /* Some structures needed for proper use of thread locks */
205 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
206 into HWCryptoHook_Mutex */
207 struct HWCryptoHook_MutexValue
212 /* hwcryptohook.h has some typedefs that turn
213 struct HWCryptoHook_PassphraseContextValue
214 into HWCryptoHook_PassphraseContext */
215 struct HWCryptoHook_PassphraseContextValue
217 pem_password_cb *password_callback; /* If != NULL, will be called */
221 /* hwcryptohook.h has some typedefs that turn
222 struct HWCryptoHook_CallerContextValue
223 into HWCryptoHook_CallerContext */
224 struct HWCryptoHook_CallerContextValue
229 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
230 BIGNUM's, so lets define a couple of conversion macros */
231 #define BN2MPI(mp, bn) \
232 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
233 #define MPI2BN(bn, mp) \
234 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
236 #if 0 /* Card and password management is not yet supported */
237 /* HWCryptoHook callbacks. insert_card() and get_pass() are not yet
238 defined, because we haven't quite decided on the proper form yet.
239 log_message() just adds an entry in the error stack. I don't know
240 if that's good or bad... */
241 static int insert_card(const char *prompt_info,
242 const char *wrong_info,
243 HWCryptoHook_PassphraseContext *ppctx,
244 HWCryptoHook_CallerContext *cactx);
245 static int get_pass(const char *prompt_info,
246 int *len_io, char *buf,
247 HWCryptoHook_PassphraseContext *ppctx,
248 HWCryptoHook_CallerContext *cactx);
251 static BIO *logstream = NULL;
252 static pem_password_cb *password_callback = NULL;
254 static void *password_callback_userdata = NULL;
256 static int disable_mutex_callbacks = 0;
258 /* Stuff to pass to the HWCryptoHook library */
259 static HWCryptoHook_InitInfo hwcrhk_globals = {
261 &logstream, /* logstream */
262 sizeof(BN_ULONG), /* limbsize */
263 0, /* mslimb first: false for BNs */
264 -1, /* msbyte first: use native */
265 0, /* Max mutexes, 0 = no small limit */
266 0, /* Max simultaneous, 0 = default */
268 /* The next few are mutex stuff: we write wrapper functions
269 around the OS mutex functions. We initialise them to 0
270 here, and change that to actual function pointers in hwcrhk_init()
271 if dynamic locks are supported (that is, if the application
272 programmer has made sure of setting up callbacks bafore starting
273 this engine) *and* if disable_mutex_callbacks hasn't been set by
274 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
275 sizeof(HWCryptoHook_Mutex),
281 /* The next few are condvar stuff: we write wrapper functions
282 round the OS functions. Currently not implemented and not
283 and absolute necessity even in threaded programs, therefore
284 0'ed. Will hopefully be implemented some day, since it
285 enhances the efficiency of HWCryptoHook. */
286 0, /* sizeof(HWCryptoHook_CondVar), */
287 0, /* hwcrhk_cv_init, */
288 0, /* hwcrhk_cv_wait, */
289 0, /* hwcrhk_cv_signal, */
290 0, /* hwcrhk_cv_broadcast, */
291 0, /* hwcrhk_cv_destroy, */
293 hwcrhk_get_pass, /* pass phrase */
294 0, /* insert_card, */ /* insert a card */
295 hwcrhk_log_message /* Log message */
299 /* Now, to our own code */
301 /* As this is only ever called once, there's no need for locking
302 * (indeed - the lock will already be held by our caller!!!) */
303 ENGINE *ENGINE_ncipher()
305 #ifndef OPENSSL_NO_RSA
306 const RSA_METHOD *meth1;
308 #ifndef OPENSSL_NO_DH
309 const DH_METHOD *meth2;
311 ENGINE *ret = ENGINE_new();
314 if(!ENGINE_set_id(ret, engine_hwcrhk_id) ||
315 !ENGINE_set_name(ret, engine_hwcrhk_name) ||
316 #ifndef OPENSSL_NO_RSA
317 !ENGINE_set_RSA(ret, &hwcrhk_rsa) ||
319 #ifndef OPENSSL_NO_DH
320 !ENGINE_set_DH(ret, &hwcrhk_dh) ||
322 !ENGINE_set_RAND(ret, &hwcrhk_rand) ||
323 !ENGINE_set_BN_mod_exp(ret, hwcrhk_mod_exp) ||
324 !ENGINE_set_init_function(ret, hwcrhk_init) ||
325 !ENGINE_set_finish_function(ret, hwcrhk_finish) ||
326 !ENGINE_set_ctrl_function(ret, hwcrhk_ctrl) ||
327 !ENGINE_set_load_privkey_function(ret, hwcrhk_load_privkey) ||
328 !ENGINE_set_load_pubkey_function(ret, hwcrhk_load_pubkey) ||
329 !ENGINE_set_cmd_defns(ret, hwcrhk_cmd_defns))
335 #ifndef OPENSSL_NO_RSA
336 /* We know that the "PKCS1_SSLeay()" functions hook properly
337 * to the cswift-specific mod_exp and mod_exp_crt so we use
338 * those functions. NB: We don't use ENGINE_openssl() or
339 * anything "more generic" because something like the RSAref
340 * code may not hook properly, and if you own one of these
341 * cards then you have the right to do RSA operations on it
343 meth1 = RSA_PKCS1_SSLeay();
344 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
345 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
346 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
347 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
350 #ifndef OPENSSL_NO_DH
351 /* Much the same for Diffie-Hellman */
352 meth2 = DH_OpenSSL();
353 hwcrhk_dh.generate_key = meth2->generate_key;
354 hwcrhk_dh.compute_key = meth2->compute_key;
359 /* This is a process-global DSO handle used for loading and unloading
360 * the HWCryptoHook library. NB: This is only set (or unset) during an
361 * init() or finish() call (reference counts permitting) and they're
362 * operating with global locks, so this should be thread-safe
364 static DSO *hwcrhk_dso = NULL;
365 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
366 #ifndef OPENSSL_NO_RSA
367 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
370 /* These are the function pointers that are (un)set when the library has
371 * successfully (un)loaded. */
372 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
373 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
374 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
375 #ifndef OPENSSL_NO_RSA
376 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
378 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
379 #ifndef OPENSSL_NO_RSA
380 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
381 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
382 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
384 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
386 /* Used in the DSO operations. */
387 static const char def_HWCRHK_LIBNAME[] = "nfhwcrhk";
388 static const char *HWCRHK_LIBNAME = def_HWCRHK_LIBNAME;
389 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
390 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
391 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
392 #ifndef OPENSSL_NO_RSA
393 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
395 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
396 #ifndef OPENSSL_NO_RSA
397 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
398 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
399 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
401 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
403 /* HWCryptoHook library functions and mechanics - these are used by the
404 * higher-level functions further down. NB: As and where there's no
405 * error checking, take a look lower down where these functions are
406 * called, the checking and error handling is probably down there. */
408 /* utility function to obtain a context */
409 static int get_context(HWCryptoHook_ContextHandle *hac)
412 HWCryptoHook_ErrMsgBuf rmsg;
417 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
424 /* similarly to release one. */
425 static void release_context(HWCryptoHook_ContextHandle hac)
427 p_hwcrhk_Finish(hac);
430 /* (de)initialisation functions. */
431 static int hwcrhk_init(ENGINE *e)
433 HWCryptoHook_Init_t *p1;
434 HWCryptoHook_Finish_t *p2;
435 HWCryptoHook_ModExp_t *p3;
436 #ifndef OPENSSL_NO_RSA
437 HWCryptoHook_RSA_t *p4;
438 HWCryptoHook_RSALoadKey_t *p5;
439 HWCryptoHook_RSAGetPublicKey_t *p6;
440 HWCryptoHook_RSAUnloadKey_t *p7;
442 HWCryptoHook_RandomBytes_t *p8;
443 HWCryptoHook_ModExpCRT_t *p9;
445 if(hwcrhk_dso != NULL)
447 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_ALREADY_LOADED);
450 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
451 hwcrhk_dso = DSO_load(NULL, HWCRHK_LIBNAME, NULL, 0);
452 if(hwcrhk_dso == NULL)
454 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
457 if(!(p1 = (HWCryptoHook_Init_t *)
458 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
459 !(p2 = (HWCryptoHook_Finish_t *)
460 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
461 !(p3 = (HWCryptoHook_ModExp_t *)
462 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
463 #ifndef OPENSSL_NO_RSA
464 !(p4 = (HWCryptoHook_RSA_t *)
465 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
466 !(p5 = (HWCryptoHook_RSALoadKey_t *)
467 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
468 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
469 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
470 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
471 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
473 !(p8 = (HWCryptoHook_RandomBytes_t *)
474 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
475 !(p9 = (HWCryptoHook_ModExpCRT_t *)
476 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
478 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
481 /* Copy the pointers */
483 p_hwcrhk_Finish = p2;
484 p_hwcrhk_ModExp = p3;
485 #ifndef OPENSSL_NO_RSA
487 p_hwcrhk_RSALoadKey = p5;
488 p_hwcrhk_RSAGetPublicKey = p6;
489 p_hwcrhk_RSAUnloadKey = p7;
491 p_hwcrhk_RandomBytes = p8;
492 p_hwcrhk_ModExpCRT = p9;
494 /* Check if the application decided to support dynamic locks,
495 and if it does, use them. */
496 if (disable_mutex_callbacks == 0 &&
497 CRYPTO_get_dynlock_create_callback() != NULL &&
498 CRYPTO_get_dynlock_lock_callback() != NULL &&
499 CRYPTO_get_dynlock_destroy_callback() != NULL)
501 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
502 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
503 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
504 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
507 /* Try and get a context - if not, we may have a DSO but no
509 if(!get_context(&hwcrhk_context))
511 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_UNIT_FAILURE);
514 /* Everything's fine. */
515 #ifndef OPENSSL_NO_RSA
516 if (hndidx_rsa == -1)
517 hndidx_rsa = RSA_get_ex_new_index(0,
518 "nFast HWCryptoHook RSA key handle",
519 NULL, NULL, hwcrhk_ex_free);
524 DSO_free(hwcrhk_dso);
526 p_hwcrhk_Init = NULL;
527 p_hwcrhk_Finish = NULL;
528 p_hwcrhk_ModExp = NULL;
529 #ifndef OPENSSL_NO_RSA
531 p_hwcrhk_RSALoadKey = NULL;
532 p_hwcrhk_RSAGetPublicKey = NULL;
533 p_hwcrhk_RSAUnloadKey = NULL;
535 p_hwcrhk_ModExpCRT = NULL;
536 p_hwcrhk_RandomBytes = NULL;
540 static int hwcrhk_finish(ENGINE *e)
543 if(hwcrhk_dso == NULL)
545 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_NOT_LOADED);
549 release_context(hwcrhk_context);
550 if(!DSO_free(hwcrhk_dso))
552 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_DSO_FAILURE);
560 p_hwcrhk_Init = NULL;
561 p_hwcrhk_Finish = NULL;
562 p_hwcrhk_ModExp = NULL;
563 #ifndef OPENSSL_NO_RSA
565 p_hwcrhk_RSALoadKey = NULL;
566 p_hwcrhk_RSAGetPublicKey = NULL;
567 p_hwcrhk_RSAUnloadKey = NULL;
569 p_hwcrhk_ModExpCRT = NULL;
570 p_hwcrhk_RandomBytes = NULL;
574 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
580 case HWCRHK_CMD_SO_PATH:
583 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_ALREADY_LOADED);
588 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
591 HWCRHK_LIBNAME = (const char *)p;
593 case ENGINE_CTRL_SET_LOGSTREAM:
597 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
603 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
606 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_BIO_WAS_FREED);
608 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
610 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
611 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
612 password_callback = (pem_password_cb *)f;
613 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
615 /* this enables or disables the "SimpleForkCheck" flag used in the
616 * initialisation structure. */
617 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
618 case HWCRHK_CMD_FORK_CHECK:
619 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
621 hwcrhk_globals.flags |=
622 HWCryptoHook_InitFlags_SimpleForkCheck;
624 hwcrhk_globals.flags &=
625 ~HWCryptoHook_InitFlags_SimpleForkCheck;
626 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
628 /* This will prevent the initialisation function from "installing"
629 * the mutex-handling callbacks, even if they are available from
630 * within the library (or were provided to the library from the
631 * calling application). This is to remove any baggage for
632 * applications not using multithreading. */
633 case ENGINE_CTRL_CHIL_NO_LOCKING:
634 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
635 disable_mutex_callbacks = 1;
636 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
638 case HWCRHK_CMD_THREAD_LOCKING:
639 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
640 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
641 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
644 /* The command isn't understood by this engine */
646 ENGINEerr(ENGINE_F_HWCRHK_CTRL,
647 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
655 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
656 pem_password_cb *callback, void *callback_data)
658 #ifndef OPENSSL_NO_RSA
661 EVP_PKEY *res = NULL;
662 #ifndef OPENSSL_NO_RSA
663 HWCryptoHook_MPI e, n;
664 HWCryptoHook_RSAKeyHandle *hptr;
666 #if !defined(OPENSSL_NO_RSA)
667 HWCryptoHook_ErrMsgBuf rmsg;
669 HWCryptoHook_PassphraseContext ppctx;
673 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
674 ENGINE_R_NOT_INITIALISED);
677 #ifndef OPENSSL_NO_RSA
678 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
681 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
682 ERR_R_MALLOC_FAILURE);
685 ppctx.password_callback = callback;
686 ppctx.callback_data = callback_data;
687 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
690 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
691 ENGINE_R_CHIL_ERROR);
692 ERR_add_error_data(1,rmsg.buf);
697 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
702 #ifndef OPENSSL_NO_RSA
703 rtmp = RSA_new_method(eng);
704 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
707 rtmp->flags |= RSA_FLAG_EXT_PKEY;
710 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
711 != HWCRYPTOHOOK_ERROR_MPISIZE)
713 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,ENGINE_R_CHIL_ERROR);
714 ERR_add_error_data(1,rmsg.buf);
718 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
719 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
723 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
725 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
726 ENGINE_R_CHIL_ERROR);
727 ERR_add_error_data(1,rmsg.buf);
730 rtmp->e->top = e.size / sizeof(BN_ULONG);
732 rtmp->n->top = n.size / sizeof(BN_ULONG);
735 res = EVP_PKEY_new();
736 EVP_PKEY_assign_RSA(res, rtmp);
740 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
741 ENGINE_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
747 #ifndef OPENSSL_NO_RSA
754 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
755 pem_password_cb *callback, void *callback_data)
757 EVP_PKEY *res = NULL;
759 #ifndef OPENSSL_NO_RSA
760 res = hwcrhk_load_privkey(eng, key_id, callback, callback_data);
766 #ifndef OPENSSL_NO_RSA
771 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
773 res->pkey.rsa = RSA_new();
774 res->pkey.rsa->n = rsa->n;
775 res->pkey.rsa->e = rsa->e;
776 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
781 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
782 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
793 /* A little mod_exp */
794 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
795 const BIGNUM *m, BN_CTX *ctx)
798 HWCryptoHook_ErrMsgBuf rmsg;
799 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
800 we use them directly, plus a little macro magic. We only
801 thing we need to make sure of is that enough space is allocated. */
802 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
805 to_return = 0; /* expect failure */
811 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
814 /* Prepare the params */
815 bn_expand2(r, m->top); /* Check for error !! */
821 /* Perform the operation */
822 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
824 /* Convert the response */
825 r->top = m_r.size / sizeof(BN_ULONG);
830 /* FIXME: When this error is returned, HWCryptoHook is
831 telling us that falling back to software computation
832 might be a good thing. */
833 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
835 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
839 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FAILED);
841 ERR_add_error_data(1,rmsg.buf);
850 #ifndef OPENSSL_NO_RSA
851 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
854 HWCryptoHook_ErrMsgBuf rmsg;
855 HWCryptoHook_RSAKeyHandle *hptr;
856 int to_return = 0, ret;
860 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
864 /* This provides support for nForce keys. Since that's opaque data
865 all we do is provide a handle to the proper key and let HWCryptoHook
866 take care of the rest. */
867 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
870 HWCryptoHook_MPI m_a, m_r;
874 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
875 ENGINE_R_MISSING_KEY_COMPONENTS);
882 /* Prepare the params */
883 bn_expand2(r, rsa->n->top); /* Check for error !! */
887 /* Perform the operation */
888 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
890 /* Convert the response */
891 r->top = m_r.size / sizeof(BN_ULONG);
896 /* FIXME: When this error is returned, HWCryptoHook is
897 telling us that falling back to software computation
898 might be a good thing. */
899 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
901 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
905 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
907 ERR_add_error_data(1,rmsg.buf);
913 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
915 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
917 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
918 ENGINE_R_MISSING_KEY_COMPONENTS);
925 /* Prepare the params */
926 bn_expand2(r, rsa->n->top); /* Check for error !! */
930 BN2MPI(m_dmp1, rsa->dmp1);
931 BN2MPI(m_dmq1, rsa->dmq1);
932 BN2MPI(m_iqmp, rsa->iqmp);
935 /* Perform the operation */
936 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
937 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
939 /* Convert the response */
940 r->top = m_r.size / sizeof(BN_ULONG);
945 /* FIXME: When this error is returned, HWCryptoHook is
946 telling us that falling back to software computation
947 might be a good thing. */
948 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
950 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
954 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
956 ERR_add_error_data(1,rmsg.buf);
960 /* If we're here, we must be here with some semblance of success :-) */
967 /* This function is aliased to mod_exp (with the mont stuff dropped). */
968 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
969 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
971 return hwcrhk_mod_exp(r, a, p, m, ctx);
974 /* This function is aliased to mod_exp (with the dh and mont dropped). */
975 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
976 const BIGNUM *a, const BIGNUM *p,
977 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
979 return hwcrhk_mod_exp(r, a, p, m, ctx);
982 /* Random bytes are good */
983 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
986 HWCryptoHook_ErrMsgBuf rmsg;
987 int to_return = 0; /* assume failure */
995 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_NOT_INITIALISED);
999 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1002 /* FIXME: When this error is returned, HWCryptoHook is
1003 telling us that falling back to software computation
1004 might be a good thing. */
1005 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1007 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FALLBACK);
1011 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FAILED);
1013 ERR_add_error_data(1,rmsg.buf);
1021 static int hwcrhk_rand_status(void)
1026 /* This cleans up an RSA KM key, called when ex_data is freed */
1028 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1029 int ind,long argl, void *argp)
1032 HWCryptoHook_ErrMsgBuf rmsg;
1033 #ifndef OPENSSL_NO_RSA
1034 HWCryptoHook_RSAKeyHandle *hptr;
1036 #if !defined(OPENSSL_NO_RSA)
1043 #ifndef OPENSSL_NO_RSA
1044 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1047 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1053 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1054 * these just wrap the POSIX functions and add some logging.
1057 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1058 HWCryptoHook_CallerContext *cactx)
1060 mt->lockid = CRYPTO_get_new_dynlockid();
1061 if (mt->lockid == 0)
1066 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1068 CRYPTO_w_lock(mt->lockid);
1072 void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1074 CRYPTO_w_unlock(mt->lockid);
1077 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1079 CRYPTO_destroy_dynlockid(mt->lockid);
1082 static int hwcrhk_get_pass(const char *prompt_info,
1083 int *len_io, char *buf,
1084 HWCryptoHook_PassphraseContext *ppctx,
1085 HWCryptoHook_CallerContext *cactx)
1087 pem_password_cb *callback = password_callback;
1088 void *callback_data = NULL;
1092 if (ppctx->password_callback)
1093 callback = ppctx->password_callback;
1094 if (ppctx->callback_data)
1095 callback_data = ppctx->callback_data;
1097 if (callback == NULL)
1099 ENGINEerr(ENGINE_F_HWCRHK_GET_PASS,ENGINE_R_NO_CALLBACK);
1103 *len_io = callback(buf, *len_io, 0, callback_data);
1109 static void hwcrhk_log_message(void *logstr, const char *message)
1111 BIO *lstream = NULL;
1113 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1115 lstream=*(BIO **)logstr;
1118 BIO_write(lstream, message, strlen(message));
1120 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1123 #endif /* !OPENSSL_NO_HW_NCIPHER */
1124 #endif /* !OPENSSL_NO_HW */