nrelease - gui build www/firefox3 -> www/firefox
[dragonfly.git] / crypto / openssl / engines / e_chil.c
blobe1847622ea74b92fba5632c525a06c9291c504f9
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";
236 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
237 /* Compatibility hack, the dynamic library uses this form in the path */
238 static const char *engine_hwcrhk_id_alt = "ncipher";
239 #endif
241 /* Internal stuff for HWCryptoHook */
243 /* Some structures needed for proper use of thread locks */
244 /* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
245 into HWCryptoHook_Mutex */
246 struct HWCryptoHook_MutexValue
248 int lockid;
251 /* hwcryptohook.h has some typedefs that turn
252 struct HWCryptoHook_PassphraseContextValue
253 into HWCryptoHook_PassphraseContext */
254 struct HWCryptoHook_PassphraseContextValue
256 UI_METHOD *ui_method;
257 void *callback_data;
260 /* hwcryptohook.h has some typedefs that turn
261 struct HWCryptoHook_CallerContextValue
262 into HWCryptoHook_CallerContext */
263 struct HWCryptoHook_CallerContextValue
265 pem_password_cb *password_callback; /* Deprecated! Only present for
266 backward compatibility! */
267 UI_METHOD *ui_method;
268 void *callback_data;
271 /* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
272 BIGNUM's, so lets define a couple of conversion macros */
273 #define BN2MPI(mp, bn) \
274 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
275 #define MPI2BN(bn, mp) \
276 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
278 static BIO *logstream = NULL;
279 static int disable_mutex_callbacks = 0;
281 /* One might wonder why these are needed, since one can pass down at least
282 a UI_METHOD and a pointer to callback data to the key-loading functions.
283 The thing is that the ModExp and RSAImmed functions can load keys as well,
284 if the data they get is in a special, nCipher-defined format (hint: if you
285 look at the private exponent of the RSA data as a string, you'll see this
286 string: "nCipher KM tool key id", followed by some bytes, followed a key
287 identity string, followed by more bytes. This happens when you use "embed"
288 keys instead of "hwcrhk" keys). Unfortunately, those functions do not take
289 any passphrase or caller context, and our functions can't really take any
290 callback data either. Still, the "insert_card" and "get_passphrase"
291 callbacks may be called down the line, and will need to know what user
292 interface callbacks to call, and having callback data from the application
293 may be a nice thing as well, so we need to keep track of that globally. */
294 static HWCryptoHook_CallerContext password_context = { NULL, NULL, NULL };
296 /* Stuff to pass to the HWCryptoHook library */
297 static HWCryptoHook_InitInfo hwcrhk_globals = {
298 HWCryptoHook_InitFlags_SimpleForkCheck, /* Flags */
299 &logstream, /* logstream */
300 sizeof(BN_ULONG), /* limbsize */
301 0, /* mslimb first: false for BNs */
302 -1, /* msbyte first: use native */
303 0, /* Max mutexes, 0 = no small limit */
304 0, /* Max simultaneous, 0 = default */
306 /* The next few are mutex stuff: we write wrapper functions
307 around the OS mutex functions. We initialise them to 0
308 here, and change that to actual function pointers in hwcrhk_init()
309 if dynamic locks are supported (that is, if the application
310 programmer has made sure of setting up callbacks bafore starting
311 this engine) *and* if disable_mutex_callbacks hasn't been set by
312 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
313 sizeof(HWCryptoHook_Mutex),
319 /* The next few are condvar stuff: we write wrapper functions
320 round the OS functions. Currently not implemented and not
321 and absolute necessity even in threaded programs, therefore
322 0'ed. Will hopefully be implemented some day, since it
323 enhances the efficiency of HWCryptoHook. */
324 0, /* sizeof(HWCryptoHook_CondVar), */
325 0, /* hwcrhk_cv_init, */
326 0, /* hwcrhk_cv_wait, */
327 0, /* hwcrhk_cv_signal, */
328 0, /* hwcrhk_cv_broadcast, */
329 0, /* hwcrhk_cv_destroy, */
331 hwcrhk_get_pass, /* pass phrase */
332 hwcrhk_insert_card, /* insert a card */
333 hwcrhk_log_message /* Log message */
337 /* Now, to our own code */
339 /* This internal function is used by ENGINE_chil() and possibly by the
340 * "dynamic" ENGINE support too */
341 static int bind_helper(ENGINE *e)
343 #ifndef OPENSSL_NO_RSA
344 const RSA_METHOD *meth1;
345 #endif
346 #ifndef OPENSSL_NO_DH
347 const DH_METHOD *meth2;
348 #endif
349 if(!ENGINE_set_id(e, engine_hwcrhk_id) ||
350 !ENGINE_set_name(e, engine_hwcrhk_name) ||
351 #ifndef OPENSSL_NO_RSA
352 !ENGINE_set_RSA(e, &hwcrhk_rsa) ||
353 #endif
354 #ifndef OPENSSL_NO_DH
355 !ENGINE_set_DH(e, &hwcrhk_dh) ||
356 #endif
357 !ENGINE_set_RAND(e, &hwcrhk_rand) ||
358 !ENGINE_set_destroy_function(e, hwcrhk_destroy) ||
359 !ENGINE_set_init_function(e, hwcrhk_init) ||
360 !ENGINE_set_finish_function(e, hwcrhk_finish) ||
361 !ENGINE_set_ctrl_function(e, hwcrhk_ctrl) ||
362 !ENGINE_set_load_privkey_function(e, hwcrhk_load_privkey) ||
363 !ENGINE_set_load_pubkey_function(e, hwcrhk_load_pubkey) ||
364 !ENGINE_set_cmd_defns(e, hwcrhk_cmd_defns))
365 return 0;
367 #ifndef OPENSSL_NO_RSA
368 /* We know that the "PKCS1_SSLeay()" functions hook properly
369 * to the cswift-specific mod_exp and mod_exp_crt so we use
370 * those functions. NB: We don't use ENGINE_openssl() or
371 * anything "more generic" because something like the RSAref
372 * code may not hook properly, and if you own one of these
373 * cards then you have the right to do RSA operations on it
374 * anyway! */
375 meth1 = RSA_PKCS1_SSLeay();
376 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
377 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
378 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
379 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
380 #endif
382 #ifndef OPENSSL_NO_DH
383 /* Much the same for Diffie-Hellman */
384 meth2 = DH_OpenSSL();
385 hwcrhk_dh.generate_key = meth2->generate_key;
386 hwcrhk_dh.compute_key = meth2->compute_key;
387 #endif
389 /* Ensure the hwcrhk error handling is set up */
390 ERR_load_HWCRHK_strings();
391 return 1;
394 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
395 static ENGINE *engine_chil(void)
397 ENGINE *ret = ENGINE_new();
398 if(!ret)
399 return NULL;
400 if(!bind_helper(ret))
402 ENGINE_free(ret);
403 return NULL;
405 return ret;
408 void ENGINE_load_chil(void)
410 /* Copied from eng_[openssl|dyn].c */
411 ENGINE *toadd = engine_chil();
412 if(!toadd) return;
413 ENGINE_add(toadd);
414 ENGINE_free(toadd);
415 ERR_clear_error();
417 #endif
419 /* This is a process-global DSO handle used for loading and unloading
420 * the HWCryptoHook library. NB: This is only set (or unset) during an
421 * init() or finish() call (reference counts permitting) and they're
422 * operating with global locks, so this should be thread-safe
423 * implicitly. */
424 static DSO *hwcrhk_dso = NULL;
425 static HWCryptoHook_ContextHandle hwcrhk_context = 0;
426 #ifndef OPENSSL_NO_RSA
427 static int hndidx_rsa = -1; /* Index for KM handle. Not really used yet. */
428 #endif
430 /* These are the function pointers that are (un)set when the library has
431 * successfully (un)loaded. */
432 static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
433 static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
434 static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
435 #ifndef OPENSSL_NO_RSA
436 static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
437 #endif
438 static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
439 #ifndef OPENSSL_NO_RSA
440 static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
441 static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
442 static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
443 #endif
444 static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
446 /* Used in the DSO operations. */
447 static const char *HWCRHK_LIBNAME = NULL;
448 static void free_HWCRHK_LIBNAME(void)
450 if(HWCRHK_LIBNAME)
451 OPENSSL_free((void*)HWCRHK_LIBNAME);
452 HWCRHK_LIBNAME = NULL;
454 static const char *get_HWCRHK_LIBNAME(void)
456 if(HWCRHK_LIBNAME)
457 return HWCRHK_LIBNAME;
458 return "nfhwcrhk";
460 static long set_HWCRHK_LIBNAME(const char *name)
462 free_HWCRHK_LIBNAME();
463 return (((HWCRHK_LIBNAME = BUF_strdup(name)) != NULL) ? 1 : 0);
465 static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
466 static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
467 static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
468 #ifndef OPENSSL_NO_RSA
469 static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
470 #endif
471 static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
472 #ifndef OPENSSL_NO_RSA
473 static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
474 static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
475 static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
476 #endif
477 static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
479 /* HWCryptoHook library functions and mechanics - these are used by the
480 * higher-level functions further down. NB: As and where there's no
481 * error checking, take a look lower down where these functions are
482 * called, the checking and error handling is probably down there. */
484 /* utility function to obtain a context */
485 static int get_context(HWCryptoHook_ContextHandle *hac,
486 HWCryptoHook_CallerContext *cac)
488 char tempbuf[1024];
489 HWCryptoHook_ErrMsgBuf rmsg;
491 rmsg.buf = tempbuf;
492 rmsg.size = sizeof(tempbuf);
494 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
495 cac);
496 if (!*hac)
497 return 0;
498 return 1;
501 /* similarly to release one. */
502 static void release_context(HWCryptoHook_ContextHandle hac)
504 p_hwcrhk_Finish(hac);
507 /* Destructor (complements the "ENGINE_chil()" constructor) */
508 static int hwcrhk_destroy(ENGINE *e)
510 free_HWCRHK_LIBNAME();
511 ERR_unload_HWCRHK_strings();
512 return 1;
515 /* (de)initialisation functions. */
516 static int hwcrhk_init(ENGINE *e)
518 HWCryptoHook_Init_t *p1;
519 HWCryptoHook_Finish_t *p2;
520 HWCryptoHook_ModExp_t *p3;
521 #ifndef OPENSSL_NO_RSA
522 HWCryptoHook_RSA_t *p4;
523 HWCryptoHook_RSALoadKey_t *p5;
524 HWCryptoHook_RSAGetPublicKey_t *p6;
525 HWCryptoHook_RSAUnloadKey_t *p7;
526 #endif
527 HWCryptoHook_RandomBytes_t *p8;
528 HWCryptoHook_ModExpCRT_t *p9;
530 if(hwcrhk_dso != NULL)
532 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_ALREADY_LOADED);
533 goto err;
535 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
536 hwcrhk_dso = DSO_load(NULL, get_HWCRHK_LIBNAME(), NULL, 0);
537 if(hwcrhk_dso == NULL)
539 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
540 goto err;
542 if(!(p1 = (HWCryptoHook_Init_t *)
543 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
544 !(p2 = (HWCryptoHook_Finish_t *)
545 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
546 !(p3 = (HWCryptoHook_ModExp_t *)
547 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
548 #ifndef OPENSSL_NO_RSA
549 !(p4 = (HWCryptoHook_RSA_t *)
550 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
551 !(p5 = (HWCryptoHook_RSALoadKey_t *)
552 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
553 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
554 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
555 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
556 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
557 #endif
558 !(p8 = (HWCryptoHook_RandomBytes_t *)
559 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
560 !(p9 = (HWCryptoHook_ModExpCRT_t *)
561 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
563 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_DSO_FAILURE);
564 goto err;
566 /* Copy the pointers */
567 p_hwcrhk_Init = p1;
568 p_hwcrhk_Finish = p2;
569 p_hwcrhk_ModExp = p3;
570 #ifndef OPENSSL_NO_RSA
571 p_hwcrhk_RSA = p4;
572 p_hwcrhk_RSALoadKey = p5;
573 p_hwcrhk_RSAGetPublicKey = p6;
574 p_hwcrhk_RSAUnloadKey = p7;
575 #endif
576 p_hwcrhk_RandomBytes = p8;
577 p_hwcrhk_ModExpCRT = p9;
579 /* Check if the application decided to support dynamic locks,
580 and if it does, use them. */
581 if (disable_mutex_callbacks == 0)
583 if (CRYPTO_get_dynlock_create_callback() != NULL &&
584 CRYPTO_get_dynlock_lock_callback() != NULL &&
585 CRYPTO_get_dynlock_destroy_callback() != NULL)
587 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
588 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
589 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
590 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
594 /* Try and get a context - if not, we may have a DSO but no
595 * accelerator! */
596 if(!get_context(&hwcrhk_context, &password_context))
598 HWCRHKerr(HWCRHK_F_HWCRHK_INIT,HWCRHK_R_UNIT_FAILURE);
599 goto err;
601 /* Everything's fine. */
602 #ifndef OPENSSL_NO_RSA
603 if (hndidx_rsa == -1)
604 hndidx_rsa = RSA_get_ex_new_index(0,
605 "nFast HWCryptoHook RSA key handle",
606 NULL, NULL, hwcrhk_ex_free);
607 #endif
608 return 1;
609 err:
610 if(hwcrhk_dso)
611 DSO_free(hwcrhk_dso);
612 hwcrhk_dso = NULL;
613 p_hwcrhk_Init = NULL;
614 p_hwcrhk_Finish = NULL;
615 p_hwcrhk_ModExp = NULL;
616 #ifndef OPENSSL_NO_RSA
617 p_hwcrhk_RSA = NULL;
618 p_hwcrhk_RSALoadKey = NULL;
619 p_hwcrhk_RSAGetPublicKey = NULL;
620 p_hwcrhk_RSAUnloadKey = NULL;
621 #endif
622 p_hwcrhk_ModExpCRT = NULL;
623 p_hwcrhk_RandomBytes = NULL;
624 return 0;
627 static int hwcrhk_finish(ENGINE *e)
629 int to_return = 1;
630 free_HWCRHK_LIBNAME();
631 if(hwcrhk_dso == NULL)
633 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_NOT_LOADED);
634 to_return = 0;
635 goto err;
637 release_context(hwcrhk_context);
638 if(!DSO_free(hwcrhk_dso))
640 HWCRHKerr(HWCRHK_F_HWCRHK_FINISH,HWCRHK_R_DSO_FAILURE);
641 to_return = 0;
642 goto err;
644 err:
645 if (logstream)
646 BIO_free(logstream);
647 hwcrhk_dso = NULL;
648 p_hwcrhk_Init = NULL;
649 p_hwcrhk_Finish = NULL;
650 p_hwcrhk_ModExp = NULL;
651 #ifndef OPENSSL_NO_RSA
652 p_hwcrhk_RSA = NULL;
653 p_hwcrhk_RSALoadKey = NULL;
654 p_hwcrhk_RSAGetPublicKey = NULL;
655 p_hwcrhk_RSAUnloadKey = NULL;
656 #endif
657 p_hwcrhk_ModExpCRT = NULL;
658 p_hwcrhk_RandomBytes = NULL;
659 return to_return;
662 static int hwcrhk_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
664 int to_return = 1;
666 switch(cmd)
668 case HWCRHK_CMD_SO_PATH:
669 if(hwcrhk_dso)
671 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_ALREADY_LOADED);
672 return 0;
674 if(p == NULL)
676 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,ERR_R_PASSED_NULL_PARAMETER);
677 return 0;
679 return set_HWCRHK_LIBNAME((const char *)p);
680 case ENGINE_CTRL_SET_LOGSTREAM:
682 BIO *bio = (BIO *)p;
684 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
685 if (logstream)
687 BIO_free(logstream);
688 logstream = NULL;
690 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
691 logstream = bio;
692 else
693 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,HWCRHK_R_BIO_WAS_FREED);
695 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
696 break;
697 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
698 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
699 password_context.password_callback = (pem_password_cb *)f;
700 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
701 break;
702 case ENGINE_CTRL_SET_USER_INTERFACE:
703 case HWCRHK_CMD_SET_USER_INTERFACE:
704 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
705 password_context.ui_method = (UI_METHOD *)p;
706 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
707 break;
708 case ENGINE_CTRL_SET_CALLBACK_DATA:
709 case HWCRHK_CMD_SET_CALLBACK_DATA:
710 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
711 password_context.callback_data = p;
712 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
713 break;
714 /* this enables or disables the "SimpleForkCheck" flag used in the
715 * initialisation structure. */
716 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
717 case HWCRHK_CMD_FORK_CHECK:
718 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
719 if(i)
720 hwcrhk_globals.flags |=
721 HWCryptoHook_InitFlags_SimpleForkCheck;
722 else
723 hwcrhk_globals.flags &=
724 ~HWCryptoHook_InitFlags_SimpleForkCheck;
725 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
726 break;
727 /* This will prevent the initialisation function from "installing"
728 * the mutex-handling callbacks, even if they are available from
729 * within the library (or were provided to the library from the
730 * calling application). This is to remove any baggage for
731 * applications not using multithreading. */
732 case ENGINE_CTRL_CHIL_NO_LOCKING:
733 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
734 disable_mutex_callbacks = 1;
735 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
736 break;
737 case HWCRHK_CMD_THREAD_LOCKING:
738 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
739 disable_mutex_callbacks = ((i == 0) ? 0 : 1);
740 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
741 break;
743 /* The command isn't understood by this engine */
744 default:
745 HWCRHKerr(HWCRHK_F_HWCRHK_CTRL,
746 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
747 to_return = 0;
748 break;
751 return to_return;
754 static EVP_PKEY *hwcrhk_load_privkey(ENGINE *eng, const char *key_id,
755 UI_METHOD *ui_method, void *callback_data)
757 #ifndef OPENSSL_NO_RSA
758 RSA *rtmp = NULL;
759 #endif
760 EVP_PKEY *res = NULL;
761 #ifndef OPENSSL_NO_RSA
762 HWCryptoHook_MPI e, n;
763 HWCryptoHook_RSAKeyHandle *hptr;
764 #endif
765 #if !defined(OPENSSL_NO_RSA)
766 char tempbuf[1024];
767 HWCryptoHook_ErrMsgBuf rmsg;
768 HWCryptoHook_PassphraseContext ppctx;
769 #endif
771 #if !defined(OPENSSL_NO_RSA)
772 rmsg.buf = tempbuf;
773 rmsg.size = sizeof(tempbuf);
774 #endif
776 if(!hwcrhk_context)
778 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
779 HWCRHK_R_NOT_INITIALISED);
780 goto err;
782 #ifndef OPENSSL_NO_RSA
783 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
784 if (!hptr)
786 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
787 ERR_R_MALLOC_FAILURE);
788 goto err;
790 ppctx.ui_method = ui_method;
791 ppctx.callback_data = callback_data;
792 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
793 &rmsg, &ppctx))
795 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
796 HWCRHK_R_CHIL_ERROR);
797 ERR_add_error_data(1,rmsg.buf);
798 goto err;
800 if (!*hptr)
802 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
803 HWCRHK_R_NO_KEY);
804 goto err;
806 #endif
807 #ifndef OPENSSL_NO_RSA
808 rtmp = RSA_new_method(eng);
809 RSA_set_ex_data(rtmp, hndidx_rsa, (char *)hptr);
810 rtmp->e = BN_new();
811 rtmp->n = BN_new();
812 rtmp->flags |= RSA_FLAG_EXT_PKEY;
813 MPI2BN(rtmp->e, e);
814 MPI2BN(rtmp->n, n);
815 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
816 != HWCRYPTOHOOK_ERROR_MPISIZE)
818 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,HWCRHK_R_CHIL_ERROR);
819 ERR_add_error_data(1,rmsg.buf);
820 goto err;
823 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
824 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
825 MPI2BN(rtmp->e, e);
826 MPI2BN(rtmp->n, n);
828 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
830 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
831 HWCRHK_R_CHIL_ERROR);
832 ERR_add_error_data(1,rmsg.buf);
833 goto err;
835 rtmp->e->top = e.size / sizeof(BN_ULONG);
836 bn_fix_top(rtmp->e);
837 rtmp->n->top = n.size / sizeof(BN_ULONG);
838 bn_fix_top(rtmp->n);
840 res = EVP_PKEY_new();
841 EVP_PKEY_assign_RSA(res, rtmp);
842 #endif
844 if (!res)
845 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PRIVKEY,
846 HWCRHK_R_PRIVATE_KEY_ALGORITHMS_DISABLED);
848 return res;
849 err:
850 if (res)
851 EVP_PKEY_free(res);
852 #ifndef OPENSSL_NO_RSA
853 if (rtmp)
854 RSA_free(rtmp);
855 #endif
856 return NULL;
859 static EVP_PKEY *hwcrhk_load_pubkey(ENGINE *eng, const char *key_id,
860 UI_METHOD *ui_method, void *callback_data)
862 EVP_PKEY *res = NULL;
864 #ifndef OPENSSL_NO_RSA
865 res = hwcrhk_load_privkey(eng, key_id,
866 ui_method, callback_data);
867 #endif
869 if (res)
870 switch(res->type)
872 #ifndef OPENSSL_NO_RSA
873 case EVP_PKEY_RSA:
875 RSA *rsa = NULL;
877 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
878 rsa = res->pkey.rsa;
879 res->pkey.rsa = RSA_new();
880 res->pkey.rsa->n = rsa->n;
881 res->pkey.rsa->e = rsa->e;
882 rsa->n = NULL;
883 rsa->e = NULL;
884 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
885 RSA_free(rsa);
887 break;
888 #endif
889 default:
890 HWCRHKerr(HWCRHK_F_HWCRHK_LOAD_PUBKEY,
891 HWCRHK_R_CTRL_COMMAND_NOT_IMPLEMENTED);
892 goto err;
895 return res;
896 err:
897 if (res)
898 EVP_PKEY_free(res);
899 return NULL;
902 /* A little mod_exp */
903 static int hwcrhk_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
904 const BIGNUM *m, BN_CTX *ctx)
906 char tempbuf[1024];
907 HWCryptoHook_ErrMsgBuf rmsg;
908 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
909 we use them directly, plus a little macro magic. We only
910 thing we need to make sure of is that enough space is allocated. */
911 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
912 int to_return, ret;
914 to_return = 0; /* expect failure */
915 rmsg.buf = tempbuf;
916 rmsg.size = sizeof(tempbuf);
918 if(!hwcrhk_context)
920 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
921 goto err;
923 /* Prepare the params */
924 bn_expand2(r, m->top); /* Check for error !! */
925 BN2MPI(m_a, a);
926 BN2MPI(m_p, p);
927 BN2MPI(m_n, m);
928 MPI2BN(r, m_r);
930 /* Perform the operation */
931 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
933 /* Convert the response */
934 r->top = m_r.size / sizeof(BN_ULONG);
935 bn_fix_top(r);
937 if (ret < 0)
939 /* FIXME: When this error is returned, HWCryptoHook is
940 telling us that falling back to software computation
941 might be a good thing. */
942 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
944 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FALLBACK);
946 else
948 HWCRHKerr(HWCRHK_F_HWCRHK_MOD_EXP,HWCRHK_R_REQUEST_FAILED);
950 ERR_add_error_data(1,rmsg.buf);
951 goto err;
954 to_return = 1;
955 err:
956 return to_return;
959 #ifndef OPENSSL_NO_RSA
960 static int hwcrhk_rsa_mod_exp(BIGNUM *r, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
962 char tempbuf[1024];
963 HWCryptoHook_ErrMsgBuf rmsg;
964 HWCryptoHook_RSAKeyHandle *hptr;
965 int to_return = 0, ret;
967 rmsg.buf = tempbuf;
968 rmsg.size = sizeof(tempbuf);
970 if(!hwcrhk_context)
972 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,HWCRHK_R_NOT_INITIALISED);
973 goto err;
976 /* This provides support for nForce keys. Since that's opaque data
977 all we do is provide a handle to the proper key and let HWCryptoHook
978 take care of the rest. */
979 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx_rsa))
980 != NULL)
982 HWCryptoHook_MPI m_a, m_r;
984 if(!rsa->n)
986 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
987 HWCRHK_R_MISSING_KEY_COMPONENTS);
988 goto err;
991 /* Prepare the params */
992 bn_expand2(r, rsa->n->top); /* Check for error !! */
993 BN2MPI(m_a, I);
994 MPI2BN(r, m_r);
996 /* Perform the operation */
997 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
999 /* Convert the response */
1000 r->top = m_r.size / sizeof(BN_ULONG);
1001 bn_fix_top(r);
1003 if (ret < 0)
1005 /* FIXME: When this error is returned, HWCryptoHook is
1006 telling us that falling back to software computation
1007 might be a good thing. */
1008 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1010 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1011 HWCRHK_R_REQUEST_FALLBACK);
1013 else
1015 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1016 HWCRHK_R_REQUEST_FAILED);
1018 ERR_add_error_data(1,rmsg.buf);
1019 goto err;
1022 else
1024 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
1026 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
1028 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1029 HWCRHK_R_MISSING_KEY_COMPONENTS);
1030 goto err;
1033 /* Prepare the params */
1034 bn_expand2(r, rsa->n->top); /* Check for error !! */
1035 BN2MPI(m_a, I);
1036 BN2MPI(m_p, rsa->p);
1037 BN2MPI(m_q, rsa->q);
1038 BN2MPI(m_dmp1, rsa->dmp1);
1039 BN2MPI(m_dmq1, rsa->dmq1);
1040 BN2MPI(m_iqmp, rsa->iqmp);
1041 MPI2BN(r, m_r);
1043 /* Perform the operation */
1044 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
1045 m_dmp1, m_dmq1, m_iqmp, &m_r, &rmsg);
1047 /* Convert the response */
1048 r->top = m_r.size / sizeof(BN_ULONG);
1049 bn_fix_top(r);
1051 if (ret < 0)
1053 /* FIXME: When this error is returned, HWCryptoHook is
1054 telling us that falling back to software computation
1055 might be a good thing. */
1056 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1058 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1059 HWCRHK_R_REQUEST_FALLBACK);
1061 else
1063 HWCRHKerr(HWCRHK_F_HWCRHK_RSA_MOD_EXP,
1064 HWCRHK_R_REQUEST_FAILED);
1066 ERR_add_error_data(1,rmsg.buf);
1067 goto err;
1070 /* If we're here, we must be here with some semblance of success :-) */
1071 to_return = 1;
1072 err:
1073 return to_return;
1075 #endif
1077 #ifndef OPENSSL_NO_RSA
1078 /* This function is aliased to mod_exp (with the mont stuff dropped). */
1079 static int hwcrhk_mod_exp_mont(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
1080 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1082 return hwcrhk_mod_exp(r, a, p, m, ctx);
1084 #endif
1086 #ifndef OPENSSL_NO_DH
1087 /* This function is aliased to mod_exp (with the dh and mont dropped). */
1088 static int hwcrhk_mod_exp_dh(const DH *dh, BIGNUM *r,
1089 const BIGNUM *a, const BIGNUM *p,
1090 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
1092 return hwcrhk_mod_exp(r, a, p, m, ctx);
1094 #endif
1096 /* Random bytes are good */
1097 static int hwcrhk_rand_bytes(unsigned char *buf, int num)
1099 char tempbuf[1024];
1100 HWCryptoHook_ErrMsgBuf rmsg;
1101 int to_return = 0; /* assume failure */
1102 int ret;
1104 rmsg.buf = tempbuf;
1105 rmsg.size = sizeof(tempbuf);
1107 if(!hwcrhk_context)
1109 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,HWCRHK_R_NOT_INITIALISED);
1110 goto err;
1113 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
1114 if (ret < 0)
1116 /* FIXME: When this error is returned, HWCryptoHook is
1117 telling us that falling back to software computation
1118 might be a good thing. */
1119 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
1121 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1122 HWCRHK_R_REQUEST_FALLBACK);
1124 else
1126 HWCRHKerr(HWCRHK_F_HWCRHK_RAND_BYTES,
1127 HWCRHK_R_REQUEST_FAILED);
1129 ERR_add_error_data(1,rmsg.buf);
1130 goto err;
1132 to_return = 1;
1133 err:
1134 return to_return;
1137 static int hwcrhk_rand_status(void)
1139 return 1;
1142 /* This cleans up an RSA KM key, called when ex_data is freed */
1143 #ifndef OPENSSL_NO_RSA
1144 static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
1145 int ind,long argl, void *argp)
1147 char tempbuf[1024];
1148 HWCryptoHook_ErrMsgBuf rmsg;
1149 #ifndef OPENSSL_NO_RSA
1150 HWCryptoHook_RSAKeyHandle *hptr;
1151 #endif
1152 #if !defined(OPENSSL_NO_RSA)
1153 int ret;
1154 #endif
1156 rmsg.buf = tempbuf;
1157 rmsg.size = sizeof(tempbuf);
1159 #ifndef OPENSSL_NO_RSA
1160 hptr = (HWCryptoHook_RSAKeyHandle *) item;
1161 if(hptr)
1163 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
1164 OPENSSL_free(hptr);
1166 #endif
1168 #endif
1170 /* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
1171 * these just wrap the POSIX functions and add some logging.
1174 static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
1175 HWCryptoHook_CallerContext *cactx)
1177 mt->lockid = CRYPTO_get_new_dynlockid();
1178 if (mt->lockid == 0)
1179 return 1; /* failure */
1180 return 0; /* success */
1183 static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
1185 CRYPTO_w_lock(mt->lockid);
1186 return 0;
1189 static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
1191 CRYPTO_w_unlock(mt->lockid);
1194 static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
1196 CRYPTO_destroy_dynlockid(mt->lockid);
1199 static int hwcrhk_get_pass(const char *prompt_info,
1200 int *len_io, char *buf,
1201 HWCryptoHook_PassphraseContext *ppctx,
1202 HWCryptoHook_CallerContext *cactx)
1204 pem_password_cb *callback = NULL;
1205 void *callback_data = NULL;
1206 UI_METHOD *ui_method = NULL;
1208 if (cactx)
1210 if (cactx->ui_method)
1211 ui_method = cactx->ui_method;
1212 if (cactx->password_callback)
1213 callback = cactx->password_callback;
1214 if (cactx->callback_data)
1215 callback_data = cactx->callback_data;
1217 if (ppctx)
1219 if (ppctx->ui_method)
1221 ui_method = ppctx->ui_method;
1222 callback = NULL;
1224 if (ppctx->callback_data)
1225 callback_data = ppctx->callback_data;
1227 if (callback == NULL && ui_method == NULL)
1229 HWCRHKerr(HWCRHK_F_HWCRHK_GET_PASS,HWCRHK_R_NO_CALLBACK);
1230 return -1;
1233 if (ui_method)
1235 UI *ui = UI_new_method(ui_method);
1236 if (ui)
1238 int ok;
1239 char *prompt = UI_construct_prompt(ui,
1240 "pass phrase", prompt_info);
1242 ok = UI_add_input_string(ui,prompt,
1243 UI_INPUT_FLAG_DEFAULT_PWD,
1244 buf,0,(*len_io) - 1);
1245 UI_add_user_data(ui, callback_data);
1246 UI_ctrl(ui, UI_CTRL_PRINT_ERRORS, 1, 0, 0);
1248 if (ok >= 0)
1251 ok=UI_process(ui);
1253 while (ok < 0 && UI_ctrl(ui, UI_CTRL_IS_REDOABLE, 0, 0, 0));
1255 if (ok >= 0)
1256 *len_io = strlen(buf);
1258 UI_free(ui);
1259 OPENSSL_free(prompt);
1262 else
1264 *len_io = callback(buf, *len_io, 0, callback_data);
1266 if(!*len_io)
1267 return -1;
1268 return 0;
1271 static int hwcrhk_insert_card(const char *prompt_info,
1272 const char *wrong_info,
1273 HWCryptoHook_PassphraseContext *ppctx,
1274 HWCryptoHook_CallerContext *cactx)
1276 int ok = -1;
1277 UI *ui;
1278 void *callback_data = NULL;
1279 UI_METHOD *ui_method = NULL;
1281 if (cactx)
1283 if (cactx->ui_method)
1284 ui_method = cactx->ui_method;
1285 if (cactx->callback_data)
1286 callback_data = cactx->callback_data;
1288 if (ppctx)
1290 if (ppctx->ui_method)
1291 ui_method = ppctx->ui_method;
1292 if (ppctx->callback_data)
1293 callback_data = ppctx->callback_data;
1295 if (ui_method == NULL)
1297 HWCRHKerr(HWCRHK_F_HWCRHK_INSERT_CARD,
1298 HWCRHK_R_NO_CALLBACK);
1299 return -1;
1302 ui = UI_new_method(ui_method);
1304 if (ui)
1306 char answer;
1307 char buf[BUFSIZ];
1309 if (wrong_info)
1310 BIO_snprintf(buf, sizeof(buf)-1,
1311 "Current card: \"%s\"\n", wrong_info);
1312 ok = UI_dup_info_string(ui, buf);
1313 if (ok >= 0 && prompt_info)
1315 BIO_snprintf(buf, sizeof(buf)-1,
1316 "Insert card \"%s\"", prompt_info);
1317 ok = UI_dup_input_boolean(ui, buf,
1318 "\n then hit <enter> or C<enter> to cancel\n",
1319 "\r\n", "Cc", UI_INPUT_FLAG_ECHO, &answer);
1321 UI_add_user_data(ui, callback_data);
1323 if (ok >= 0)
1324 ok = UI_process(ui);
1325 UI_free(ui);
1327 if (ok == -2 || (ok >= 0 && answer == 'C'))
1328 ok = 1;
1329 else if (ok < 0)
1330 ok = -1;
1331 else
1332 ok = 0;
1334 return ok;
1337 static void hwcrhk_log_message(void *logstr, const char *message)
1339 BIO *lstream = NULL;
1341 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1342 if (logstr)
1343 lstream=*(BIO **)logstr;
1344 if (lstream)
1346 BIO_printf(lstream, "%s\n", message);
1348 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1351 /* This stuff is needed if this ENGINE is being compiled into a self-contained
1352 * shared-library. */
1353 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
1354 static int bind_fn(ENGINE *e, const char *id)
1356 if(id && (strcmp(id, engine_hwcrhk_id) != 0) &&
1357 (strcmp(id, engine_hwcrhk_id_alt) != 0))
1358 return 0;
1359 if(!bind_helper(e))
1360 return 0;
1361 return 1;
1363 IMPLEMENT_DYNAMIC_CHECK_FN()
1364 IMPLEMENT_DYNAMIC_BIND_FN(bind_fn)
1365 #endif /* OPENSSL_NO_DYNAMIC_ENGINE */
1367 #endif /* !OPENSSL_NO_HW_CHIL */
1368 #endif /* !OPENSSL_NO_HW */