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