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 "engine_int.h"
66 #include <openssl/engine.h>
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(void);
86 static int hwcrhk_finish(void);
87 static int hwcrhk_ctrl(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);
100 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa);
101 /* This function is aliased to mod_exp (with the mont stuff dropped). */
102 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
103 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
106 /* This function is alised to mod_exp (with the DH and mont dropped). */
107 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
108 const BIGNUM *a, const BIGNUM *p,
109 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
112 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
113 static int hwcrhk_rand_status(void);
116 static EVP_PKEY *hwcrhk_load_privkey(const char *key_id,
117 const char *passphrase);
118 static EVP_PKEY *hwcrhk_load_pubkey(const char *key_id,
119 const char *passphrase);
120 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
121 int ind,long argl, void *argp);
123 /* Interaction stuff */
124 static int hwcrhk_get_pass(const char *prompt_info,
125 int *len_io, char *buf,
126 HWCryptoHook_PassphraseContext *ppctx,
127 HWCryptoHook_CallerContext *cactx);
128 static void hwcrhk_log_message(void *logstr, const char *message);
130 /* Our internal RSA_METHOD that we provide pointers to */
131 static RSA_METHOD hwcrhk_rsa =
133 "nCipher RSA method",
148 /* Our internal DH_METHOD that we provide pointers to */
149 static DH_METHOD hwcrhk_dh =
161 static RAND_METHOD hwcrhk_rand =
163 /* "nCipher RAND method", */
172 /* Our ENGINE structure. */
173 static ENGINE engine_hwcrhk =
176 "nCipher hardware engine support",
189 0, 0, /* no references */
190 NULL, NULL /* unlinked */
193 /* Internal stuff for HWCryptoHook */
195 /* Some structures needed for proper use of thread locks */
196 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
197 into HWCryptoHook_Mutex */
198 struct HWCryptoHook_MutexValue
203 /* hwcryptohook.h has some typedefs that turn
204 struct HWCryptoHook_PassphraseContextValue
205 into HWCryptoHook_PassphraseContext */
206 struct HWCryptoHook_PassphraseContextValue
211 /* hwcryptohook.h has some typedefs that turn
212 struct HWCryptoHook_CallerContextValue
213 into HWCryptoHook_CallerContext */
214 struct HWCryptoHook_CallerContextValue
219 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
220 BIGNUM's, so lets define a couple of conversion macros */
221 #define BN2MPI(mp, bn) \
222 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
223 #define MPI2BN(bn, mp) \
224 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
226 #if 0 /* Card and password management is not yet supported */
227 /* HWCryptoHook callbacks. insert_card() and get_pass() are not yet
228 defined, because we haven't quite decided on the proper form yet.
229 log_message() just adds an entry in the error stack. I don't know
230 if that's good or bad... */
231 static int insert_card(const char *prompt_info,
232 const char *wrong_info,
233 HWCryptoHook_PassphraseContext *ppctx,
234 HWCryptoHook_CallerContext *cactx);
235 static int get_pass(const char *prompt_info,
236 int *len_io, char *buf,
237 HWCryptoHook_PassphraseContext *ppctx,
238 HWCryptoHook_CallerContext *cactx);
241 static BIO *logstream = NULL;
242 static pem_password_cb *password_callback = NULL;
244 static void *password_callback_userdata = NULL;
246 static int disable_mutex_callbacks = 0;
248 /* Stuff to pass to the HWCryptoHook library */
249 static HWCryptoHook_InitInfo hwcrhk_globals = {
251 &logstream, /* logstream */
252 sizeof(BN_ULONG), /* limbsize */
253 0, /* mslimb first: false for BNs */
254 -1, /* msbyte first: use native */
255 0, /* Max mutexes, 0 = no small limit */
256 0, /* Max simultaneous, 0 = default */
258 /* The next few are mutex stuff: we write wrapper functions
259 around the OS mutex functions. We initialise them to 0
260 here, and change that to actual function pointers in hwcrhk_init()
261 if dynamic locks are supported (that is, if the application
262 programmer has made sure of setting up callbacks bafore starting
263 this engine) *and* if disable_mutex_callbacks hasn't been set by
264 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
265 sizeof(HWCryptoHook_Mutex),
271 /* The next few are condvar stuff: we write wrapper functions
272 round the OS functions. Currently not implemented and not
273 and absolute necessity even in threaded programs, therefore
274 0'ed. Will hopefully be implemented some day, since it
275 enhances the efficiency of HWCryptoHook. */
276 0, /* sizeof(HWCryptoHook_CondVar), */
277 0, /* hwcrhk_cv_init, */
278 0, /* hwcrhk_cv_wait, */
279 0, /* hwcrhk_cv_signal, */
280 0, /* hwcrhk_cv_broadcast, */
281 0, /* hwcrhk_cv_destroy, */
283 hwcrhk_get_pass, /* pass phrase */
284 0, /* insert_card, */ /* insert a card */
285 hwcrhk_log_message /* Log message */
289 /* Now, to our own code */
291 /* As this is only ever called once, there's no need for locking
292 * (indeed - the lock will already be held by our caller!!!) */
293 ENGINE *ENGINE_ncipher()
295 const RSA_METHOD *meth1;
296 const DH_METHOD *meth2;
298 /* We know that the "PKCS1_SSLeay()" functions hook properly
299 * to the cswift-specific mod_exp and mod_exp_crt so we use
300 * those functions. NB: We don't use ENGINE_openssl() or
301 * anything "more generic" because something like the RSAref
302 * code may not hook properly, and if you own one of these
303 * cards then you have the right to do RSA operations on it
305 meth1 = RSA_PKCS1_SSLeay();
306 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
307 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
308 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
309 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
311 /* Much the same for Diffie-Hellman */
312 meth2 = DH_OpenSSL();
313 hwcrhk_dh.generate_key = meth2->generate_key;
314 hwcrhk_dh.compute_key = meth2->compute_key;
315 return &engine_hwcrhk;
318 /* This is a process-global DSO handle used for loading and unloading
319 * the HWCryptoHook library. NB: This is only set (or unset) during an
320 * init() or finish() call (reference counts permitting) and they're
321 * operating with global locks, so this should be thread-safe
323 static DSO *hwcrhk_dso = NULL;
324 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
325 static int hndidx = -1; /* Index for KM handle. Not really used yet. */
327 /* These are the function pointers that are (un)set when the library has
328 * successfully (un)loaded. */
329 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
330 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
331 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
332 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
333 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
334 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
335 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
336 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
337 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
339 /* Used in the DSO operations. */
340 static const char *HWCRHK_LIBNAME = "nfhwcrhk";
341 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
342 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
343 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
344 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
345 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
346 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
347 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
348 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
349 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
351 /* HWCryptoHook library functions and mechanics - these are used by the
352 * higher-level functions further down. NB: As and where there's no
353 * error checking, take a look lower down where these functions are
354 * called, the checking and error handling is probably down there. */
356 /* utility function to obtain a context */
357 static int get_context(HWCryptoHook_ContextHandle *hac)
360 HWCryptoHook_ErrMsgBuf rmsg;
365 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
372 /* similarly to release one. */
373 static void release_context(HWCryptoHook_ContextHandle hac)
375 p_hwcrhk_Finish(hac);
378 /* (de)initialisation functions. */
379 static int hwcrhk_init()
381 HWCryptoHook_Init_t *p1;
382 HWCryptoHook_Finish_t *p2;
383 HWCryptoHook_ModExp_t *p3;
384 HWCryptoHook_RSA_t *p4;
385 HWCryptoHook_RSALoadKey_t *p5;
386 HWCryptoHook_RSAGetPublicKey_t *p6;
387 HWCryptoHook_RSAUnloadKey_t *p7;
388 HWCryptoHook_RandomBytes_t *p8;
389 HWCryptoHook_ModExpCRT_t *p9;
391 if(hwcrhk_dso != NULL)
393 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_ALREADY_LOADED);
396 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
397 hwcrhk_dso = DSO_load(NULL, HWCRHK_LIBNAME, NULL, 0);
398 if(hwcrhk_dso == NULL)
400 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
403 if(!(p1 = (HWCryptoHook_Init_t *)
404 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
405 !(p2 = (HWCryptoHook_Finish_t *)
406 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
407 !(p3 = (HWCryptoHook_ModExp_t *)
408 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
409 !(p4 = (HWCryptoHook_RSA_t *)
410 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
411 !(p5 = (HWCryptoHook_RSALoadKey_t *)
412 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
413 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
414 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
415 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
416 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
417 !(p8 = (HWCryptoHook_RandomBytes_t *)
418 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
419 !(p9 = (HWCryptoHook_ModExpCRT_t *)
420 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
422 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
425 /* Copy the pointers */
427 p_hwcrhk_Finish = p2;
428 p_hwcrhk_ModExp = p3;
430 p_hwcrhk_RSALoadKey = p5;
431 p_hwcrhk_RSAGetPublicKey = p6;
432 p_hwcrhk_RSAUnloadKey = p7;
433 p_hwcrhk_RandomBytes = p8;
434 p_hwcrhk_ModExpCRT = p9;
436 /* Check if the application decided to support dynamic locks,
437 and if it does, use them. */
438 if (disable_mutex_callbacks == 0 &&
439 CRYPTO_get_dynlock_create_callback() != NULL &&
440 CRYPTO_get_dynlock_lock_callback() != NULL &&
441 CRYPTO_get_dynlock_destroy_callback() != NULL)
443 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
444 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
445 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
446 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
449 /* Try and get a context - if not, we may have a DSO but no
451 if(!get_context(&hwcrhk_context))
453 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_UNIT_FAILURE);
456 /* Everything's fine. */
458 hndidx = RSA_get_ex_new_index(0,
459 "nFast HWCryptoHook RSA key handle",
460 NULL, NULL, hwcrhk_ex_free);
464 DSO_free(hwcrhk_dso);
466 p_hwcrhk_Init = NULL;
467 p_hwcrhk_Finish = NULL;
468 p_hwcrhk_ModExp = NULL;
470 p_hwcrhk_RSALoadKey = NULL;
471 p_hwcrhk_RSAGetPublicKey = NULL;
472 p_hwcrhk_RSAUnloadKey = NULL;
473 p_hwcrhk_ModExpCRT = NULL;
474 p_hwcrhk_RandomBytes = NULL;
478 static int hwcrhk_finish()
481 if(hwcrhk_dso == NULL)
483 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_NOT_LOADED);
487 release_context(hwcrhk_context);
488 if(!DSO_free(hwcrhk_dso))
490 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_DSO_FAILURE);
498 p_hwcrhk_Init = NULL;
499 p_hwcrhk_Finish = NULL;
500 p_hwcrhk_ModExp = NULL;
502 p_hwcrhk_RSALoadKey = NULL;
503 p_hwcrhk_RSAGetPublicKey = NULL;
504 p_hwcrhk_RSAUnloadKey = NULL;
505 p_hwcrhk_ModExpCRT = NULL;
506 p_hwcrhk_RandomBytes = NULL;
510 static int hwcrhk_ctrl(int cmd, long i, void *p, void (*f)())
516 case ENGINE_CTRL_SET_LOGSTREAM:
520 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
526 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
529 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_BIO_WAS_FREED);
531 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
533 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
534 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
535 password_callback = (pem_password_cb *)f;
536 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
538 /* this enables or disables the "SimpleForkCheck" flag used in the
539 * initialisation structure. */
540 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
541 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
543 hwcrhk_globals.flags |=
544 HWCryptoHook_InitFlags_SimpleForkCheck;
546 hwcrhk_globals.flags &=
547 ~HWCryptoHook_InitFlags_SimpleForkCheck;
548 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
550 /* This will prevent the initialisation function from "installing"
551 * the mutex-handling callbacks, even if they are available from
552 * within the library (or were provided to the library from the
553 * calling application). This is to remove any baggage for
554 * applications not using multithreading. */
555 case ENGINE_CTRL_CHIL_NO_LOCKING:
556 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
557 disable_mutex_callbacks = 1;
558 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
561 /* The command isn't understood by this engine */
563 ENGINEerr(ENGINE_F_HWCRHK_CTRL,
564 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
572 static EVP_PKEY *hwcrhk_load_privkey(const char *key_id,
573 const char *passphrase)
576 EVP_PKEY *res = NULL;
577 HWCryptoHook_MPI e, n;
578 HWCryptoHook_RSAKeyHandle *hptr;
579 HWCryptoHook_ErrMsgBuf rmsg;
583 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
584 ENGINE_R_NOT_INITIALISED);
587 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
590 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
591 ERR_R_MALLOC_FAILURE);
594 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
597 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
598 ENGINE_R_CHIL_ERROR);
599 ERR_add_error_data(1,rmsg.buf);
604 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
608 rtmp = RSA_new_method(&engine_hwcrhk);
609 RSA_set_ex_data(rtmp, hndidx, (char *)hptr);
612 rtmp->flags |= RSA_FLAG_EXT_PKEY;
615 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
616 != HWCRYPTOHOOK_ERROR_MPISIZE)
618 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,ENGINE_R_CHIL_ERROR);
619 ERR_add_error_data(1,rmsg.buf);
623 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
624 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
628 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
630 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
631 ENGINE_R_CHIL_ERROR);
632 ERR_add_error_data(1,rmsg.buf);
635 rtmp->e->top = e.size / sizeof(BN_ULONG);
637 rtmp->n->top = n.size / sizeof(BN_ULONG);
640 res = EVP_PKEY_new();
641 EVP_PKEY_assign_RSA(res, rtmp);
652 static EVP_PKEY *hwcrhk_load_pubkey(const char *key_id, const char *passphrase)
654 EVP_PKEY *res = hwcrhk_load_privkey(key_id, passphrase);
663 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
665 res->pkey.rsa = RSA_new();
666 res->pkey.rsa->n = rsa->n;
667 res->pkey.rsa->e = rsa->e;
668 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
672 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
673 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
684 /* A little mod_exp */
685 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
686 const BIGNUM *m, BN_CTX *ctx)
689 HWCryptoHook_ErrMsgBuf rmsg;
690 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
691 we use them directly, plus a little macro magic. We only
692 thing we need to make sure of is that enough space is allocated. */
693 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
696 to_return = 0; /* expect failure */
702 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
705 /* Prepare the params */
706 bn_expand2(r, m->top); /* Check for error !! */
712 /* Perform the operation */
713 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
715 /* Convert the response */
716 r->top = m_r.size / sizeof(BN_ULONG);
721 /* FIXME: When this error is returned, HWCryptoHook is
722 telling us that falling back to software computation
723 might be a good thing. */
724 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
726 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
730 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FAILED);
732 ERR_add_error_data(1,rmsg.buf);
741 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
744 HWCryptoHook_ErrMsgBuf rmsg;
745 HWCryptoHook_RSAKeyHandle *hptr;
746 int to_return = 0, ret;
750 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
754 /* This provides support for nForce keys. Since that's opaque data
755 all we do is provide a handle to the proper key and let HWCryptoHook
756 take care of the rest. */
757 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx))
760 HWCryptoHook_MPI m_a, m_r;
764 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
765 ENGINE_R_MISSING_KEY_COMPONENTS);
772 /* Prepare the params */
773 bn_expand2(r, rsa->n->top); /* Check for error !! */
777 /* Perform the operation */
778 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
780 /* Convert the response */
781 r->top = m_r.size / sizeof(BN_ULONG);
786 /* FIXME: When this error is returned, HWCryptoHook is
787 telling us that falling back to software computation
788 might be a good thing. */
789 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
791 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
795 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
797 ERR_add_error_data(1,rmsg.buf);
803 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
805 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
807 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
808 ENGINE_R_MISSING_KEY_COMPONENTS);
815 /* Prepare the params */
816 bn_expand2(r, rsa->n->top); /* Check for error !! */
820 BN2MPI(m_dmp1, rsa->dmp1);
821 BN2MPI(m_dmq1, rsa->dmq1);
822 BN2MPI(m_iqmp, rsa->iqmp);
825 /* Perform the operation */
826 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
827 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
829 /* Convert the response */
830 r->top = m_r.size / sizeof(BN_ULONG);
835 /* FIXME: When this error is returned, HWCryptoHook is
836 telling us that falling back to software computation
837 might be a good thing. */
838 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
840 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
844 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
846 ERR_add_error_data(1,rmsg.buf);
850 /* If we're here, we must be here with some semblance of success :-) */
856 /* This function is aliased to mod_exp (with the mont stuff dropped). */
857 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
858 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
860 return hwcrhk_mod_exp(r, a, p, m, ctx);
863 /* This function is aliased to mod_exp (with the dh and mont dropped). */
864 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
865 const BIGNUM *a, const BIGNUM *p,
866 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
868 return hwcrhk_mod_exp(r, a, p, m, ctx);
871 /* Random bytes are good */
872 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
875 HWCryptoHook_ErrMsgBuf rmsg;
876 int to_return = 0; /* assume failure */
884 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_NOT_INITIALISED);
888 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
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_RAND_BYTES,ENGINE_R_REQUEST_FALLBACK);
900 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FAILED);
902 ERR_add_error_data(1,rmsg.buf);
910 static int hwcrhk_rand_status(void)
915 /* This cleans up an RSA KM key, called when ex_data is freed */
917 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
918 int ind,long argl, void *argp)
921 HWCryptoHook_ErrMsgBuf rmsg;
922 HWCryptoHook_RSAKeyHandle *hptr;
928 hptr = (HWCryptoHook_RSAKeyHandle *) item;
930 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
934 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
935 * these just wrap the POSIX functions and add some logging.
938 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
939 HWCryptoHook_CallerContext *cactx)
941 mt->lockid = CRYPTO_get_new_dynlockid();
947 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
949 CRYPTO_w_lock(mt->lockid);
953 void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
955 CRYPTO_w_unlock(mt->lockid);
958 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
960 CRYPTO_destroy_dynlockid(mt->lockid);
963 static int hwcrhk_get_pass(const char *prompt_info,
964 int *len_io, char *buf,
965 HWCryptoHook_PassphraseContext *ppctx,
966 HWCryptoHook_CallerContext *cactx)
971 if (password_callback == NULL)
973 ENGINEerr(ENGINE_F_HWCRHK_GET_PASS,ENGINE_R_NO_CALLBACK);
978 strncpy(prompt, "Card: \"", sizeof(prompt));
980 strncpy(prompt + l, prompt_info, sizeof(prompt) - l);
981 l += strlen(prompt_info);
982 if (l + 2 < sizeof(prompt))
984 strncpy(prompt + l, "\"\n", sizeof(prompt) - l);
988 if (l < sizeof(prompt) - 1)
990 strncpy(prompt, "Enter Passphrase <enter to cancel>:",
996 /* I know, passing on the prompt instead of the user data *is*
997 a bad thing. However, that's all we have right now.
998 -- Richard Levitte */
999 *len_io = password_callback(buf, *len_io, 0, prompt);
1005 static void hwcrhk_log_message(void *logstr, const char *message)
1007 BIO *lstream = NULL;
1009 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1011 lstream=*(BIO **)logstr;
1014 BIO_write(lstream, message, strlen(message));
1016 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1019 #endif /* !NO_HW_NCIPHER */