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