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