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(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
108 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
111 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
112 static int hwcrhk_rand_status(void);
115 static EVP_PKEY *hwcrhk_load_privkey(const char *key_id,
116 const char *passphrase);
117 static EVP_PKEY *hwcrhk_load_pubkey(const char *key_id,
118 const char *passphrase);
119 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
120 int ind,long argl, void *argp);
122 /* Interaction stuff */
123 static int hwcrhk_get_pass(const char *prompt_info,
124 int *len_io, char *buf,
125 HWCryptoHook_PassphraseContext *ppctx,
126 HWCryptoHook_CallerContext *cactx);
127 static void hwcrhk_log_message(void *logstr, const char *message);
129 /* Our internal RSA_METHOD that we provide pointers to */
130 static RSA_METHOD hwcrhk_rsa =
132 "nCipher RSA method",
147 /* Our internal DH_METHOD that we provide pointers to */
148 static DH_METHOD hwcrhk_dh =
160 static RAND_METHOD hwcrhk_rand =
162 /* "nCipher RAND method", */
171 /* Our ENGINE structure. */
172 static ENGINE engine_hwcrhk =
175 "nCipher hardware engine support",
188 0, 0, /* no references */
189 NULL, NULL /* unlinked */
192 /* Internal stuff for HWCryptoHook */
194 /* Some structures needed for proper use of thread locks */
195 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
196 into HWCryptoHook_Mutex */
197 struct HWCryptoHook_MutexValue
202 /* hwcryptohook.h has some typedefs that turn
203 struct HWCryptoHook_PassphraseContextValue
204 into HWCryptoHook_PassphraseContext */
205 struct HWCryptoHook_PassphraseContextValue
210 /* hwcryptohook.h has some typedefs that turn
211 struct HWCryptoHook_CallerContextValue
212 into HWCryptoHook_CallerContext */
213 struct HWCryptoHook_CallerContextValue
218 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
219 BIGNUM's, so lets define a couple of conversion macros */
220 #define BN2MPI(mp, bn) \
221 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
222 #define MPI2BN(bn, mp) \
223 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
225 #if 0 /* Card and password management is not yet supported */
226 /* HWCryptoHook callbacks. insert_card() and get_pass() are not yet
227 defined, because we haven't quite decided on the proper form yet.
228 log_message() just adds an entry in the error stack. I don't know
229 if that's good or bad... */
230 static int insert_card(const char *prompt_info,
231 const char *wrong_info,
232 HWCryptoHook_PassphraseContext *ppctx,
233 HWCryptoHook_CallerContext *cactx);
234 static int get_pass(const char *prompt_info,
235 int *len_io, char *buf,
236 HWCryptoHook_PassphraseContext *ppctx,
237 HWCryptoHook_CallerContext *cactx);
240 static BIO *logstream = NULL;
241 static pem_password_cb *password_callback = NULL;
243 static void *password_callback_userdata = NULL;
245 static int disable_mutex_callbacks = 0;
247 /* Stuff to pass to the HWCryptoHook library */
248 static HWCryptoHook_InitInfo hwcrhk_globals = {
250 &logstream, /* logstream */
251 sizeof(BN_ULONG), /* limbsize */
252 0, /* mslimb first: false for BNs */
253 -1, /* msbyte first: use native */
254 0, /* Max mutexes, 0 = no small limit */
255 0, /* Max simultaneous, 0 = default */
257 /* The next few are mutex stuff: we write wrapper functions
258 around the OS mutex functions. We initialise them to 0
259 here, and change that to actual function pointers in hwcrhk_init()
260 if dynamic locks are supported (that is, if the application
261 programmer has made sure of setting up callbacks bafore starting
262 this engine) *and* if disable_mutex_callbacks hasn't been set by
263 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
264 sizeof(HWCryptoHook_Mutex),
270 /* The next few are condvar stuff: we write wrapper functions
271 round the OS functions. Currently not implemented and not
272 and absolute necessity even in threaded programs, therefore
273 0'ed. Will hopefully be implemented some day, since it
274 enhances the efficiency of HWCryptoHook. */
275 0, /* sizeof(HWCryptoHook_CondVar), */
276 0, /* hwcrhk_cv_init, */
277 0, /* hwcrhk_cv_wait, */
278 0, /* hwcrhk_cv_signal, */
279 0, /* hwcrhk_cv_broadcast, */
280 0, /* hwcrhk_cv_destroy, */
282 hwcrhk_get_pass, /* pass phrase */
283 0, /* insert_card, */ /* insert a card */
284 hwcrhk_log_message /* Log message */
288 /* Now, to our own code */
290 /* As this is only ever called once, there's no need for locking
291 * (indeed - the lock will already be held by our caller!!!) */
292 ENGINE *ENGINE_ncipher()
297 /* We know that the "PKCS1_SSLeay()" functions hook properly
298 * to the cswift-specific mod_exp and mod_exp_crt so we use
299 * those functions. NB: We don't use ENGINE_openssl() or
300 * anything "more generic" because something like the RSAref
301 * code may not hook properly, and if you own one of these
302 * cards then you have the right to do RSA operations on it
304 meth1 = RSA_PKCS1_SSLeay();
305 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
306 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
307 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
308 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
310 /* Much the same for Diffie-Hellman */
311 meth2 = DH_OpenSSL();
312 hwcrhk_dh.generate_key = meth2->generate_key;
313 hwcrhk_dh.compute_key = meth2->compute_key;
314 return &engine_hwcrhk;
317 /* This is a process-global DSO handle used for loading and unloading
318 * the HWCryptoHook library. NB: This is only set (or unset) during an
319 * init() or finish() call (reference counts permitting) and they're
320 * operating with global locks, so this should be thread-safe
322 static DSO *hwcrhk_dso = NULL;
323 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
324 static int hndidx = -1; /* Index for KM handle. Not really used yet. */
326 /* These are the function pointers that are (un)set when the library has
327 * successfully (un)loaded. */
328 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
329 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
330 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
331 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
332 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
333 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
334 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
335 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
336 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
338 /* Used in the DSO operations. */
339 static const char *HWCRHK_LIBNAME = "nfhwcrhk";
340 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
341 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
342 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
343 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
344 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
345 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
346 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
347 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
348 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
350 /* HWCryptoHook library functions and mechanics - these are used by the
351 * higher-level functions further down. NB: As and where there's no
352 * error checking, take a look lower down where these functions are
353 * called, the checking and error handling is probably down there. */
355 /* utility function to obtain a context */
356 static int get_context(HWCryptoHook_ContextHandle *hac)
359 HWCryptoHook_ErrMsgBuf rmsg;
364 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
371 /* similarly to release one. */
372 static void release_context(HWCryptoHook_ContextHandle hac)
374 p_hwcrhk_Finish(hac);
377 /* (de)initialisation functions. */
378 static int hwcrhk_init()
380 HWCryptoHook_Init_t *p1;
381 HWCryptoHook_Finish_t *p2;
382 HWCryptoHook_ModExp_t *p3;
383 HWCryptoHook_RSA_t *p4;
384 HWCryptoHook_RSALoadKey_t *p5;
385 HWCryptoHook_RSAGetPublicKey_t *p6;
386 HWCryptoHook_RSAUnloadKey_t *p7;
387 HWCryptoHook_RandomBytes_t *p8;
388 HWCryptoHook_ModExpCRT_t *p9;
390 if(hwcrhk_dso != NULL)
392 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_ALREADY_LOADED);
395 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
396 hwcrhk_dso = DSO_load(NULL, HWCRHK_LIBNAME, NULL, 0);
397 if(hwcrhk_dso == NULL)
399 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
402 if(!(p1 = (HWCryptoHook_Init_t *)
403 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
404 !(p2 = (HWCryptoHook_Finish_t *)
405 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
406 !(p3 = (HWCryptoHook_ModExp_t *)
407 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
408 !(p4 = (HWCryptoHook_RSA_t *)
409 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
410 !(p5 = (HWCryptoHook_RSALoadKey_t *)
411 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
412 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
413 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
414 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
415 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
416 !(p8 = (HWCryptoHook_RandomBytes_t *)
417 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
418 !(p9 = (HWCryptoHook_ModExpCRT_t *)
419 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
421 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
424 /* Copy the pointers */
426 p_hwcrhk_Finish = p2;
427 p_hwcrhk_ModExp = p3;
429 p_hwcrhk_RSALoadKey = p5;
430 p_hwcrhk_RSAGetPublicKey = p6;
431 p_hwcrhk_RSAUnloadKey = p7;
432 p_hwcrhk_RandomBytes = p8;
433 p_hwcrhk_ModExpCRT = p9;
435 /* Check if the application decided to support dynamic locks,
436 and if it does, use them. */
437 if (disable_mutex_callbacks == 0 &&
438 CRYPTO_get_dynlock_create_callback() != NULL &&
439 CRYPTO_get_dynlock_lock_callback() != NULL &&
440 CRYPTO_get_dynlock_destroy_callback() != NULL)
442 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
443 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
444 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
445 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
448 /* Try and get a context - if not, we may have a DSO but no
450 if(!get_context(&hwcrhk_context))
452 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_UNIT_FAILURE);
455 /* Everything's fine. */
457 hndidx = RSA_get_ex_new_index(0,
458 "nFast HWCryptoHook RSA key handle",
459 NULL, NULL, hwcrhk_ex_free);
463 DSO_free(hwcrhk_dso);
465 p_hwcrhk_Init = NULL;
466 p_hwcrhk_Finish = NULL;
467 p_hwcrhk_ModExp = NULL;
469 p_hwcrhk_RSALoadKey = NULL;
470 p_hwcrhk_RSAGetPublicKey = NULL;
471 p_hwcrhk_RSAUnloadKey = NULL;
472 p_hwcrhk_ModExpCRT = NULL;
473 p_hwcrhk_RandomBytes = NULL;
477 static int hwcrhk_finish()
480 if(hwcrhk_dso == NULL)
482 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_NOT_LOADED);
486 release_context(hwcrhk_context);
487 if(!DSO_free(hwcrhk_dso))
489 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_DSO_FAILURE);
497 p_hwcrhk_Init = NULL;
498 p_hwcrhk_Finish = NULL;
499 p_hwcrhk_ModExp = NULL;
501 p_hwcrhk_RSALoadKey = NULL;
502 p_hwcrhk_RSAGetPublicKey = NULL;
503 p_hwcrhk_RSAUnloadKey = NULL;
504 p_hwcrhk_ModExpCRT = NULL;
505 p_hwcrhk_RandomBytes = NULL;
509 static int hwcrhk_ctrl(int cmd, long i, void *p, void (*f)())
515 case ENGINE_CTRL_SET_LOGSTREAM:
519 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
525 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
528 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_BIO_WAS_FREED);
530 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
532 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
533 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
534 password_callback = (pem_password_cb *)f;
535 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
537 /* this enables or disables the "SimpleForkCheck" flag used in the
538 * initialisation structure. */
539 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
540 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
542 hwcrhk_globals.flags |=
543 HWCryptoHook_InitFlags_SimpleForkCheck;
545 hwcrhk_globals.flags &=
546 ~HWCryptoHook_InitFlags_SimpleForkCheck;
547 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
549 /* This will prevent the initialisation function from "installing"
550 * the mutex-handling callbacks, even if they are available from
551 * within the library (or were provided to the library from the
552 * calling application). This is to remove any baggage for
553 * applications not using multithreading. */
554 case ENGINE_CTRL_CHIL_NO_LOCKING:
555 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
556 disable_mutex_callbacks = 1;
557 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
560 /* The command isn't understood by this engine */
562 ENGINEerr(ENGINE_F_HWCRHK_CTRL,
563 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
571 static EVP_PKEY *hwcrhk_load_privkey(const char *key_id,
572 const char *passphrase)
575 EVP_PKEY *res = NULL;
576 HWCryptoHook_MPI e, n;
577 HWCryptoHook_RSAKeyHandle *hptr;
578 HWCryptoHook_ErrMsgBuf rmsg;
582 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
583 ENGINE_R_NOT_INITIALISED);
586 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
589 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
590 ERR_R_MALLOC_FAILURE);
593 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
596 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
597 ENGINE_R_CHIL_ERROR);
598 ERR_add_error_data(1,rmsg.buf);
603 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
607 rtmp = RSA_new_method(&engine_hwcrhk);
608 RSA_set_ex_data(rtmp, hndidx, (char *)hptr);
611 rtmp->flags |= RSA_FLAG_EXT_PKEY;
614 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
615 != HWCRYPTOHOOK_ERROR_MPISIZE)
617 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,ENGINE_R_CHIL_ERROR);
618 ERR_add_error_data(1,rmsg.buf);
622 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
623 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
627 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
629 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
630 ENGINE_R_CHIL_ERROR);
631 ERR_add_error_data(1,rmsg.buf);
634 rtmp->e->top = e.size / sizeof(BN_ULONG);
636 rtmp->n->top = n.size / sizeof(BN_ULONG);
639 res = EVP_PKEY_new();
640 EVP_PKEY_assign_RSA(res, rtmp);
651 static EVP_PKEY *hwcrhk_load_pubkey(const char *key_id, const char *passphrase)
653 EVP_PKEY *res = hwcrhk_load_privkey(key_id, passphrase);
662 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
664 res->pkey.rsa = RSA_new();
665 res->pkey.rsa->n = rsa->n;
666 res->pkey.rsa->e = rsa->e;
667 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
671 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
672 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
683 /* A little mod_exp */
684 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
685 const BIGNUM *m, BN_CTX *ctx)
688 HWCryptoHook_ErrMsgBuf rmsg;
689 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
690 we use them directly, plus a little macro magic. We only
691 thing we need to make sure of is that enough space is allocated. */
692 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
695 to_return = 0; /* expect failure */
701 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
704 /* Prepare the params */
705 bn_expand2(r, m->top); /* Check for error !! */
711 /* Perform the operation */
712 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
714 /* Convert the response */
715 r->top = m_r.size / sizeof(BN_ULONG);
720 /* FIXME: When this error is returned, HWCryptoHook is
721 telling us that falling back to software computation
722 might be a good thing. */
723 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
725 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
729 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FAILED);
731 ERR_add_error_data(1,rmsg.buf);
740 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
743 HWCryptoHook_ErrMsgBuf rmsg;
744 HWCryptoHook_RSAKeyHandle *hptr;
745 int to_return = 0, ret;
749 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
753 /* This provides support for nForce keys. Since that's opaque data
754 all we do is provide a handle to the proper key and let HWCryptoHook
755 take care of the rest. */
756 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx))
759 HWCryptoHook_MPI m_a, m_r;
763 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
764 ENGINE_R_MISSING_KEY_COMPONENTS);
771 /* Prepare the params */
772 bn_expand2(r, rsa->n->top); /* Check for error !! */
776 /* Perform the operation */
777 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
779 /* Convert the response */
780 r->top = m_r.size / sizeof(BN_ULONG);
785 /* FIXME: When this error is returned, HWCryptoHook is
786 telling us that falling back to software computation
787 might be a good thing. */
788 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
790 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
794 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
796 ERR_add_error_data(1,rmsg.buf);
802 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
804 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
806 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
807 ENGINE_R_MISSING_KEY_COMPONENTS);
814 /* Prepare the params */
815 bn_expand2(r, rsa->n->top); /* Check for error !! */
819 BN2MPI(m_dmp1, rsa->dmp1);
820 BN2MPI(m_dmq1, rsa->dmq1);
821 BN2MPI(m_iqmp, rsa->iqmp);
824 /* Perform the operation */
825 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
826 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
828 /* Convert the response */
829 r->top = m_r.size / sizeof(BN_ULONG);
834 /* FIXME: When this error is returned, HWCryptoHook is
835 telling us that falling back to software computation
836 might be a good thing. */
837 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
839 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
843 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
845 ERR_add_error_data(1,rmsg.buf);
849 /* If we're here, we must be here with some semblance of success :-) */
855 /* This function is aliased to mod_exp (with the mont stuff dropped). */
856 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
857 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
859 return hwcrhk_mod_exp(r, a, p, m, ctx);
862 /* This function is aliased to mod_exp (with the dh and mont dropped). */
863 static int hwcrhk_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
864 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
866 return hwcrhk_mod_exp(r, a, p, m, ctx);
869 /* Random bytes are good */
870 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
873 HWCryptoHook_ErrMsgBuf rmsg;
874 int to_return = 0; /* assume failure */
882 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_NOT_INITIALISED);
886 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
889 /* FIXME: When this error is returned, HWCryptoHook is
890 telling us that falling back to software computation
891 might be a good thing. */
892 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
894 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FALLBACK);
898 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FAILED);
900 ERR_add_error_data(1,rmsg.buf);
908 static int hwcrhk_rand_status(void)
913 /* This cleans up an RSA KM key, called when ex_data is freed */
915 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
916 int ind,long argl, void *argp)
919 HWCryptoHook_ErrMsgBuf rmsg;
920 HWCryptoHook_RSAKeyHandle *hptr;
926 hptr = (HWCryptoHook_RSAKeyHandle *) item;
928 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
932 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
933 * these just wrap the POSIX functions and add some logging.
936 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
937 HWCryptoHook_CallerContext *cactx)
939 mt->lockid = CRYPTO_get_new_dynlockid();
945 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
947 CRYPTO_w_lock(mt->lockid);
951 void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
953 CRYPTO_w_unlock(mt->lockid);
956 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
958 CRYPTO_destroy_dynlockid(mt->lockid);
961 static int hwcrhk_get_pass(const char *prompt_info,
962 int *len_io, char *buf,
963 HWCryptoHook_PassphraseContext *ppctx,
964 HWCryptoHook_CallerContext *cactx)
969 if (password_callback == NULL)
971 ENGINEerr(ENGINE_F_HWCRHK_GET_PASS,ENGINE_R_NO_CALLBACK);
976 strncpy(prompt, "Card: \"", sizeof(prompt));
978 strncpy(prompt + l, prompt_info, sizeof(prompt) - l);
979 l += strlen(prompt_info);
980 if (l + 2 < sizeof(prompt))
982 strncpy(prompt + l, "\"\n", sizeof(prompt) - l);
986 if (l < sizeof(prompt) - 1)
988 strncpy(prompt, "Enter Passphrase <enter to cancel>:",
994 /* I know, passing on the prompt instead of the user data *is*
995 a bad thing. However, that's all we have right now.
996 -- Richard Levitte */
997 *len_io = password_callback(buf, *len_io, 0, prompt);
1003 static void hwcrhk_log_message(void *logstr, const char *message)
1005 BIO *lstream = NULL;
1007 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1009 lstream=*(BIO **)logstr;
1012 BIO_write(lstream, message, strlen(message));
1014 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1017 #endif /* !NO_HW_NCIPHER */