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