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);
99 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa);
100 /* This function is aliased to mod_exp (with the mont stuff dropped). */
101 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
102 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
105 /* This function is alised to mod_exp (with the DH and mont dropped). */
106 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
107 const 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(ENGINE *eng, const char *key_id,
116 const char *passphrase);
117 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, 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 /* The definitions for control commands specific to this engine */
130 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
131 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
132 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
133 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
136 "Specifies the path to the 'hwcrhk' shared library",
137 ENGINE_CMD_FLAG_STRING},
138 {HWCRHK_CMD_FORK_CHECK,
140 "Turns fork() checking on or off (boolean)",
141 ENGINE_CMD_FLAG_NUMERIC},
142 {HWCRHK_CMD_THREAD_LOCKING,
144 "Turns thread-safe locking on or off (boolean)",
145 ENGINE_CMD_FLAG_NUMERIC},
149 /* Our internal RSA_METHOD that we provide pointers to */
150 static RSA_METHOD hwcrhk_rsa =
152 "nCipher RSA method",
167 /* Our internal DH_METHOD that we provide pointers to */
168 static DH_METHOD hwcrhk_dh =
180 static RAND_METHOD hwcrhk_rand =
182 /* "nCipher RAND method", */
191 /* Constants used when creating the ENGINE */
192 static const char *engine_hwcrhk_id = "chil";
193 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
195 /* Internal stuff for HWCryptoHook */
197 /* Some structures needed for proper use of thread locks */
198 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
199 into HWCryptoHook_Mutex */
200 struct HWCryptoHook_MutexValue
205 /* hwcryptohook.h has some typedefs that turn
206 struct HWCryptoHook_PassphraseContextValue
207 into HWCryptoHook_PassphraseContext */
208 struct HWCryptoHook_PassphraseContextValue
213 /* hwcryptohook.h has some typedefs that turn
214 struct HWCryptoHook_CallerContextValue
215 into HWCryptoHook_CallerContext */
216 struct HWCryptoHook_CallerContextValue
221 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
222 BIGNUM's, so lets define a couple of conversion macros */
223 #define BN2MPI(mp, bn) \
224 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
225 #define MPI2BN(bn, mp) \
226 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
228 #if 0 /* Card and password management is not yet supported */
229 /* HWCryptoHook callbacks. insert_card() and get_pass() are not yet
230 defined, because we haven't quite decided on the proper form yet.
231 log_message() just adds an entry in the error stack. I don't know
232 if that's good or bad... */
233 static int insert_card(const char *prompt_info,
234 const char *wrong_info,
235 HWCryptoHook_PassphraseContext *ppctx,
236 HWCryptoHook_CallerContext *cactx);
237 static int get_pass(const char *prompt_info,
238 int *len_io, char *buf,
239 HWCryptoHook_PassphraseContext *ppctx,
240 HWCryptoHook_CallerContext *cactx);
243 static BIO *logstream = NULL;
244 static pem_password_cb *password_callback = NULL;
246 static void *password_callback_userdata = NULL;
248 static int disable_mutex_callbacks = 0;
250 /* Stuff to pass to the HWCryptoHook library */
251 static HWCryptoHook_InitInfo hwcrhk_globals = {
253 &logstream, /* logstream */
254 sizeof(BN_ULONG), /* limbsize */
255 0, /* mslimb first: false for BNs */
256 -1, /* msbyte first: use native */
257 0, /* Max mutexes, 0 = no small limit */
258 0, /* Max simultaneous, 0 = default */
260 /* The next few are mutex stuff: we write wrapper functions
261 around the OS mutex functions. We initialise them to 0
262 here, and change that to actual function pointers in hwcrhk_init()
263 if dynamic locks are supported (that is, if the application
264 programmer has made sure of setting up callbacks bafore starting
265 this engine) *and* if disable_mutex_callbacks hasn't been set by
266 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
267 sizeof(HWCryptoHook_Mutex),
273 /* The next few are condvar stuff: we write wrapper functions
274 round the OS functions. Currently not implemented and not
275 and absolute necessity even in threaded programs, therefore
276 0'ed. Will hopefully be implemented some day, since it
277 enhances the efficiency of HWCryptoHook. */
278 0, /* sizeof(HWCryptoHook_CondVar), */
279 0, /* hwcrhk_cv_init, */
280 0, /* hwcrhk_cv_wait, */
281 0, /* hwcrhk_cv_signal, */
282 0, /* hwcrhk_cv_broadcast, */
283 0, /* hwcrhk_cv_destroy, */
285 hwcrhk_get_pass, /* pass phrase */
286 0, /* insert_card, */ /* insert a card */
287 hwcrhk_log_message /* Log message */
291 /* Now, to our own code */
293 /* As this is only ever called once, there's no need for locking
294 * (indeed - the lock will already be held by our caller!!!) */
295 ENGINE *ENGINE_ncipher()
297 const RSA_METHOD *meth1;
298 const DH_METHOD *meth2;
299 ENGINE *ret = ENGINE_new();
302 if(!ENGINE_set_id(ret, engine_hwcrhk_id) ||
303 !ENGINE_set_name(ret, engine_hwcrhk_name) ||
304 !ENGINE_set_RSA(ret, &hwcrhk_rsa) ||
305 !ENGINE_set_DH(ret, &hwcrhk_dh) ||
306 !ENGINE_set_RAND(ret, &hwcrhk_rand) ||
307 !ENGINE_set_BN_mod_exp(ret, hwcrhk_mod_exp) ||
308 !ENGINE_set_init_function(ret, hwcrhk_init) ||
309 !ENGINE_set_finish_function(ret, hwcrhk_finish) ||
310 !ENGINE_set_ctrl_function(ret, hwcrhk_ctrl) ||
311 !ENGINE_set_load_privkey_function(ret, hwcrhk_load_privkey) ||
312 !ENGINE_set_load_pubkey_function(ret, hwcrhk_load_pubkey) ||
313 !ENGINE_set_cmd_defns(ret, hwcrhk_cmd_defns))
319 /* We know that the "PKCS1_SSLeay()" functions hook properly
320 * to the cswift-specific mod_exp and mod_exp_crt so we use
321 * those functions. NB: We don't use ENGINE_openssl() or
322 * anything "more generic" because something like the RSAref
323 * code may not hook properly, and if you own one of these
324 * cards then you have the right to do RSA operations on it
326 meth1 = RSA_PKCS1_SSLeay();
327 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
328 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
329 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
330 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
332 /* Much the same for Diffie-Hellman */
333 meth2 = DH_OpenSSL();
334 hwcrhk_dh.generate_key = meth2->generate_key;
335 hwcrhk_dh.compute_key = meth2->compute_key;
339 /* This is a process-global DSO handle used for loading and unloading
340 * the HWCryptoHook library. NB: This is only set (or unset) during an
341 * init() or finish() call (reference counts permitting) and they're
342 * operating with global locks, so this should be thread-safe
344 static DSO *hwcrhk_dso = NULL;
345 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
346 static int hndidx = -1; /* Index for KM handle. Not really used yet. */
348 /* These are the function pointers that are (un)set when the library has
349 * successfully (un)loaded. */
350 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
351 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
352 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
353 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
354 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
355 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
356 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
357 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
358 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
360 /* Used in the DSO operations. */
361 static const char def_HWCRHK_LIBNAME[] = "nfhwcrhk";
362 static const char *HWCRHK_LIBNAME = def_HWCRHK_LIBNAME;
363 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
364 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
365 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
366 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
367 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
368 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
369 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
370 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
371 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
373 /* HWCryptoHook library functions and mechanics - these are used by the
374 * higher-level functions further down. NB: As and where there's no
375 * error checking, take a look lower down where these functions are
376 * called, the checking and error handling is probably down there. */
378 /* utility function to obtain a context */
379 static int get_context(HWCryptoHook_ContextHandle *hac)
382 HWCryptoHook_ErrMsgBuf rmsg;
387 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
394 /* similarly to release one. */
395 static void release_context(HWCryptoHook_ContextHandle hac)
397 p_hwcrhk_Finish(hac);
400 /* (de)initialisation functions. */
401 static int hwcrhk_init(ENGINE *e)
403 HWCryptoHook_Init_t *p1;
404 HWCryptoHook_Finish_t *p2;
405 HWCryptoHook_ModExp_t *p3;
406 HWCryptoHook_RSA_t *p4;
407 HWCryptoHook_RSALoadKey_t *p5;
408 HWCryptoHook_RSAGetPublicKey_t *p6;
409 HWCryptoHook_RSAUnloadKey_t *p7;
410 HWCryptoHook_RandomBytes_t *p8;
411 HWCryptoHook_ModExpCRT_t *p9;
413 if(hwcrhk_dso != NULL)
415 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_ALREADY_LOADED);
418 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
419 hwcrhk_dso = DSO_load(NULL, HWCRHK_LIBNAME, NULL, 0);
420 if(hwcrhk_dso == NULL)
422 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
425 if(!(p1 = (HWCryptoHook_Init_t *)
426 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
427 !(p2 = (HWCryptoHook_Finish_t *)
428 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
429 !(p3 = (HWCryptoHook_ModExp_t *)
430 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
431 !(p4 = (HWCryptoHook_RSA_t *)
432 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
433 !(p5 = (HWCryptoHook_RSALoadKey_t *)
434 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
435 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
436 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
437 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
438 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
439 !(p8 = (HWCryptoHook_RandomBytes_t *)
440 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
441 !(p9 = (HWCryptoHook_ModExpCRT_t *)
442 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
444 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
447 /* Copy the pointers */
449 p_hwcrhk_Finish = p2;
450 p_hwcrhk_ModExp = p3;
452 p_hwcrhk_RSALoadKey = p5;
453 p_hwcrhk_RSAGetPublicKey = p6;
454 p_hwcrhk_RSAUnloadKey = p7;
455 p_hwcrhk_RandomBytes = p8;
456 p_hwcrhk_ModExpCRT = p9;
458 /* Check if the application decided to support dynamic locks,
459 and if it does, use them. */
460 if (disable_mutex_callbacks == 0 &&
461 CRYPTO_get_dynlock_create_callback() != NULL &&
462 CRYPTO_get_dynlock_lock_callback() != NULL &&
463 CRYPTO_get_dynlock_destroy_callback() != NULL)
465 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
466 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
467 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
468 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
471 /* Try and get a context - if not, we may have a DSO but no
473 if(!get_context(&hwcrhk_context))
475 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_UNIT_FAILURE);
478 /* Everything's fine. */
480 hndidx = RSA_get_ex_new_index(0,
481 "nFast HWCryptoHook RSA key handle",
482 NULL, NULL, hwcrhk_ex_free);
486 DSO_free(hwcrhk_dso);
488 p_hwcrhk_Init = NULL;
489 p_hwcrhk_Finish = NULL;
490 p_hwcrhk_ModExp = NULL;
492 p_hwcrhk_RSALoadKey = NULL;
493 p_hwcrhk_RSAGetPublicKey = NULL;
494 p_hwcrhk_RSAUnloadKey = NULL;
495 p_hwcrhk_ModExpCRT = NULL;
496 p_hwcrhk_RandomBytes = NULL;
500 static int hwcrhk_finish(ENGINE *e)
503 if(hwcrhk_dso == NULL)
505 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_NOT_LOADED);
509 release_context(hwcrhk_context);
510 if(!DSO_free(hwcrhk_dso))
512 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_DSO_FAILURE);
520 p_hwcrhk_Init = NULL;
521 p_hwcrhk_Finish = NULL;
522 p_hwcrhk_ModExp = NULL;
524 p_hwcrhk_RSALoadKey = NULL;
525 p_hwcrhk_RSAGetPublicKey = NULL;
526 p_hwcrhk_RSAUnloadKey = NULL;
527 p_hwcrhk_ModExpCRT = NULL;
528 p_hwcrhk_RandomBytes = NULL;
532 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
538 case HWCRHK_CMD_SO_PATH:
541 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_ALREADY_LOADED);
546 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
549 HWCRHK_LIBNAME = (const char *)p;
551 case ENGINE_CTRL_SET_LOGSTREAM:
555 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
561 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
564 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_BIO_WAS_FREED);
566 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
568 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
569 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
570 password_callback = (pem_password_cb *)f;
571 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
573 /* this enables or disables the "SimpleForkCheck" flag used in the
574 * initialisation structure. */
575 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
576 case HWCRHK_CMD_FORK_CHECK:
577 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
579 hwcrhk_globals.flags |=
580 HWCryptoHook_InitFlags_SimpleForkCheck;
582 hwcrhk_globals.flags &=
583 ~HWCryptoHook_InitFlags_SimpleForkCheck;
584 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
586 /* This will prevent the initialisation function from "installing"
587 * the mutex-handling callbacks, even if they are available from
588 * within the library (or were provided to the library from the
589 * calling application). This is to remove any baggage for
590 * applications not using multithreading. */
591 case ENGINE_CTRL_CHIL_NO_LOCKING:
592 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
593 disable_mutex_callbacks = 1;
594 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
596 case HWCRHK_CMD_THREAD_LOCKING:
597 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
598 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
599 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
602 /* The command isn't understood by this engine */
604 ENGINEerr(ENGINE_F_HWCRHK_CTRL,
605 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
613 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
614 const char *passphrase)
617 EVP_PKEY *res = NULL;
618 HWCryptoHook_MPI e, n;
619 HWCryptoHook_RSAKeyHandle *hptr;
620 HWCryptoHook_ErrMsgBuf rmsg;
624 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
625 ENGINE_R_NOT_INITIALISED);
628 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
631 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
632 ERR_R_MALLOC_FAILURE);
635 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
638 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
639 ENGINE_R_CHIL_ERROR);
640 ERR_add_error_data(1,rmsg.buf);
645 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
649 rtmp = RSA_new_method(eng);
650 RSA_set_ex_data(rtmp, hndidx, (char *)hptr);
653 rtmp->flags |= RSA_FLAG_EXT_PKEY;
656 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
657 != HWCRYPTOHOOK_ERROR_MPISIZE)
659 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,ENGINE_R_CHIL_ERROR);
660 ERR_add_error_data(1,rmsg.buf);
664 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
665 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
669 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
671 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
672 ENGINE_R_CHIL_ERROR);
673 ERR_add_error_data(1,rmsg.buf);
676 rtmp->e->top = e.size / sizeof(BN_ULONG);
678 rtmp->n->top = n.size / sizeof(BN_ULONG);
681 res = EVP_PKEY_new();
682 EVP_PKEY_assign_RSA(res, rtmp);
693 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
694 const char *passphrase)
696 EVP_PKEY *res = hwcrhk_load_privkey(eng, key_id, passphrase);
705 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
707 res->pkey.rsa = RSA_new();
708 res->pkey.rsa->n = rsa->n;
709 res->pkey.rsa->e = rsa->e;
710 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
714 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
715 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
726 /* A little mod_exp */
727 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
728 const BIGNUM *m, BN_CTX *ctx)
731 HWCryptoHook_ErrMsgBuf rmsg;
732 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
733 we use them directly, plus a little macro magic. We only
734 thing we need to make sure of is that enough space is allocated. */
735 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
738 to_return = 0; /* expect failure */
744 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
747 /* Prepare the params */
748 bn_expand2(r, m->top); /* Check for error !! */
754 /* Perform the operation */
755 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
757 /* Convert the response */
758 r->top = m_r.size / sizeof(BN_ULONG);
763 /* FIXME: When this error is returned, HWCryptoHook is
764 telling us that falling back to software computation
765 might be a good thing. */
766 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
768 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
772 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FAILED);
774 ERR_add_error_data(1,rmsg.buf);
783 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
786 HWCryptoHook_ErrMsgBuf rmsg;
787 HWCryptoHook_RSAKeyHandle *hptr;
788 int to_return = 0, ret;
792 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
796 /* This provides support for nForce keys. Since that's opaque data
797 all we do is provide a handle to the proper key and let HWCryptoHook
798 take care of the rest. */
799 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx))
802 HWCryptoHook_MPI m_a, m_r;
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 /* Perform the operation */
820 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
822 /* Convert the response */
823 r->top = m_r.size / sizeof(BN_ULONG);
828 /* FIXME: When this error is returned, HWCryptoHook is
829 telling us that falling back to software computation
830 might be a good thing. */
831 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
833 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
837 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
839 ERR_add_error_data(1,rmsg.buf);
845 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
847 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
849 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
850 ENGINE_R_MISSING_KEY_COMPONENTS);
857 /* Prepare the params */
858 bn_expand2(r, rsa->n->top); /* Check for error !! */
862 BN2MPI(m_dmp1, rsa->dmp1);
863 BN2MPI(m_dmq1, rsa->dmq1);
864 BN2MPI(m_iqmp, rsa->iqmp);
867 /* Perform the operation */
868 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
869 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
871 /* Convert the response */
872 r->top = m_r.size / sizeof(BN_ULONG);
877 /* FIXME: When this error is returned, HWCryptoHook is
878 telling us that falling back to software computation
879 might be a good thing. */
880 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
882 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
886 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
888 ERR_add_error_data(1,rmsg.buf);
892 /* If we're here, we must be here with some semblance of success :-) */
898 /* This function is aliased to mod_exp (with the mont stuff dropped). */
899 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
900 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
902 return hwcrhk_mod_exp(r, a, p, m, ctx);
905 /* This function is aliased to mod_exp (with the dh and mont dropped). */
906 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
907 const BIGNUM *a, const BIGNUM *p,
908 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
910 return hwcrhk_mod_exp(r, a, p, m, ctx);
913 /* Random bytes are good */
914 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
917 HWCryptoHook_ErrMsgBuf rmsg;
918 int to_return = 0; /* assume failure */
926 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_NOT_INITIALISED);
930 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
933 /* FIXME: When this error is returned, HWCryptoHook is
934 telling us that falling back to software computation
935 might be a good thing. */
936 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
938 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FALLBACK);
942 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FAILED);
944 ERR_add_error_data(1,rmsg.buf);
952 static int hwcrhk_rand_status(void)
957 /* This cleans up an RSA KM key, called when ex_data is freed */
959 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
960 int ind,long argl, void *argp)
963 HWCryptoHook_ErrMsgBuf rmsg;
964 HWCryptoHook_RSAKeyHandle *hptr;
970 hptr = (HWCryptoHook_RSAKeyHandle *) item;
972 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
976 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
977 * these just wrap the POSIX functions and add some logging.
980 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
981 HWCryptoHook_CallerContext *cactx)
983 mt->lockid = CRYPTO_get_new_dynlockid();
989 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
991 CRYPTO_w_lock(mt->lockid);
995 void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
997 CRYPTO_w_unlock(mt->lockid);
1000 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1002 CRYPTO_destroy_dynlockid(mt->lockid);
1005 static int hwcrhk_get_pass(const char *prompt_info,
1006 int *len_io, char *buf,
1007 HWCryptoHook_PassphraseContext *ppctx,
1008 HWCryptoHook_CallerContext *cactx)
1013 if (password_callback == NULL)
1015 ENGINEerr(ENGINE_F_HWCRHK_GET_PASS,ENGINE_R_NO_CALLBACK);
1020 strncpy(prompt, "Card: \"", sizeof(prompt));
1022 strncpy(prompt + l, prompt_info, sizeof(prompt) - l);
1023 l += strlen(prompt_info);
1024 if (l + 2 < sizeof(prompt))
1026 strncpy(prompt + l, "\"\n", sizeof(prompt) - l);
1030 if (l < sizeof(prompt) - 1)
1032 strncpy(prompt, "Enter Passphrase <enter to cancel>:",
1033 sizeof(prompt) - l);
1038 /* I know, passing on the prompt instead of the user data *is*
1039 a bad thing. However, that's all we have right now.
1040 -- Richard Levitte */
1041 *len_io = password_callback(buf, *len_io, 0, prompt);
1047 static void hwcrhk_log_message(void *logstr, const char *message)
1049 BIO *lstream = NULL;
1051 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1053 lstream=*(BIO **)logstr;
1056 BIO_write(lstream, message, strlen(message));
1058 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1061 #endif /* !OPENSSL_NO_HW_NCIPHER */
1062 #endif /* !OPENSSL_NO_HW */