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