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