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-2001 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>
64 #include <openssl/dso.h>
65 #include <openssl/engine.h>
66 #include <openssl/ui.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 #define HWCRHK_LIB_NAME "hwcrhk engine"
86 #include "e_ncipher_err.c"
88 static int hwcrhk_destroy(ENGINE *e);
89 static int hwcrhk_init(ENGINE *e);
90 static int hwcrhk_finish(ENGINE *e);
91 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)());
93 /* Functions to handle mutexes */
94 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
95 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
96 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
97 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
100 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
101 const BIGNUM *m, BN_CTX *ctx);
103 #ifndef OPENSSL_NO_RSA
105 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa);
107 /* This function is aliased to mod_exp (with the mont stuff dropped). */
108 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
109 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
111 #ifndef OPENSSL_NO_DH
113 /* This function is alised to mod_exp (with the DH and mont dropped). */
114 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
115 const BIGNUM *a, const BIGNUM *p,
116 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
120 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
121 static int hwcrhk_rand_status(void);
124 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
125 UI_METHOD *ui_method, void *callback_data);
126 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
127 UI_METHOD *ui_method, void *callback_data);
128 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
129 int ind,long argl, void *argp);
131 /* Interaction stuff */
132 static int hwcrhk_insert_card(const char *prompt_info,
133 const char *wrong_info,
134 HWCryptoHook_PassphraseContext *ppctx,
135 HWCryptoHook_CallerContext *cactx);
136 static int hwcrhk_get_pass(const char *prompt_info,
137 int *len_io, char *buf,
138 HWCryptoHook_PassphraseContext *ppctx,
139 HWCryptoHook_CallerContext *cactx);
140 static void hwcrhk_log_message(void *logstr, const char *message);
142 /* The definitions for control commands specific to this engine */
143 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
144 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
145 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
146 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
147 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
148 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
151 "Specifies the path to the 'hwcrhk' shared library",
152 ENGINE_CMD_FLAG_STRING},
153 {HWCRHK_CMD_FORK_CHECK,
155 "Turns fork() checking on or off (boolean)",
156 ENGINE_CMD_FLAG_NUMERIC},
157 {HWCRHK_CMD_THREAD_LOCKING,
159 "Turns thread-safe locking on or off (boolean)",
160 ENGINE_CMD_FLAG_NUMERIC},
161 {HWCRHK_CMD_SET_USER_INTERFACE,
162 "SET_USER_INTERFACE",
163 "Set the global user interface (internal)",
164 ENGINE_CMD_FLAG_INTERNAL},
165 {HWCRHK_CMD_SET_CALLBACK_DATA,
167 "Set the global user interface extra data (internal)",
168 ENGINE_CMD_FLAG_INTERNAL},
172 #ifndef OPENSSL_NO_RSA
173 /* Our internal RSA_METHOD that we provide pointers to */
174 static RSA_METHOD hwcrhk_rsa =
176 "nCipher RSA method",
192 #ifndef OPENSSL_NO_DH
193 /* Our internal DH_METHOD that we provide pointers to */
194 static DH_METHOD hwcrhk_dh =
207 static RAND_METHOD hwcrhk_rand =
209 /* "nCipher RAND method", */
218 /* Constants used when creating the ENGINE */
219 static const char *engine_hwcrhk_id = "chil";
220 static const char *engine_hwcrhk_name = "nCipher hardware engine support";
222 /* Internal stuff for HWCryptoHook */
224 /* Some structures needed for proper use of thread locks */
225 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
226 into HWCryptoHook_Mutex */
227 struct HWCryptoHook_MutexValue
232 /* hwcryptohook.h has some typedefs that turn
233 struct HWCryptoHook_PassphraseContextValue
234 into HWCryptoHook_PassphraseContext */
235 struct HWCryptoHook_PassphraseContextValue
237 UI_METHOD *ui_method;
241 /* hwcryptohook.h has some typedefs that turn
242 struct HWCryptoHook_CallerContextValue
243 into HWCryptoHook_CallerContext */
244 struct HWCryptoHook_CallerContextValue
246 pem_password_cb *password_callback; /* Deprecated! Only present for
247 backward compatibility! */
248 UI_METHOD *ui_method;
252 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
253 BIGNUM's, so lets define a couple of conversion macros */
254 #define BN2MPI(mp, bn) \
255 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
256 #define MPI2BN(bn, mp) \
257 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
259 static BIO *logstream = NULL;
260 static int disable_mutex_callbacks = 0;
262 /* One might wonder why these are needed, since one can pass down at least
263 a UI_METHOD and a pointer to callback data to the key-loading functions.
264 The thing is that the ModExp and RSAImmed functions can load keys as well,
265 if the data they get is in a special, nCipher-defined format (hint: if you
266 look at the private exponent of the RSA data as a string, you'll see this
267 string: "nCipher KM tool key id", followed by some bytes, followed a key
268 identity string, followed by more bytes. This happens when you use "embed"
269 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
270 any passphrase or caller context, and our functions can't really take any
271 callback data either. Still, the "insert_card" and "get_passphrase"
272 callbacks may be called down the line, and will need to know what user
273 interface callbacks to call, and having callback data from the application
274 may be a nice thing as well, so we need to keep track of that globally. */
275 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
277 /* Stuff to pass to the HWCryptoHook library */
278 static HWCryptoHook_InitInfo hwcrhk_globals = {
279 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
280 &logstream, /* logstream */
281 sizeof(BN_ULONG), /* limbsize */
282 0, /* mslimb first: false for BNs */
283 -1, /* msbyte first: use native */
284 0, /* Max mutexes, 0 = no small limit */
285 0, /* Max simultaneous, 0 = default */
287 /* The next few are mutex stuff: we write wrapper functions
288 around the OS mutex functions. We initialise them to 0
289 here, and change that to actual function pointers in hwcrhk_init()
290 if dynamic locks are supported (that is, if the application
291 programmer has made sure of setting up callbacks bafore starting
292 this engine) *and* if disable_mutex_callbacks hasn't been set by
293 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
294 sizeof(HWCryptoHook_Mutex),
300 /* The next few are condvar stuff: we write wrapper functions
301 round the OS functions. Currently not implemented and not
302 and absolute necessity even in threaded programs, therefore
303 0'ed. Will hopefully be implemented some day, since it
304 enhances the efficiency of HWCryptoHook. */
305 0, /* sizeof(HWCryptoHook_CondVar), */
306 0, /* hwcrhk_cv_init, */
307 0, /* hwcrhk_cv_wait, */
308 0, /* hwcrhk_cv_signal, */
309 0, /* hwcrhk_cv_broadcast, */
310 0, /* hwcrhk_cv_destroy, */
312 hwcrhk_get_pass, /* pass phrase */
313 hwcrhk_insert_card, /* insert a card */
314 hwcrhk_log_message /* Log message */
318 /* Now, to our own code */
320 /* This internal function is used by ENGINE_ncipher() and possibly by the
321 * "dynamic" ENGINE support too */
322 static int bind_helper(ENGINE *e)
324 #ifndef OPENSSL_NO_RSA
325 const RSA_METHOD *meth1;
327 #ifndef OPENSSL_NO_DH
328 const DH_METHOD *meth2;
330 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
331 !ENGINE_set_name(e, engine_hwcrhk_name) ||
332 #ifndef OPENSSL_NO_RSA
333 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
335 #ifndef OPENSSL_NO_DH
336 !ENGINE_set_DH(e, &hwcrhk_dh) ||
338 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
339 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
340 !ENGINE_set_init_function(e, hwcrhk_init) ||
341 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
342 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
343 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
344 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
345 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
348 #ifndef OPENSSL_NO_RSA
349 /* We know that the "PKCS1_SSLeay()" functions hook properly
350 * to the cswift-specific mod_exp and mod_exp_crt so we use
351 * those functions. NB: We don't use ENGINE_openssl() or
352 * anything "more generic" because something like the RSAref
353 * code may not hook properly, and if you own one of these
354 * cards then you have the right to do RSA operations on it
356 meth1 = RSA_PKCS1_SSLeay();
357 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
358 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
359 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
360 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
363 #ifndef OPENSSL_NO_DH
364 /* Much the same for Diffie-Hellman */
365 meth2 = DH_OpenSSL();
366 hwcrhk_dh.generate_key = meth2->generate_key;
367 hwcrhk_dh.compute_key = meth2->compute_key;
370 /* Ensure the hwcrhk error handling is set up */
371 ERR_load_HWCRHK_strings();
375 static ENGINE *engine_ncipher(void)
377 ENGINE *ret = ENGINE_new();
380 if(!bind_helper(ret))
388 void ENGINE_load_chil(void)
390 /* Copied from eng_[openssl|dyn].c */
391 ENGINE *toadd = engine_ncipher();
398 /* This is a process-global DSO handle used for loading and unloading
399 * the HWCryptoHook library. NB: This is only set (or unset) during an
400 * init() or finish() call (reference counts permitting) and they're
401 * operating with global locks, so this should be thread-safe
403 static DSO *hwcrhk_dso = NULL;
404 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
405 #ifndef OPENSSL_NO_RSA
406 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
409 /* These are the function pointers that are (un)set when the library has
410 * successfully (un)loaded. */
411 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
412 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
413 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
414 #ifndef OPENSSL_NO_RSA
415 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
417 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
418 #ifndef OPENSSL_NO_RSA
419 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
420 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
421 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
423 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
425 /* Used in the DSO operations. */
426 static const char *HWCRHK_LIBNAME = NULL;
427 static void free_HWCRHK_LIBNAME(void)
430 OPENSSL_free((void*)HWCRHK_LIBNAME);
431 HWCRHK_LIBNAME = NULL;
433 static const char *get_HWCRHK_LIBNAME(void)
436 return HWCRHK_LIBNAME;
439 static long set_HWCRHK_LIBNAME(const char *name)
441 free_HWCRHK_LIBNAME();
442 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
444 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
445 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
446 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
447 #ifndef OPENSSL_NO_RSA
448 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
450 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
451 #ifndef OPENSSL_NO_RSA
452 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
453 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
454 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
456 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
458 /* HWCryptoHook library functions and mechanics - these are used by the
459 * higher-level functions further down. NB: As and where there's no
460 * error checking, take a look lower down where these functions are
461 * called, the checking and error handling is probably down there. */
463 /* utility function to obtain a context */
464 static int get_context(HWCryptoHook_ContextHandle *hac,
465 HWCryptoHook_CallerContext *cac)
468 HWCryptoHook_ErrMsgBuf rmsg;
471 rmsg.size = sizeof(tempbuf);
473 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
480 /* similarly to release one. */
481 static void release_context(HWCryptoHook_ContextHandle hac)
483 p_hwcrhk_Finish(hac);
486 /* Destructor (complements the "ENGINE_ncipher()" constructor) */
487 static int hwcrhk_destroy(ENGINE *e)
489 free_HWCRHK_LIBNAME();
490 ERR_unload_HWCRHK_strings();
494 /* (de)initialisation functions. */
495 static int hwcrhk_init(ENGINE *e)
497 HWCryptoHook_Init_t *p1;
498 HWCryptoHook_Finish_t *p2;
499 HWCryptoHook_ModExp_t *p3;
500 #ifndef OPENSSL_NO_RSA
501 HWCryptoHook_RSA_t *p4;
502 HWCryptoHook_RSALoadKey_t *p5;
503 HWCryptoHook_RSAGetPublicKey_t *p6;
504 HWCryptoHook_RSAUnloadKey_t *p7;
506 HWCryptoHook_RandomBytes_t *p8;
507 HWCryptoHook_ModExpCRT_t *p9;
509 if(hwcrhk_dso != NULL)
511 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
514 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
515 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
516 if(hwcrhk_dso == NULL)
518 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
521 if(!(p1 = (HWCryptoHook_Init_t *)
522 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
523 !(p2 = (HWCryptoHook_Finish_t *)
524 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
525 !(p3 = (HWCryptoHook_ModExp_t *)
526 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
527 #ifndef OPENSSL_NO_RSA
528 !(p4 = (HWCryptoHook_RSA_t *)
529 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
530 !(p5 = (HWCryptoHook_RSALoadKey_t *)
531 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
532 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
533 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
534 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
535 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
537 !(p8 = (HWCryptoHook_RandomBytes_t *)
538 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
539 !(p9 = (HWCryptoHook_ModExpCRT_t *)
540 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
542 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
545 /* Copy the pointers */
547 p_hwcrhk_Finish = p2;
548 p_hwcrhk_ModExp = p3;
549 #ifndef OPENSSL_NO_RSA
551 p_hwcrhk_RSALoadKey = p5;
552 p_hwcrhk_RSAGetPublicKey = p6;
553 p_hwcrhk_RSAUnloadKey = p7;
555 p_hwcrhk_RandomBytes = p8;
556 p_hwcrhk_ModExpCRT = p9;
558 /* Check if the application decided to support dynamic locks,
559 and if it does, use them. */
560 if (disable_mutex_callbacks == 0 &&
561 CRYPTO_get_dynlock_create_callback() != NULL &&
562 CRYPTO_get_dynlock_lock_callback() != NULL &&
563 CRYPTO_get_dynlock_destroy_callback() != NULL)
565 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
566 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
567 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
568 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
571 /* Try and get a context - if not, we may have a DSO but no
573 if(!get_context(&hwcrhk_context, &password_context))
575 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
578 /* Everything's fine. */
579 #ifndef OPENSSL_NO_RSA
580 if (hndidx_rsa == -1)
581 hndidx_rsa = RSA_get_ex_new_index(0,
582 "nFast HWCryptoHook RSA key handle",
583 NULL, NULL, hwcrhk_ex_free);
588 DSO_free(hwcrhk_dso);
590 p_hwcrhk_Init = NULL;
591 p_hwcrhk_Finish = NULL;
592 p_hwcrhk_ModExp = NULL;
593 #ifndef OPENSSL_NO_RSA
595 p_hwcrhk_RSALoadKey = NULL;
596 p_hwcrhk_RSAGetPublicKey = NULL;
597 p_hwcrhk_RSAUnloadKey = NULL;
599 p_hwcrhk_ModExpCRT = NULL;
600 p_hwcrhk_RandomBytes = NULL;
604 static int hwcrhk_finish(ENGINE *e)
607 free_HWCRHK_LIBNAME();
608 if(hwcrhk_dso == NULL)
610 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
614 release_context(hwcrhk_context);
615 if(!DSO_free(hwcrhk_dso))
617 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
625 p_hwcrhk_Init = NULL;
626 p_hwcrhk_Finish = NULL;
627 p_hwcrhk_ModExp = NULL;
628 #ifndef OPENSSL_NO_RSA
630 p_hwcrhk_RSALoadKey = NULL;
631 p_hwcrhk_RSAGetPublicKey = NULL;
632 p_hwcrhk_RSAUnloadKey = NULL;
634 p_hwcrhk_ModExpCRT = NULL;
635 p_hwcrhk_RandomBytes = NULL;
639 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)())
645 case HWCRHK_CMD_SO_PATH:
648 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
653 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
656 return set_HWCRHK_LIBNAME((const char *)p);
657 case ENGINE_CTRL_SET_LOGSTREAM:
661 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
667 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
670 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
672 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
674 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
675 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
676 password_context.password_callback = (pem_password_cb *)f;
677 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
679 case ENGINE_CTRL_SET_USER_INTERFACE:
680 case HWCRHK_CMD_SET_USER_INTERFACE:
681 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
682 password_context.ui_method = (UI_METHOD *)p;
683 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
685 case ENGINE_CTRL_SET_CALLBACK_DATA:
686 case HWCRHK_CMD_SET_CALLBACK_DATA:
687 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
688 password_context.callback_data = p;
689 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
691 /* this enables or disables the "SimpleForkCheck" flag used in the
692 * initialisation structure. */
693 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
694 case HWCRHK_CMD_FORK_CHECK:
695 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
697 hwcrhk_globals.flags |=
698 HWCryptoHook_InitFlags_SimpleForkCheck;
700 hwcrhk_globals.flags &=
701 ~HWCryptoHook_InitFlags_SimpleForkCheck;
702 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
704 /* This will prevent the initialisation function from "installing"
705 * the mutex-handling callbacks, even if they are available from
706 * within the library (or were provided to the library from the
707 * calling application). This is to remove any baggage for
708 * applications not using multithreading. */
709 case ENGINE_CTRL_CHIL_NO_LOCKING:
710 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
711 disable_mutex_callbacks = 1;
712 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
714 case HWCRHK_CMD_THREAD_LOCKING:
715 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
716 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
717 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
720 /* The command isn't understood by this engine */
722 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
723 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
731 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
732 UI_METHOD *ui_method, void *callback_data)
734 #ifndef OPENSSL_NO_RSA
737 EVP_PKEY *res = NULL;
738 #ifndef OPENSSL_NO_RSA
739 HWCryptoHook_MPI e, n;
740 HWCryptoHook_RSAKeyHandle *hptr;
742 #if !defined(OPENSSL_NO_RSA)
744 HWCryptoHook_ErrMsgBuf rmsg;
746 HWCryptoHook_PassphraseContext ppctx;
748 #if !defined(OPENSSL_NO_RSA)
750 rmsg.size = sizeof(tempbuf);
755 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
756 HWCRHK_R_NOT_INITIALISED);
759 #ifndef OPENSSL_NO_RSA
760 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
763 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
764 ERR_R_MALLOC_FAILURE);
767 ppctx.ui_method = ui_method;
768 ppctx.callback_data = callback_data;
769 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
772 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
773 HWCRHK_R_CHIL_ERROR);
774 ERR_add_error_data(1,rmsg.buf);
779 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
784 #ifndef OPENSSL_NO_RSA
785 rtmp = RSA_new_method(eng);
786 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
789 rtmp->flags |= RSA_FLAG_EXT_PKEY;
792 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
793 != HWCRYPTOHOOK_ERROR_MPISIZE)
795 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,HWCRHK_R_CHIL_ERROR);
796 ERR_add_error_data(1,rmsg.buf);
800 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
801 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
805 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
807 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
808 HWCRHK_R_CHIL_ERROR);
809 ERR_add_error_data(1,rmsg.buf);
812 rtmp->e->top = e.size / sizeof(BN_ULONG);
814 rtmp->n->top = n.size / sizeof(BN_ULONG);
817 res = EVP_PKEY_new();
818 EVP_PKEY_assign_RSA(res, rtmp);
822 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
823 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
829 #ifndef OPENSSL_NO_RSA
836 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
837 UI_METHOD *ui_method, void *callback_data)
839 EVP_PKEY *res = NULL;
841 #ifndef OPENSSL_NO_RSA
842 res = hwcrhk_load_privkey(eng, key_id,
843 ui_method, callback_data);
849 #ifndef OPENSSL_NO_RSA
854 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
856 res->pkey.rsa = RSA_new();
857 res->pkey.rsa->n = rsa->n;
858 res->pkey.rsa->e = rsa->e;
861 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
867 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
868 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
879 /* A little mod_exp */
880 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
881 const BIGNUM *m, BN_CTX *ctx)
884 HWCryptoHook_ErrMsgBuf rmsg;
885 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
886 we use them directly, plus a little macro magic. We only
887 thing we need to make sure of is that enough space is allocated. */
888 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
891 to_return = 0; /* expect failure */
893 rmsg.size = sizeof(tempbuf);
897 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
900 /* Prepare the params */
901 bn_expand2(r, m->top); /* Check for error !! */
907 /* Perform the operation */
908 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
910 /* Convert the response */
911 r->top = m_r.size / sizeof(BN_ULONG);
916 /* FIXME: When this error is returned, HWCryptoHook is
917 telling us that falling back to software computation
918 might be a good thing. */
919 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
921 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
925 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
927 ERR_add_error_data(1,rmsg.buf);
936 #ifndef OPENSSL_NO_RSA
937 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa)
940 HWCryptoHook_ErrMsgBuf rmsg;
941 HWCryptoHook_RSAKeyHandle *hptr;
942 int to_return = 0, ret;
945 rmsg.size = sizeof(tempbuf);
949 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
953 /* This provides support for nForce keys. Since that's opaque data
954 all we do is provide a handle to the proper key and let HWCryptoHook
955 take care of the rest. */
956 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
959 HWCryptoHook_MPI m_a, m_r;
963 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
964 HWCRHK_R_MISSING_KEY_COMPONENTS);
968 /* Prepare the params */
969 bn_expand2(r, rsa->n->top); /* Check for error !! */
973 /* Perform the operation */
974 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
976 /* Convert the response */
977 r->top = m_r.size / sizeof(BN_ULONG);
982 /* FIXME: When this error is returned, HWCryptoHook is
983 telling us that falling back to software computation
984 might be a good thing. */
985 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
987 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
988 HWCRHK_R_REQUEST_FALLBACK);
992 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
993 HWCRHK_R_REQUEST_FAILED);
995 ERR_add_error_data(1,rmsg.buf);
1001 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1003 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1005 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1006 HWCRHK_R_MISSING_KEY_COMPONENTS);
1010 /* Prepare the params */
1011 bn_expand2(r, rsa->n->top); /* Check for error !! */
1013 BN2MPI(m_p, rsa->p);
1014 BN2MPI(m_q, rsa->q);
1015 BN2MPI(m_dmp1, rsa->dmp1);
1016 BN2MPI(m_dmq1, rsa->dmq1);
1017 BN2MPI(m_iqmp, rsa->iqmp);
1020 /* Perform the operation */
1021 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1022 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
1024 /* Convert the response */
1025 r->top = m_r.size / sizeof(BN_ULONG);
1030 /* FIXME: When this error is returned, HWCryptoHook is
1031 telling us that falling back to software computation
1032 might be a good thing. */
1033 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1035 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1036 HWCRHK_R_REQUEST_FALLBACK);
1040 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1041 HWCRHK_R_REQUEST_FAILED);
1043 ERR_add_error_data(1,rmsg.buf);
1047 /* If we're here, we must be here with some semblance of success :-) */
1054 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1055 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1056 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1058 return hwcrhk_mod_exp(r, a, p, m, ctx);
1061 #ifndef OPENSSL_NO_DH
1062 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1063 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1064 const BIGNUM *a, const BIGNUM *p,
1065 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1067 return hwcrhk_mod_exp(r, a, p, m, ctx);
1071 /* Random bytes are good */
1072 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1075 HWCryptoHook_ErrMsgBuf rmsg;
1076 int to_return = 0; /* assume failure */
1080 rmsg.size = sizeof(tempbuf);
1084 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1088 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1091 /* FIXME: When this error is returned, HWCryptoHook is
1092 telling us that falling back to software computation
1093 might be a good thing. */
1094 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1096 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1097 HWCRHK_R_REQUEST_FALLBACK);
1101 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1102 HWCRHK_R_REQUEST_FAILED);
1104 ERR_add_error_data(1,rmsg.buf);
1112 static int hwcrhk_rand_status(void)
1117 /* This cleans up an RSA KM key, called when ex_data is freed */
1119 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1120 int ind,long argl, void *argp)
1123 HWCryptoHook_ErrMsgBuf rmsg;
1124 #ifndef OPENSSL_NO_RSA
1125 HWCryptoHook_RSAKeyHandle *hptr;
1127 #if !defined(OPENSSL_NO_RSA)
1132 rmsg.size = sizeof(tempbuf);
1134 #ifndef OPENSSL_NO_RSA
1135 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1138 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1144 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1145 * these just wrap the POSIX functions and add some logging.
1148 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1149 HWCryptoHook_CallerContext *cactx)
1151 mt->lockid = CRYPTO_get_new_dynlockid();
1152 if (mt->lockid == 0)
1153 return 1; /* failure */
1154 return 0; /* success */
1157 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1159 CRYPTO_w_lock(mt->lockid);
1163 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1165 CRYPTO_w_unlock(mt->lockid);
1168 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1170 CRYPTO_destroy_dynlockid(mt->lockid);
1173 static int hwcrhk_get_pass(const char *prompt_info,
1174 int *len_io, char *buf,
1175 HWCryptoHook_PassphraseContext *ppctx,
1176 HWCryptoHook_CallerContext *cactx)
1178 pem_password_cb *callback = NULL;
1179 void *callback_data = NULL;
1180 UI_METHOD *ui_method = NULL;
1184 if (cactx->ui_method)
1185 ui_method = cactx->ui_method;
1186 if (cactx->password_callback)
1187 callback = cactx->password_callback;
1188 if (cactx->callback_data)
1189 callback_data = cactx->callback_data;
1193 if (ppctx->ui_method)
1195 ui_method = ppctx->ui_method;
1198 if (ppctx->callback_data)
1199 callback_data = ppctx->callback_data;
1201 if (callback == NULL && ui_method == NULL)
1203 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1209 UI *ui = UI_new_method(ui_method);
1213 char *prompt = UI_construct_prompt(ui,
1214 "pass phrase", prompt_info);
1216 ok = UI_add_input_string(ui,prompt,
1217 UI_INPUT_FLAG_DEFAULT_PWD,
1218 buf,0,(*len_io) - 1);
1219 UI_add_user_data(ui, callback_data);
1220 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1227 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1230 *len_io = strlen(buf);
1233 OPENSSL_free(prompt);
1238 *len_io = callback(buf, *len_io, 0, callback_data);
1245 static int hwcrhk_insert_card(const char *prompt_info,
1246 const char *wrong_info,
1247 HWCryptoHook_PassphraseContext *ppctx,
1248 HWCryptoHook_CallerContext *cactx)
1252 void *callback_data = NULL;
1253 UI_METHOD *ui_method = NULL;
1257 if (cactx->ui_method)
1258 ui_method = cactx->ui_method;
1259 if (cactx->callback_data)
1260 callback_data = cactx->callback_data;
1264 if (ppctx->ui_method)
1265 ui_method = ppctx->ui_method;
1266 if (ppctx->callback_data)
1267 callback_data = ppctx->callback_data;
1269 if (ui_method == NULL)
1271 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1272 HWCRHK_R_NO_CALLBACK);
1276 ui = UI_new_method(ui_method);
1284 BIO_snprintf(buf, sizeof(buf)-1,
1285 "Current card: \"%s\"\n", wrong_info);
1286 ok = UI_dup_info_string(ui, buf);
1287 if (ok >= 0 && prompt_info)
1289 BIO_snprintf(buf, sizeof(buf)-1,
1290 "Insert card \"%s\"", prompt_info);
1291 ok = UI_dup_input_boolean(ui, buf,
1292 "\n then hit <enter> or C<enter> to cancel\n",
1293 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1295 UI_add_user_data(ui, callback_data);
1298 ok = UI_process(ui);
1301 if (ok == -2 || (ok >= 0 && answer == 'C'))
1311 static void hwcrhk_log_message(void *logstr, const char *message)
1313 BIO *lstream = NULL;
1315 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1317 lstream=*(BIO **)logstr;
1320 BIO_write(lstream, message, strlen(message));
1322 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1325 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1326 * shared-library. */
1327 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1328 static int bind_fn(ENGINE *e, const char *id)
1330 if(id && (strcmp(id, engine_hwcrhk_id) != 0))
1336 IMPLEMENT_DYNAMIC_CHECK_FN()
1337 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1338 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1340 #endif /* !OPENSSL_NO_HW_NCIPHER */
1341 #endif /* !OPENSSL_NO_HW */