Sync usage with man page.
[netbsd-mini2440.git] / crypto / external / bsd / openssl / dist / engines / e_chil.c
blobc0643256f202e84647301273b2883ce936fde27b
1 /* crypto/engine/e_chil.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 (steve@openssl.org)
4 * for the OpenSSL project 2000.
5 */
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
11 * are met:
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
19 * distribution.
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
36 * acknowledgment:
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).
60 #include <stdio.h>
61 #include <string.h>
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>
67 #include <openssl/rand.h>
68 #ifndef OPENSSL_NO_RSA
69 #include <openssl/rsa.h>
70 #endif
71 #ifndef OPENSSL_NO_DH
72 #include <openssl/dh.h>
73 #endif
74 #include <openssl/bn.h>
76 #ifndef OPENSSL_NO_HW
77 #ifndef OPENSSL_NO_HW_CHIL
79 /* Attribution notice: nCipher have said several times that it's OK for
80 * us to implement a general interface to their boxes, and recently declared
81 * their HWCryptoHook to be public, and therefore available for us to use.
82 * Thanks, nCipher.
84 * The hwcryptohook.h included here is from May 2000.
85 * [Richard Levitte]
87 #ifdef FLAT_INC
88 #include "hwcryptohook.h"
89 #else
90 #include "vendor_defns/hwcryptohook.h"
91 #endif
93 #define HWCRHK_LIB_NAME "CHIL engine"
94 #include "e_chil_err.c"
96 static int hwcrhk_destroy(ENGINE *e);
97 static int hwcrhk_init(ENGINE *e);
98 static int hwcrhk_finish(ENGINE *e);
99 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void));
101 /* Functions to handle mutexes */
102 static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
103 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
104 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
105 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
107 /* BIGNUM stuff */
108 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
109 const BIGNUM *m, BN_CTX *ctx);
111 #ifndef OPENSSL_NO_RSA
112 /* RSA stuff */
113 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
114 #endif
115 #ifndef OPENSSL_NO_RSA
116 /* This function is aliased to mod_exp (with the mont stuff dropped). */
117 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
118 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
119 #endif
121 #ifndef OPENSSL_NO_DH
122 /* DH stuff */
123 /* This function is alised to mod_exp (with the DH and mont dropped). */
124 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
125 const BIGNUM *a, const BIGNUM *p,
126 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
127 #endif
129 /* RAND stuff */
130 static int hwcrhk_rand_bytes(unsigned char *buf, int num);
131 static int hwcrhk_rand_status(void);
133 /* KM stuff */
134 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
135 UI_METHOD *ui_method, void *callback_data);
136 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
137 UI_METHOD *ui_method, void *callback_data);
138 #ifndef OPENSSL_NO_RSA
139 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
140 int ind,long argl, void *argp);
141 #endif
143 /* Interaction stuff */
144 static int hwcrhk_insert_card(const char *prompt_info,
145 const char *wrong_info,
146 HWCryptoHook_PassphraseContext *ppctx,
147 HWCryptoHook_CallerContext *cactx);
148 static int hwcrhk_get_pass(const char *prompt_info,
149 int *len_io, char *buf,
150 HWCryptoHook_PassphraseContext *ppctx,
151 HWCryptoHook_CallerContext *cactx);
152 static void hwcrhk_log_message(void *logstr, const char *message);
154 /* The definitions for control commands specific to this engine */
155 #define HWCRHK_CMD_SO_PATH ENGINE_CMD_BASE
156 #define HWCRHK_CMD_FORK_CHECK (ENGINE_CMD_BASE + 1)
157 #define HWCRHK_CMD_THREAD_LOCKING (ENGINE_CMD_BASE + 2)
158 #define HWCRHK_CMD_SET_USER_INTERFACE (ENGINE_CMD_BASE + 3)
159 #define HWCRHK_CMD_SET_CALLBACK_DATA (ENGINE_CMD_BASE + 4)
160 static const ENGINE_CMD_DEFN hwcrhk_cmd_defns[] = {
161 {HWCRHK_CMD_SO_PATH,
162 "SO_PATH",
163 "Specifies the path to the 'hwcrhk' shared library",
164 ENGINE_CMD_FLAG_STRING},
165 {HWCRHK_CMD_FORK_CHECK,
166 "FORK_CHECK",
167 "Turns fork() checking on (non-zero) or off (zero)",
168 ENGINE_CMD_FLAG_NUMERIC},
169 {HWCRHK_CMD_THREAD_LOCKING,
170 "THREAD_LOCKING",
171 "Turns thread-safe locking on (zero) or off (non-zero)",
172 ENGINE_CMD_FLAG_NUMERIC},
173 {HWCRHK_CMD_SET_USER_INTERFACE,
174 "SET_USER_INTERFACE",
175 "Set the global user interface (internal)",
176 ENGINE_CMD_FLAG_INTERNAL},
177 {HWCRHK_CMD_SET_CALLBACK_DATA,
178 "SET_CALLBACK_DATA",
179 "Set the global user interface extra data (internal)",
180 ENGINE_CMD_FLAG_INTERNAL},
181 {0, NULL, NULL, 0}
184 #ifndef OPENSSL_NO_RSA
185 /* Our internal RSA_METHOD that we provide pointers to */
186 static RSA_METHOD hwcrhk_rsa =
188 "CHIL RSA method",
189 NULL,
190 NULL,
191 NULL,
192 NULL,
193 hwcrhk_rsa_mod_exp,
194 hwcrhk_mod_exp_mont,
195 NULL,
196 NULL,
198 NULL,
199 NULL,
200 NULL,
201 NULL
203 #endif
205 #ifndef OPENSSL_NO_DH
206 /* Our internal DH_METHOD that we provide pointers to */
207 static DH_METHOD hwcrhk_dh =
209 "CHIL DH method",
210 NULL,
211 NULL,
212 hwcrhk_mod_exp_dh,
213 NULL,
214 NULL,
216 NULL,
217 NULL
219 #endif
221 static RAND_METHOD hwcrhk_rand =
223 /* "CHIL RAND method", */
224 NULL,
225 hwcrhk_rand_bytes,
226 NULL,
227 NULL,
228 hwcrhk_rand_bytes,
229 hwcrhk_rand_status,
232 /* Constants used when creating the ENGINE */
233 static const char *engine_hwcrhk_id = "chil";
234 static const char *engine_hwcrhk_name = "CHIL hardware engine support";
235 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
236 /* Compatibility hack, the dynamic library uses this form in the path */
237 static const char *engine_hwcrhk_id_alt = "ncipher";
238 #endif
240 /* Internal stuff for HWCryptoHook */
242 /* Some structures needed for proper use of thread locks */
243 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
244 into HWCryptoHook_Mutex */
245 struct HWCryptoHook_MutexValue
247 int lockid;
250 /* hwcryptohook.h has some typedefs that turn
251 struct HWCryptoHook_PassphraseContextValue
252 into HWCryptoHook_PassphraseContext */
253 struct HWCryptoHook_PassphraseContextValue
255 UI_METHOD *ui_method;
256 void *callback_data;
259 /* hwcryptohook.h has some typedefs that turn
260 struct HWCryptoHook_CallerContextValue
261 into HWCryptoHook_CallerContext */
262 struct HWCryptoHook_CallerContextValue
264 pem_password_cb *password_callback; /* Deprecated! Only present for
265 backward compatibility! */
266 UI_METHOD *ui_method;
267 void *callback_data;
270 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
271 BIGNUM's, so lets define a couple of conversion macros */
272 #define BN2MPI(mp, bn) \
273 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
274 #define MPI2BN(bn, mp) \
275 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
277 static BIO *logstream = NULL;
278 static int disable_mutex_callbacks = 0;
280 /* One might wonder why these are needed, since one can pass down at least
281 a UI_METHOD and a pointer to callback data to the key-loading functions.
282 The thing is that the ModExp and RSAImmed functions can load keys as well,
283 if the data they get is in a special, nCipher-defined format (hint: if you
284 look at the private exponent of the RSA data as a string, you'll see this
285 string: "nCipher KM tool key id", followed by some bytes, followed a key
286 identity string, followed by more bytes. This happens when you use "embed"
287 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
288 any passphrase or caller context, and our functions can't really take any
289 callback data either. Still, the "insert_card" and "get_passphrase"
290 callbacks may be called down the line, and will need to know what user
291 interface callbacks to call, and having callback data from the application
292 may be a nice thing as well, so we need to keep track of that globally. */
293 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
295 /* Stuff to pass to the HWCryptoHook library */
296 static HWCryptoHook_InitInfo hwcrhk_globals = {
297 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
298 &logstream, /* logstream */
299 sizeof(BN_ULONG), /* limbsize */
300 0, /* mslimb first: false for BNs */
301 -1, /* msbyte first: use native */
302 0, /* Max mutexes, 0 = no small limit */
303 0, /* Max simultaneous, 0 = default */
305 /* The next few are mutex stuff: we write wrapper functions
306 around the OS mutex functions. We initialise them to 0
307 here, and change that to actual function pointers in hwcrhk_init()
308 if dynamic locks are supported (that is, if the application
309 programmer has made sure of setting up callbacks bafore starting
310 this engine) *and* if disable_mutex_callbacks hasn't been set by
311 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
312 sizeof(HWCryptoHook_Mutex),
318 /* The next few are condvar stuff: we write wrapper functions
319 round the OS functions. Currently not implemented and not
320 and absolute necessity even in threaded programs, therefore
321 0'ed. Will hopefully be implemented some day, since it
322 enhances the efficiency of HWCryptoHook. */
323 0, /* sizeof(HWCryptoHook_CondVar), */
324 0, /* hwcrhk_cv_init, */
325 0, /* hwcrhk_cv_wait, */
326 0, /* hwcrhk_cv_signal, */
327 0, /* hwcrhk_cv_broadcast, */
328 0, /* hwcrhk_cv_destroy, */
330 hwcrhk_get_pass, /* pass phrase */
331 hwcrhk_insert_card, /* insert a card */
332 hwcrhk_log_message /* Log message */
336 /* Now, to our own code */
338 /* This internal function is used by ENGINE_chil() and possibly by the
339 * "dynamic" ENGINE support too */
340 static int bind_helper(ENGINE *e)
342 #ifndef OPENSSL_NO_RSA
343 const RSA_METHOD *meth1;
344 #endif
345 #ifndef OPENSSL_NO_DH
346 const DH_METHOD *meth2;
347 #endif
348 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
349 !ENGINE_set_name(e, engine_hwcrhk_name) ||
350 #ifndef OPENSSL_NO_RSA
351 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
352 #endif
353 #ifndef OPENSSL_NO_DH
354 !ENGINE_set_DH(e, &hwcrhk_dh) ||
355 #endif
356 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
357 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
358 !ENGINE_set_init_function(e, hwcrhk_init) ||
359 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
360 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
361 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
362 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
363 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
364 return 0;
366 #ifndef OPENSSL_NO_RSA
367 /* We know that the "PKCS1_SSLeay()" functions hook properly
368 * to the cswift-specific mod_exp and mod_exp_crt so we use
369 * those functions. NB: We don't use ENGINE_openssl() or
370 * anything "more generic" because something like the RSAref
371 * code may not hook properly, and if you own one of these
372 * cards then you have the right to do RSA operations on it
373 * anyway! */
374 meth1 = RSA_PKCS1_SSLeay();
375 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
376 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
377 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
378 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
379 #endif
381 #ifndef OPENSSL_NO_DH
382 /* Much the same for Diffie-Hellman */
383 meth2 = DH_OpenSSL();
384 hwcrhk_dh.generate_key = meth2->generate_key;
385 hwcrhk_dh.compute_key = meth2->compute_key;
386 #endif
388 /* Ensure the hwcrhk error handling is set up */
389 ERR_load_HWCRHK_strings();
390 return 1;
393 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
394 static ENGINE *engine_chil(void)
396 ENGINE *ret = ENGINE_new();
397 if(!ret)
398 return NULL;
399 if(!bind_helper(ret))
401 ENGINE_free(ret);
402 return NULL;
404 return ret;
407 void ENGINE_load_chil(void)
409 /* Copied from eng_[openssl|dyn].c */
410 ENGINE *toadd = engine_chil();
411 if(!toadd) return;
412 ENGINE_add(toadd);
413 ENGINE_free(toadd);
414 ERR_clear_error();
416 #endif
418 /* This is a process-global DSO handle used for loading and unloading
419 * the HWCryptoHook library. NB: This is only set (or unset) during an
420 * init() or finish() call (reference counts permitting) and they're
421 * operating with global locks, so this should be thread-safe
422 * implicitly. */
423 static DSO *hwcrhk_dso = NULL;
424 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
425 #ifndef OPENSSL_NO_RSA
426 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
427 #endif
429 /* These are the function pointers that are (un)set when the library has
430 * successfully (un)loaded. */
431 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
432 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
433 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
434 #ifndef OPENSSL_NO_RSA
435 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
436 #endif
437 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
438 #ifndef OPENSSL_NO_RSA
439 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
440 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
441 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
442 #endif
443 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
445 /* Used in the DSO operations. */
446 static const char *HWCRHK_LIBNAME = NULL;
447 static void free_HWCRHK_LIBNAME(void)
449 if(HWCRHK_LIBNAME)
450 OPENSSL_free((void*)HWCRHK_LIBNAME);
451 HWCRHK_LIBNAME = NULL;
453 static const char *get_HWCRHK_LIBNAME(void)
455 if(HWCRHK_LIBNAME)
456 return HWCRHK_LIBNAME;
457 return "nfhwcrhk";
459 static long set_HWCRHK_LIBNAME(const char *name)
461 free_HWCRHK_LIBNAME();
462 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
464 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
465 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
466 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
467 #ifndef OPENSSL_NO_RSA
468 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
469 #endif
470 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
471 #ifndef OPENSSL_NO_RSA
472 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
473 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
474 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
475 #endif
476 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
478 /* HWCryptoHook library functions and mechanics - these are used by the
479 * higher-level functions further down. NB: As and where there's no
480 * error checking, take a look lower down where these functions are
481 * called, the checking and error handling is probably down there. */
483 /* utility function to obtain a context */
484 static int get_context(HWCryptoHook_ContextHandle *hac,
485 HWCryptoHook_CallerContext *cac)
487 char tempbuf[1024];
488 HWCryptoHook_ErrMsgBuf rmsg;
490 rmsg.buf = tempbuf;
491 rmsg.size = sizeof(tempbuf);
493 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
494 cac);
495 if (!*hac)
496 return 0;
497 return 1;
500 /* similarly to release one. */
501 static void release_context(HWCryptoHook_ContextHandle hac)
503 p_hwcrhk_Finish(hac);
506 /* Destructor (complements the "ENGINE_chil()" constructor) */
507 static int hwcrhk_destroy(ENGINE *e)
509 free_HWCRHK_LIBNAME();
510 ERR_unload_HWCRHK_strings();
511 return 1;
514 /* (de)initialisation functions. */
515 static int hwcrhk_init(ENGINE *e)
517 HWCryptoHook_Init_t *p1;
518 HWCryptoHook_Finish_t *p2;
519 HWCryptoHook_ModExp_t *p3;
520 #ifndef OPENSSL_NO_RSA
521 HWCryptoHook_RSA_t *p4;
522 HWCryptoHook_RSALoadKey_t *p5;
523 HWCryptoHook_RSAGetPublicKey_t *p6;
524 HWCryptoHook_RSAUnloadKey_t *p7;
525 #endif
526 HWCryptoHook_RandomBytes_t *p8;
527 HWCryptoHook_ModExpCRT_t *p9;
529 if(hwcrhk_dso != NULL)
531 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
532 goto err;
534 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
535 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
536 if(hwcrhk_dso == NULL)
538 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
539 goto err;
541 if(!(p1 = (HWCryptoHook_Init_t *)
542 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
543 !(p2 = (HWCryptoHook_Finish_t *)
544 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
545 !(p3 = (HWCryptoHook_ModExp_t *)
546 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
547 #ifndef OPENSSL_NO_RSA
548 !(p4 = (HWCryptoHook_RSA_t *)
549 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
550 !(p5 = (HWCryptoHook_RSALoadKey_t *)
551 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
552 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
553 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
554 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
555 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
556 #endif
557 !(p8 = (HWCryptoHook_RandomBytes_t *)
558 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
559 !(p9 = (HWCryptoHook_ModExpCRT_t *)
560 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
562 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
563 goto err;
565 /* Copy the pointers */
566 p_hwcrhk_Init = p1;
567 p_hwcrhk_Finish = p2;
568 p_hwcrhk_ModExp = p3;
569 #ifndef OPENSSL_NO_RSA
570 p_hwcrhk_RSA = p4;
571 p_hwcrhk_RSALoadKey = p5;
572 p_hwcrhk_RSAGetPublicKey = p6;
573 p_hwcrhk_RSAUnloadKey = p7;
574 #endif
575 p_hwcrhk_RandomBytes = p8;
576 p_hwcrhk_ModExpCRT = p9;
578 /* Check if the application decided to support dynamic locks,
579 and if it does, use them. */
580 if (disable_mutex_callbacks == 0)
582 if (CRYPTO_get_dynlock_create_callback() != NULL &&
583 CRYPTO_get_dynlock_lock_callback() != NULL &&
584 CRYPTO_get_dynlock_destroy_callback() != NULL)
586 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
587 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
588 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
589 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
593 /* Try and get a context - if not, we may have a DSO but no
594 * accelerator! */
595 if(!get_context(&hwcrhk_context, &password_context))
597 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
598 goto err;
600 /* Everything's fine. */
601 #ifndef OPENSSL_NO_RSA
602 if (hndidx_rsa == -1)
603 hndidx_rsa = RSA_get_ex_new_index(0,
604 "nFast HWCryptoHook RSA key handle",
605 NULL, NULL, hwcrhk_ex_free);
606 #endif
607 return 1;
608 err:
609 if(hwcrhk_dso)
610 DSO_free(hwcrhk_dso);
611 hwcrhk_dso = NULL;
612 p_hwcrhk_Init = NULL;
613 p_hwcrhk_Finish = NULL;
614 p_hwcrhk_ModExp = NULL;
615 #ifndef OPENSSL_NO_RSA
616 p_hwcrhk_RSA = NULL;
617 p_hwcrhk_RSALoadKey = NULL;
618 p_hwcrhk_RSAGetPublicKey = NULL;
619 p_hwcrhk_RSAUnloadKey = NULL;
620 #endif
621 p_hwcrhk_ModExpCRT = NULL;
622 p_hwcrhk_RandomBytes = NULL;
623 return 0;
626 static int hwcrhk_finish(ENGINE *e)
628 int to_return = 1;
629 free_HWCRHK_LIBNAME();
630 if(hwcrhk_dso == NULL)
632 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
633 to_return = 0;
634 goto err;
636 release_context(hwcrhk_context);
637 if(!DSO_free(hwcrhk_dso))
639 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
640 to_return = 0;
641 goto err;
643 err:
644 if (logstream)
645 BIO_free(logstream);
646 hwcrhk_dso = NULL;
647 p_hwcrhk_Init = NULL;
648 p_hwcrhk_Finish = NULL;
649 p_hwcrhk_ModExp = NULL;
650 #ifndef OPENSSL_NO_RSA
651 p_hwcrhk_RSA = NULL;
652 p_hwcrhk_RSALoadKey = NULL;
653 p_hwcrhk_RSAGetPublicKey = NULL;
654 p_hwcrhk_RSAUnloadKey = NULL;
655 #endif
656 p_hwcrhk_ModExpCRT = NULL;
657 p_hwcrhk_RandomBytes = NULL;
658 return to_return;
661 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
663 int to_return = 1;
665 switch(cmd)
667 case HWCRHK_CMD_SO_PATH:
668 if(hwcrhk_dso)
670 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
671 return 0;
673 if(p == NULL)
675 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
676 return 0;
678 return set_HWCRHK_LIBNAME((const char *)p);
679 case ENGINE_CTRL_SET_LOGSTREAM:
681 BIO *bio = (BIO *)p;
683 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
684 if (logstream)
686 BIO_free(logstream);
687 logstream = NULL;
689 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
690 logstream = bio;
691 else
692 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
694 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
695 break;
696 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
697 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
698 password_context.password_callback = (pem_password_cb *)f;
699 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
700 break;
701 case ENGINE_CTRL_SET_USER_INTERFACE:
702 case HWCRHK_CMD_SET_USER_INTERFACE:
703 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
704 password_context.ui_method = (UI_METHOD *)p;
705 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
706 break;
707 case ENGINE_CTRL_SET_CALLBACK_DATA:
708 case HWCRHK_CMD_SET_CALLBACK_DATA:
709 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
710 password_context.callback_data = p;
711 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
712 break;
713 /* this enables or disables the "SimpleForkCheck" flag used in the
714 * initialisation structure. */
715 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
716 case HWCRHK_CMD_FORK_CHECK:
717 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
718 if(i)
719 hwcrhk_globals.flags |=
720 HWCryptoHook_InitFlags_SimpleForkCheck;
721 else
722 hwcrhk_globals.flags &=
723 ~HWCryptoHook_InitFlags_SimpleForkCheck;
724 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
725 break;
726 /* This will prevent the initialisation function from "installing"
727 * the mutex-handling callbacks, even if they are available from
728 * within the library (or were provided to the library from the
729 * calling application). This is to remove any baggage for
730 * applications not using multithreading. */
731 case ENGINE_CTRL_CHIL_NO_LOCKING:
732 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
733 disable_mutex_callbacks = 1;
734 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
735 break;
736 case HWCRHK_CMD_THREAD_LOCKING:
737 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
738 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
739 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
740 break;
742 /* The command isn't understood by this engine */
743 default:
744 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
745 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
746 to_return = 0;
747 break;
750 return to_return;
753 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
754 UI_METHOD *ui_method, void *callback_data)
756 #ifndef OPENSSL_NO_RSA
757 RSA *rtmp = NULL;
758 #endif
759 EVP_PKEY *res = NULL;
760 #ifndef OPENSSL_NO_RSA
761 HWCryptoHook_MPI e, n;
762 HWCryptoHook_RSAKeyHandle *hptr;
763 #endif
764 #if !defined(OPENSSL_NO_RSA)
765 char tempbuf[1024];
766 HWCryptoHook_ErrMsgBuf rmsg;
767 HWCryptoHook_PassphraseContext ppctx;
768 #endif
770 #if !defined(OPENSSL_NO_RSA)
771 rmsg.buf = tempbuf;
772 rmsg.size = sizeof(tempbuf);
773 #endif
775 if(!hwcrhk_context)
777 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
778 HWCRHK_R_NOT_INITIALISED);
779 goto err;
781 #ifndef OPENSSL_NO_RSA
782 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
783 if (!hptr)
785 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
786 ERR_R_MALLOC_FAILURE);
787 goto err;
789 ppctx.ui_method = ui_method;
790 ppctx.callback_data = callback_data;
791 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
792 &rmsg, &ppctx))
794 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
795 HWCRHK_R_CHIL_ERROR);
796 ERR_add_error_data(1,rmsg.buf);
797 goto err;
799 if (!*hptr)
801 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
802 HWCRHK_R_NO_KEY);
803 goto err;
805 #endif
806 #ifndef OPENSSL_NO_RSA
807 rtmp = RSA_new_method(eng);
808 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
809 rtmp->e = BN_new();
810 rtmp->n = BN_new();
811 rtmp->flags |= RSA_FLAG_EXT_PKEY;
812 MPI2BN(rtmp->e, e);
813 MPI2BN(rtmp->n, n);
814 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
815 != HWCRYPTOHOOK_ERROR_MPISIZE)
817 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,HWCRHK_R_CHIL_ERROR);
818 ERR_add_error_data(1,rmsg.buf);
819 goto err;
822 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
823 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
824 MPI2BN(rtmp->e, e);
825 MPI2BN(rtmp->n, n);
827 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
829 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
830 HWCRHK_R_CHIL_ERROR);
831 ERR_add_error_data(1,rmsg.buf);
832 goto err;
834 rtmp->e->top = e.size / sizeof(BN_ULONG);
835 bn_fix_top(rtmp->e);
836 rtmp->n->top = n.size / sizeof(BN_ULONG);
837 bn_fix_top(rtmp->n);
839 res = EVP_PKEY_new();
840 EVP_PKEY_assign_RSA(res, rtmp);
841 #endif
843 if (!res)
844 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
845 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
847 return res;
848 err:
849 #ifndef OPENSSL_NO_RSA
850 if (rtmp)
851 RSA_free(rtmp);
852 #endif
853 return NULL;
856 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
857 UI_METHOD *ui_method, void *callback_data)
859 EVP_PKEY *res = NULL;
861 #ifndef OPENSSL_NO_RSA
862 res = hwcrhk_load_privkey(eng, key_id,
863 ui_method, callback_data);
864 #endif
866 if (res)
867 switch(res->type)
869 #ifndef OPENSSL_NO_RSA
870 case EVP_PKEY_RSA:
872 RSA *rsa = NULL;
874 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
875 rsa = res->pkey.rsa;
876 res->pkey.rsa = RSA_new();
877 res->pkey.rsa->n = rsa->n;
878 res->pkey.rsa->e = rsa->e;
879 rsa->n = NULL;
880 rsa->e = NULL;
881 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
882 RSA_free(rsa);
884 break;
885 #endif
886 default:
887 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
888 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
889 goto err;
892 return res;
893 err:
894 if (res)
895 EVP_PKEY_free(res);
896 return NULL;
899 /* A little mod_exp */
900 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
901 const BIGNUM *m, BN_CTX *ctx)
903 char tempbuf[1024];
904 HWCryptoHook_ErrMsgBuf rmsg;
905 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
906 we use them directly, plus a little macro magic. We only
907 thing we need to make sure of is that enough space is allocated. */
908 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
909 int to_return, ret;
911 to_return = 0; /* expect failure */
912 rmsg.buf = tempbuf;
913 rmsg.size = sizeof(tempbuf);
915 if(!hwcrhk_context)
917 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
918 goto err;
920 /* Prepare the params */
921 bn_expand2(r, m->top); /* Check for error !! */
922 BN2MPI(m_a, a);
923 BN2MPI(m_p, p);
924 BN2MPI(m_n, m);
925 MPI2BN(r, m_r);
927 /* Perform the operation */
928 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
930 /* Convert the response */
931 r->top = m_r.size / sizeof(BN_ULONG);
932 bn_fix_top(r);
934 if (ret < 0)
936 /* FIXME: When this error is returned, HWCryptoHook is
937 telling us that falling back to software computation
938 might be a good thing. */
939 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
941 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
943 else
945 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
947 ERR_add_error_data(1,rmsg.buf);
948 goto err;
951 to_return = 1;
952 err:
953 return to_return;
956 #ifndef OPENSSL_NO_RSA
957 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
959 char tempbuf[1024];
960 HWCryptoHook_ErrMsgBuf rmsg;
961 HWCryptoHook_RSAKeyHandle *hptr;
962 int to_return = 0, ret;
964 rmsg.buf = tempbuf;
965 rmsg.size = sizeof(tempbuf);
967 if(!hwcrhk_context)
969 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
970 goto err;
973 /* This provides support for nForce keys. Since that's opaque data
974 all we do is provide a handle to the proper key and let HWCryptoHook
975 take care of the rest. */
976 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
977 != NULL)
979 HWCryptoHook_MPI m_a, m_r;
981 if(!rsa->n)
983 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
984 HWCRHK_R_MISSING_KEY_COMPONENTS);
985 goto err;
988 /* Prepare the params */
989 bn_expand2(r, rsa->n->top); /* Check for error !! */
990 BN2MPI(m_a, I);
991 MPI2BN(r, m_r);
993 /* Perform the operation */
994 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
996 /* Convert the response */
997 r->top = m_r.size / sizeof(BN_ULONG);
998 bn_fix_top(r);
1000 if (ret < 0)
1002 /* FIXME: When this error is returned, HWCryptoHook is
1003 telling us that falling back to software computation
1004 might be a good thing. */
1005 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1007 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1008 HWCRHK_R_REQUEST_FALLBACK);
1010 else
1012 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1013 HWCRHK_R_REQUEST_FAILED);
1015 ERR_add_error_data(1,rmsg.buf);
1016 goto err;
1019 else
1021 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1023 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1025 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1026 HWCRHK_R_MISSING_KEY_COMPONENTS);
1027 goto err;
1030 /* Prepare the params */
1031 bn_expand2(r, rsa->n->top); /* Check for error !! */
1032 BN2MPI(m_a, I);
1033 BN2MPI(m_p, rsa->p);
1034 BN2MPI(m_q, rsa->q);
1035 BN2MPI(m_dmp1, rsa->dmp1);
1036 BN2MPI(m_dmq1, rsa->dmq1);
1037 BN2MPI(m_iqmp, rsa->iqmp);
1038 MPI2BN(r, m_r);
1040 /* Perform the operation */
1041 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1042 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1044 /* Convert the response */
1045 r->top = m_r.size / sizeof(BN_ULONG);
1046 bn_fix_top(r);
1048 if (ret < 0)
1050 /* FIXME: When this error is returned, HWCryptoHook is
1051 telling us that falling back to software computation
1052 might be a good thing. */
1053 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1055 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1056 HWCRHK_R_REQUEST_FALLBACK);
1058 else
1060 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1061 HWCRHK_R_REQUEST_FAILED);
1063 ERR_add_error_data(1,rmsg.buf);
1064 goto err;
1067 /* If we're here, we must be here with some semblance of success :-) */
1068 to_return = 1;
1069 err:
1070 return to_return;
1072 #endif
1074 #ifndef OPENSSL_NO_RSA
1075 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1076 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1077 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1079 return hwcrhk_mod_exp(r, a, p, m, ctx);
1081 #endif
1083 #ifndef OPENSSL_NO_DH
1084 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1085 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1086 const BIGNUM *a, const BIGNUM *p,
1087 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1089 return hwcrhk_mod_exp(r, a, p, m, ctx);
1091 #endif
1093 /* Random bytes are good */
1094 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1096 char tempbuf[1024];
1097 HWCryptoHook_ErrMsgBuf rmsg;
1098 int to_return = 0; /* assume failure */
1099 int ret;
1101 rmsg.buf = tempbuf;
1102 rmsg.size = sizeof(tempbuf);
1104 if(!hwcrhk_context)
1106 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1107 goto err;
1110 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1111 if (ret < 0)
1113 /* FIXME: When this error is returned, HWCryptoHook is
1114 telling us that falling back to software computation
1115 might be a good thing. */
1116 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1118 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1119 HWCRHK_R_REQUEST_FALLBACK);
1121 else
1123 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1124 HWCRHK_R_REQUEST_FAILED);
1126 ERR_add_error_data(1,rmsg.buf);
1127 goto err;
1129 to_return = 1;
1130 err:
1131 return to_return;
1134 static int hwcrhk_rand_status(void)
1136 return 1;
1139 /* This cleans up an RSA KM key, called when ex_data is freed */
1140 #ifndef OPENSSL_NO_RSA
1141 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1142 int ind,long argl, void *argp)
1144 char tempbuf[1024];
1145 HWCryptoHook_ErrMsgBuf rmsg;
1146 #ifndef OPENSSL_NO_RSA
1147 HWCryptoHook_RSAKeyHandle *hptr;
1148 #endif
1149 #if !defined(OPENSSL_NO_RSA)
1150 int ret;
1151 #endif
1153 rmsg.buf = tempbuf;
1154 rmsg.size = sizeof(tempbuf);
1156 #ifndef OPENSSL_NO_RSA
1157 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1158 if(hptr)
1160 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1161 OPENSSL_free(hptr);
1163 #endif
1165 #endif
1167 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1168 * these just wrap the POSIX functions and add some logging.
1171 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1172 HWCryptoHook_CallerContext *cactx)
1174 mt->lockid = CRYPTO_get_new_dynlockid();
1175 if (mt->lockid == 0)
1176 return 1; /* failure */
1177 return 0; /* success */
1180 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1182 CRYPTO_w_lock(mt->lockid);
1183 return 0;
1186 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1188 CRYPTO_w_unlock(mt->lockid);
1191 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1193 CRYPTO_destroy_dynlockid(mt->lockid);
1196 static int hwcrhk_get_pass(const char *prompt_info,
1197 int *len_io, char *buf,
1198 HWCryptoHook_PassphraseContext *ppctx,
1199 HWCryptoHook_CallerContext *cactx)
1201 pem_password_cb *callback = NULL;
1202 void *callback_data = NULL;
1203 UI_METHOD *ui_method = NULL;
1205 if (cactx)
1207 if (cactx->ui_method)
1208 ui_method = cactx->ui_method;
1209 if (cactx->password_callback)
1210 callback = cactx->password_callback;
1211 if (cactx->callback_data)
1212 callback_data = cactx->callback_data;
1214 if (ppctx)
1216 if (ppctx->ui_method)
1218 ui_method = ppctx->ui_method;
1219 callback = NULL;
1221 if (ppctx->callback_data)
1222 callback_data = ppctx->callback_data;
1224 if (callback == NULL && ui_method == NULL)
1226 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1227 return -1;
1230 if (ui_method)
1232 UI *ui = UI_new_method(ui_method);
1233 if (ui)
1235 int ok;
1236 char *prompt = UI_construct_prompt(ui,
1237 "pass phrase", prompt_info);
1239 ok = UI_add_input_string(ui,prompt,
1240 UI_INPUT_FLAG_DEFAULT_PWD,
1241 buf,0,(*len_io) - 1);
1242 UI_add_user_data(ui, callback_data);
1243 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1245 if (ok >= 0)
1248 ok=UI_process(ui);
1250 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1252 if (ok >= 0)
1253 *len_io = strlen(buf);
1255 UI_free(ui);
1256 OPENSSL_free(prompt);
1259 else
1261 *len_io = callback(buf, *len_io, 0, callback_data);
1263 if(!*len_io)
1264 return -1;
1265 return 0;
1268 static int hwcrhk_insert_card(const char *prompt_info,
1269 const char *wrong_info,
1270 HWCryptoHook_PassphraseContext *ppctx,
1271 HWCryptoHook_CallerContext *cactx)
1273 int ok = -1;
1274 UI *ui;
1275 void *callback_data = NULL;
1276 UI_METHOD *ui_method = NULL;
1278 if (cactx)
1280 if (cactx->ui_method)
1281 ui_method = cactx->ui_method;
1282 if (cactx->callback_data)
1283 callback_data = cactx->callback_data;
1285 if (ppctx)
1287 if (ppctx->ui_method)
1288 ui_method = ppctx->ui_method;
1289 if (ppctx->callback_data)
1290 callback_data = ppctx->callback_data;
1292 if (ui_method == NULL)
1294 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1295 HWCRHK_R_NO_CALLBACK);
1296 return -1;
1299 ui = UI_new_method(ui_method);
1301 if (ui)
1303 char answer;
1304 char buf[BUFSIZ];
1306 if (wrong_info)
1307 BIO_snprintf(buf, sizeof(buf)-1,
1308 "Current card: \"%s\"\n", wrong_info);
1309 ok = UI_dup_info_string(ui, buf);
1310 if (ok >= 0 && prompt_info)
1312 BIO_snprintf(buf, sizeof(buf)-1,
1313 "Insert card \"%s\"", prompt_info);
1314 ok = UI_dup_input_boolean(ui, buf,
1315 "\n then hit <enter> or C<enter> to cancel\n",
1316 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1318 UI_add_user_data(ui, callback_data);
1320 if (ok >= 0)
1321 ok = UI_process(ui);
1322 UI_free(ui);
1324 if (ok == -2 || (ok >= 0 && answer == 'C'))
1325 ok = 1;
1326 else if (ok < 0)
1327 ok = -1;
1328 else
1329 ok = 0;
1331 return ok;
1334 static void hwcrhk_log_message(void *logstr, const char *message)
1336 BIO *lstream = NULL;
1338 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1339 if (logstr)
1340 lstream=*(BIO **)logstr;
1341 if (lstream)
1343 BIO_printf(lstream, "%s\n", message);
1345 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1348 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1349 * shared-library. */
1350 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1351 static int bind_fn(ENGINE *e, const char *id)
1353 if(id && (strcmp(id, engine_hwcrhk_id) != 0) &&
1354 (strcmp(id, engine_hwcrhk_id_alt) != 0))
1355 return 0;
1356 if(!bind_helper(e))
1357 return 0;
1358 return 1;
1360 IMPLEMENT_DYNAMIC_CHECK_FN()
1361 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1362 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1364 #endif /* !OPENSSL_NO_HW_CHIL */
1365 #endif /* !OPENSSL_NO_HW */