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.c1019
1 files changed, 1019 insertions, 0 deletions
diff --git a/src/lib/libcrypto/engine/hw_ncipher.c b/src/lib/libcrypto/engine/hw_ncipher.c
new file mode 100644
index 0000000000..41f5900676
--- /dev/null
+++ b/src/lib/libcrypto/engine/hw_ncipher.c
@@ -0,0 +1,1019 @@
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 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 <openssl/crypto.h>
62#include <openssl/pem.h>
63#include "cryptlib.h"
64#include <openssl/dso.h>
65#include "engine_int.h"
66#include <openssl/engine.h>
67
68#ifndef NO_HW
69#ifndef NO_HW_NCIPHER
70
71/* Attribution notice: nCipher have said several times that it's OK for
72 * us to implement a general interface to their boxes, and recently declared
73 * their HWCryptoHook to be public, and therefore available for us to use.
74 * Thanks, nCipher.
75 *
76 * The hwcryptohook.h included here is from May 2000.
77 * [Richard Levitte]
78 */
79#ifdef FLAT_INC
80#include "hwcryptohook.h"
81#else
82#include "vendor_defns/hwcryptohook.h"
83#endif
84
85static int hwcrhk_init(void);
86static int hwcrhk_finish(void);
87static int hwcrhk_ctrl(int cmd, long i, void *p, void (*f)());
88
89/* Functions to handle mutexes */
90static int hwcrhk_mutex_init(HWCryptoHook_Mutex*, HWCryptoHook_CallerContext*);
91static int hwcrhk_mutex_lock(HWCryptoHook_Mutex*);
92static void hwcrhk_mutex_unlock(HWCryptoHook_Mutex*);
93static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex*);
94
95/* BIGNUM stuff */
96static int hwcrhk_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
97 const BIGNUM *m, BN_CTX *ctx);
98
99/* RSA stuff */
100static int hwcrhk_rsa_mod_exp(BIGNUM *r, BIGNUM *I, RSA *rsa);
101/* This function is aliased to mod_exp (with the mont stuff dropped). */
102static int hwcrhk_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
103 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
104
105/* DH stuff */
106/* This function is alised to mod_exp (with the DH and mont dropped). */
107static int hwcrhk_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
108 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
109
110/* RAND stuff */
111static int hwcrhk_rand_bytes(unsigned char *buf, int num);
112static int hwcrhk_rand_status(void);
113
114/* KM stuff */
115static EVP_PKEY *hwcrhk_load_privkey(const char *key_id,
116 const char *passphrase);
117static EVP_PKEY *hwcrhk_load_pubkey(const char *key_id,
118 const char *passphrase);
119static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
120 int index,long argl, void *argp);
121
122/* Interaction stuff */
123static int hwcrhk_get_pass(const char *prompt_info,
124 int *len_io, char *buf,
125 HWCryptoHook_PassphraseContext *ppctx,
126 HWCryptoHook_CallerContext *cactx);
127static void hwcrhk_log_message(void *logstream, const char *message);
128
129/* Our internal RSA_METHOD that we provide pointers to */
130static RSA_METHOD hwcrhk_rsa =
131 {
132 "nCipher RSA method",
133 NULL,
134 NULL,
135 NULL,
136 NULL,
137 hwcrhk_rsa_mod_exp,
138 hwcrhk_mod_exp_mont,
139 NULL,
140 NULL,
141 0,
142 NULL,
143 NULL,
144 NULL
145 };
146
147/* Our internal DH_METHOD that we provide pointers to */
148static DH_METHOD hwcrhk_dh =
149 {
150 "nCipher DH method",
151 NULL,
152 NULL,
153 hwcrhk_mod_exp_dh,
154 NULL,
155 NULL,
156 0,
157 NULL
158 };
159
160static RAND_METHOD hwcrhk_rand =
161 {
162 /* "nCipher RAND method", */
163 NULL,
164 hwcrhk_rand_bytes,
165 NULL,
166 NULL,
167 hwcrhk_rand_bytes,
168 hwcrhk_rand_status,
169 };
170
171/* Our ENGINE structure. */
172static ENGINE engine_hwcrhk =
173 {
174 "chil",
175 "nCipher hardware engine support",
176 &hwcrhk_rsa,
177 NULL,
178 &hwcrhk_dh,
179 &hwcrhk_rand,
180 hwcrhk_mod_exp,
181 NULL,
182 hwcrhk_init,
183 hwcrhk_finish,
184 hwcrhk_ctrl,
185 hwcrhk_load_privkey,
186 hwcrhk_load_pubkey,
187 0, /* no flags */
188 0, 0, /* no references */
189 NULL, NULL /* unlinked */
190 };
191
192/* Internal stuff for HWCryptoHook */
193
194/* Some structures needed for proper use of thread locks */
195/* hwcryptohook.h has some typedefs that turn struct HWCryptoHook_MutexValue
196 into HWCryptoHook_Mutex */
197struct HWCryptoHook_MutexValue
198 {
199 int lockid;
200 };
201
202/* hwcryptohook.h has some typedefs that turn
203 struct HWCryptoHook_PassphraseContextValue
204 into HWCryptoHook_PassphraseContext */
205struct HWCryptoHook_PassphraseContextValue
206 {
207 void *any;
208 };
209
210/* hwcryptohook.h has some typedefs that turn
211 struct HWCryptoHook_CallerContextValue
212 into HWCryptoHook_CallerContext */
213struct HWCryptoHook_CallerContextValue
214 {
215 void *any;
216 };
217
218/* The MPI structure in HWCryptoHook is pretty compatible with OpenSSL
219 BIGNUM's, so lets define a couple of conversion macros */
220#define BN2MPI(mp, bn) \
221 {mp.size = bn->top * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
222#define MPI2BN(bn, mp) \
223 {mp.size = bn->dmax * sizeof(BN_ULONG); mp.buf = (unsigned char *)bn->d;}
224
225#if 0 /* Card and password management is not yet supported */
226/* HWCryptoHook callbacks. insert_card() and get_pass() are not yet
227 defined, because we haven't quite decided on the proper form yet.
228 log_message() just adds an entry in the error stack. I don't know
229 if that's good or bad... */
230static int insert_card(const char *prompt_info,
231 const char *wrong_info,
232 HWCryptoHook_PassphraseContext *ppctx,
233 HWCryptoHook_CallerContext *cactx);
234static int get_pass(const char *prompt_info,
235 int *len_io, char *buf,
236 HWCryptoHook_PassphraseContext *ppctx,
237 HWCryptoHook_CallerContext *cactx);
238#endif
239
240static BIO *logstream = NULL;
241static pem_password_cb *password_callback = NULL;
242#if 0
243static void *password_callback_userdata = NULL;
244#endif
245static int disable_mutex_callbacks = 0;
246
247/* Stuff to pass to the HWCryptoHook library */
248static HWCryptoHook_InitInfo hwcrhk_globals = {
249 0, /* Flags */
250 &logstream, /* logstream */
251 sizeof(BN_ULONG), /* limbsize */
252 0, /* mslimb first: false for BNs */
253 -1, /* msbyte first: use native */
254 0, /* Max mutexes, 0 = no small limit */
255 0, /* Max simultaneous, 0 = default */
256
257 /* The next few are mutex stuff: we write wrapper functions
258 around the OS mutex functions. We initialise them to 0
259 here, and change that to actual function pointers in hwcrhk_init()
260 if dynamic locks are supported (that is, if the application
261 programmer has made sure of setting up callbacks bafore starting
262 this engine) *and* if disable_mutex_callbacks hasn't been set by
263 a call to ENGINE_ctrl(ENGINE_CTRL_CHIL_NO_LOCKING). */
264 sizeof(HWCryptoHook_Mutex),
265 0,
266 0,
267 0,
268 0,
269
270 /* The next few are condvar stuff: we write wrapper functions
271 round the OS functions. Currently not implemented and not
272 and absolute necessity even in threaded programs, therefore
273 0'ed. Will hopefully be implemented some day, since it
274 enhances the efficiency of HWCryptoHook. */
275 0, /* sizeof(HWCryptoHook_CondVar), */
276 0, /* hwcrhk_cv_init, */
277 0, /* hwcrhk_cv_wait, */
278 0, /* hwcrhk_cv_signal, */
279 0, /* hwcrhk_cv_broadcast, */
280 0, /* hwcrhk_cv_destroy, */
281
282 hwcrhk_get_pass, /* pass phrase */
283 0, /* insert_card, */ /* insert a card */
284 hwcrhk_log_message /* Log message */
285};
286
287
288/* Now, to our own code */
289
290/* As this is only ever called once, there's no need for locking
291 * (indeed - the lock will already be held by our caller!!!) */
292ENGINE *ENGINE_ncipher()
293 {
294 RSA_METHOD *meth1;
295 DH_METHOD *meth2;
296
297 /* We know that the "PKCS1_SSLeay()" functions hook properly
298 * to the cswift-specific mod_exp and mod_exp_crt so we use
299 * those functions. NB: We don't use ENGINE_openssl() or
300 * anything "more generic" because something like the RSAref
301 * code may not hook properly, and if you own one of these
302 * cards then you have the right to do RSA operations on it
303 * anyway! */
304 meth1 = RSA_PKCS1_SSLeay();
305 hwcrhk_rsa.rsa_pub_enc = meth1->rsa_pub_enc;
306 hwcrhk_rsa.rsa_pub_dec = meth1->rsa_pub_dec;
307 hwcrhk_rsa.rsa_priv_enc = meth1->rsa_priv_enc;
308 hwcrhk_rsa.rsa_priv_dec = meth1->rsa_priv_dec;
309
310 /* Much the same for Diffie-Hellman */
311 meth2 = DH_OpenSSL();
312 hwcrhk_dh.generate_key = meth2->generate_key;
313 hwcrhk_dh.compute_key = meth2->compute_key;
314 return &engine_hwcrhk;
315 }
316
317/* This is a process-global DSO handle used for loading and unloading
318 * the HWCryptoHook library. NB: This is only set (or unset) during an
319 * init() or finish() call (reference counts permitting) and they're
320 * operating with global locks, so this should be thread-safe
321 * implicitly. */
322static DSO *hwcrhk_dso = NULL;
323static HWCryptoHook_ContextHandle hwcrhk_context = 0;
324static int hndidx = -1; /* Index for KM handle. Not really used yet. */
325
326/* These are the function pointers that are (un)set when the library has
327 * successfully (un)loaded. */
328static HWCryptoHook_Init_t *p_hwcrhk_Init = NULL;
329static HWCryptoHook_Finish_t *p_hwcrhk_Finish = NULL;
330static HWCryptoHook_ModExp_t *p_hwcrhk_ModExp = NULL;
331static HWCryptoHook_RSA_t *p_hwcrhk_RSA = NULL;
332static HWCryptoHook_RandomBytes_t *p_hwcrhk_RandomBytes = NULL;
333static HWCryptoHook_RSALoadKey_t *p_hwcrhk_RSALoadKey = NULL;
334static HWCryptoHook_RSAGetPublicKey_t *p_hwcrhk_RSAGetPublicKey = NULL;
335static HWCryptoHook_RSAUnloadKey_t *p_hwcrhk_RSAUnloadKey = NULL;
336static HWCryptoHook_ModExpCRT_t *p_hwcrhk_ModExpCRT = NULL;
337
338/* Used in the DSO operations. */
339static const char *HWCRHK_LIBNAME = "nfhwcrhk";
340static const char *n_hwcrhk_Init = "HWCryptoHook_Init";
341static const char *n_hwcrhk_Finish = "HWCryptoHook_Finish";
342static const char *n_hwcrhk_ModExp = "HWCryptoHook_ModExp";
343static const char *n_hwcrhk_RSA = "HWCryptoHook_RSA";
344static const char *n_hwcrhk_RandomBytes = "HWCryptoHook_RandomBytes";
345static const char *n_hwcrhk_RSALoadKey = "HWCryptoHook_RSALoadKey";
346static const char *n_hwcrhk_RSAGetPublicKey = "HWCryptoHook_RSAGetPublicKey";
347static const char *n_hwcrhk_RSAUnloadKey = "HWCryptoHook_RSAUnloadKey";
348static const char *n_hwcrhk_ModExpCRT = "HWCryptoHook_ModExpCRT";
349
350/* HWCryptoHook library functions and mechanics - these are used by the
351 * higher-level functions further down. NB: As and where there's no
352 * error checking, take a look lower down where these functions are
353 * called, the checking and error handling is probably down there. */
354
355/* utility function to obtain a context */
356static int get_context(HWCryptoHook_ContextHandle *hac)
357 {
358 char tempbuf[1024];
359 HWCryptoHook_ErrMsgBuf rmsg;
360
361 rmsg.buf = tempbuf;
362 rmsg.size = 1024;
363
364 *hac = p_hwcrhk_Init(&hwcrhk_globals, sizeof(hwcrhk_globals), &rmsg,
365 NULL);
366 if (!*hac)
367 return 0;
368 return 1;
369 }
370
371/* similarly to release one. */
372static void release_context(HWCryptoHook_ContextHandle hac)
373 {
374 p_hwcrhk_Finish(hac);
375 }
376
377/* (de)initialisation functions. */
378static int hwcrhk_init()
379 {
380 HWCryptoHook_Init_t *p1;
381 HWCryptoHook_Finish_t *p2;
382 HWCryptoHook_ModExp_t *p3;
383 HWCryptoHook_RSA_t *p4;
384 HWCryptoHook_RSALoadKey_t *p5;
385 HWCryptoHook_RSAGetPublicKey_t *p6;
386 HWCryptoHook_RSAUnloadKey_t *p7;
387 HWCryptoHook_RandomBytes_t *p8;
388 HWCryptoHook_ModExpCRT_t *p9;
389
390 if(hwcrhk_dso != NULL)
391 {
392 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_ALREADY_LOADED);
393 goto err;
394 }
395 /* Attempt to load libnfhwcrhk.so/nfhwcrhk.dll/whatever. */
396 hwcrhk_dso = DSO_load(NULL, HWCRHK_LIBNAME, NULL,
397 DSO_FLAG_NAME_TRANSLATION);
398 if(hwcrhk_dso == NULL)
399 {
400 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
401 goto err;
402 }
403 if(!(p1 = (HWCryptoHook_Init_t *)
404 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Init)) ||
405 !(p2 = (HWCryptoHook_Finish_t *)
406 DSO_bind_func(hwcrhk_dso, n_hwcrhk_Finish)) ||
407 !(p3 = (HWCryptoHook_ModExp_t *)
408 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExp)) ||
409 !(p4 = (HWCryptoHook_RSA_t *)
410 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSA)) ||
411 !(p5 = (HWCryptoHook_RSALoadKey_t *)
412 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSALoadKey)) ||
413 !(p6 = (HWCryptoHook_RSAGetPublicKey_t *)
414 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAGetPublicKey)) ||
415 !(p7 = (HWCryptoHook_RSAUnloadKey_t *)
416 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RSAUnloadKey)) ||
417 !(p8 = (HWCryptoHook_RandomBytes_t *)
418 DSO_bind_func(hwcrhk_dso, n_hwcrhk_RandomBytes)) ||
419 !(p9 = (HWCryptoHook_ModExpCRT_t *)
420 DSO_bind_func(hwcrhk_dso, n_hwcrhk_ModExpCRT)))
421 {
422 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_DSO_FAILURE);
423 goto err;
424 }
425 /* Copy the pointers */
426 p_hwcrhk_Init = p1;
427 p_hwcrhk_Finish = p2;
428 p_hwcrhk_ModExp = p3;
429 p_hwcrhk_RSA = p4;
430 p_hwcrhk_RSALoadKey = p5;
431 p_hwcrhk_RSAGetPublicKey = p6;
432 p_hwcrhk_RSAUnloadKey = p7;
433 p_hwcrhk_RandomBytes = p8;
434 p_hwcrhk_ModExpCRT = p9;
435
436 /* Check if the application decided to support dynamic locks,
437 and if it does, use them. */
438 if (disable_mutex_callbacks == 0 &&
439 CRYPTO_get_dynlock_create_callback() != NULL &&
440 CRYPTO_get_dynlock_lock_callback() != NULL &&
441 CRYPTO_get_dynlock_destroy_callback() != NULL)
442 {
443 hwcrhk_globals.mutex_init = hwcrhk_mutex_init;
444 hwcrhk_globals.mutex_acquire = hwcrhk_mutex_lock;
445 hwcrhk_globals.mutex_release = hwcrhk_mutex_unlock;
446 hwcrhk_globals.mutex_destroy = hwcrhk_mutex_destroy;
447 }
448
449 /* Try and get a context - if not, we may have a DSO but no
450 * accelerator! */
451 if(!get_context(&hwcrhk_context))
452 {
453 ENGINEerr(ENGINE_F_HWCRHK_INIT,ENGINE_R_UNIT_FAILURE);
454 goto err;
455 }
456 /* Everything's fine. */
457 if (hndidx == -1)
458 hndidx = RSA_get_ex_new_index(0,
459 "nFast HWCryptoHook RSA key handle",
460 NULL, NULL, hwcrhk_ex_free);
461 return 1;
462err:
463 if(hwcrhk_dso)
464 DSO_free(hwcrhk_dso);
465 hwcrhk_dso = NULL;
466 p_hwcrhk_Init = NULL;
467 p_hwcrhk_Finish = NULL;
468 p_hwcrhk_ModExp = NULL;
469 p_hwcrhk_RSA = NULL;
470 p_hwcrhk_RSALoadKey = NULL;
471 p_hwcrhk_RSAGetPublicKey = NULL;
472 p_hwcrhk_RSAUnloadKey = NULL;
473 p_hwcrhk_ModExpCRT = NULL;
474 p_hwcrhk_RandomBytes = NULL;
475 return 0;
476 }
477
478static int hwcrhk_finish()
479 {
480 int to_return = 1;
481 if(hwcrhk_dso == NULL)
482 {
483 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_NOT_LOADED);
484 to_return = 0;
485 goto err;
486 }
487 release_context(hwcrhk_context);
488 if(!DSO_free(hwcrhk_dso))
489 {
490 ENGINEerr(ENGINE_F_HWCRHK_FINISH,ENGINE_R_DSO_FAILURE);
491 to_return = 0;
492 goto err;
493 }
494 err:
495 if (logstream)
496 BIO_free(logstream);
497 hwcrhk_dso = NULL;
498 p_hwcrhk_Init = NULL;
499 p_hwcrhk_Finish = NULL;
500 p_hwcrhk_ModExp = NULL;
501 p_hwcrhk_RSA = NULL;
502 p_hwcrhk_RSALoadKey = NULL;
503 p_hwcrhk_RSAGetPublicKey = NULL;
504 p_hwcrhk_RSAUnloadKey = NULL;
505 p_hwcrhk_ModExpCRT = NULL;
506 p_hwcrhk_RandomBytes = NULL;
507 return to_return;
508 }
509
510static int hwcrhk_ctrl(int cmd, long i, void *p, void (*f)())
511 {
512 int to_return = 1;
513
514 switch(cmd)
515 {
516 case ENGINE_CTRL_SET_LOGSTREAM:
517 {
518 BIO *bio = (BIO *)p;
519
520 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
521 if (logstream)
522 {
523 BIO_free(logstream);
524 logstream = NULL;
525 }
526 if (CRYPTO_add(&bio->references,1,CRYPTO_LOCK_BIO) > 1)
527 logstream = bio;
528 else
529 ENGINEerr(ENGINE_F_HWCRHK_CTRL,ENGINE_R_BIO_WAS_FREED);
530 }
531 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
532 break;
533 case ENGINE_CTRL_SET_PASSWORD_CALLBACK:
534 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
535 password_callback = (pem_password_cb *)f;
536 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
537 break;
538 /* this enables or disables the "SimpleForkCheck" flag used in the
539 * initialisation structure. */
540 case ENGINE_CTRL_CHIL_SET_FORKCHECK:
541 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
542 if(i)
543 hwcrhk_globals.flags |=
544 HWCryptoHook_InitFlags_SimpleForkCheck;
545 else
546 hwcrhk_globals.flags &=
547 ~HWCryptoHook_InitFlags_SimpleForkCheck;
548 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
549 break;
550 /* This will prevent the initialisation function from "installing"
551 * the mutex-handling callbacks, even if they are available from
552 * within the library (or were provided to the library from the
553 * calling application). This is to remove any baggage for
554 * applications not using multithreading. */
555 case ENGINE_CTRL_CHIL_NO_LOCKING:
556 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
557 disable_mutex_callbacks = 1;
558 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
559 break;
560
561 /* The command isn't understood by this engine */
562 default:
563 ENGINEerr(ENGINE_F_HWCRHK_CTRL,
564 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
565 to_return = 0;
566 break;
567 }
568
569 return to_return;
570 }
571
572static EVP_PKEY *hwcrhk_load_privkey(const char *key_id,
573 const char *passphrase)
574 {
575 RSA *rtmp = NULL;
576 EVP_PKEY *res = NULL;
577 HWCryptoHook_MPI e, n;
578 HWCryptoHook_RSAKeyHandle *hptr;
579 HWCryptoHook_ErrMsgBuf rmsg;
580
581 if(!hwcrhk_context)
582 {
583 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
584 ENGINE_R_NOT_INITIALISED);
585 goto err;
586 }
587 hptr = OPENSSL_malloc(sizeof(HWCryptoHook_RSAKeyHandle));
588 if (!hptr)
589 {
590 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
591 ERR_R_MALLOC_FAILURE);
592 goto err;
593 }
594 if (p_hwcrhk_RSALoadKey(hwcrhk_context, key_id, hptr,
595 &rmsg, NULL))
596 {
597 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
598 ENGINE_R_CHIL_ERROR);
599 ERR_add_error_data(1,rmsg.buf);
600 goto err;
601 }
602 if (!*hptr)
603 {
604 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PRIVKEY,
605 ENGINE_R_NO_KEY);
606 goto err;
607 }
608 rtmp = RSA_new_method(&engine_hwcrhk);
609 RSA_set_ex_data(rtmp, hndidx, (char *)hptr);
610 rtmp->e = BN_new();
611 rtmp->n = BN_new();
612 rtmp->flags |= RSA_FLAG_EXT_PKEY;
613 MPI2BN(rtmp->e, e);
614 MPI2BN(rtmp->n, n);
615 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg)
616 != HWCRYPTOHOOK_ERROR_MPISIZE)
617 {
618 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,ENGINE_R_CHIL_ERROR);
619 ERR_add_error_data(1,rmsg.buf);
620 goto err;
621 }
622
623 bn_expand2(rtmp->e, e.size/sizeof(BN_ULONG));
624 bn_expand2(rtmp->n, n.size/sizeof(BN_ULONG));
625 MPI2BN(rtmp->e, e);
626 MPI2BN(rtmp->n, n);
627
628 if (p_hwcrhk_RSAGetPublicKey(*hptr, &n, &e, &rmsg))
629 {
630 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
631 ENGINE_R_CHIL_ERROR);
632 ERR_add_error_data(1,rmsg.buf);
633 goto err;
634 }
635 rtmp->e->top = e.size / sizeof(BN_ULONG);
636 bn_fix_top(rtmp->e);
637 rtmp->n->top = n.size / sizeof(BN_ULONG);
638 bn_fix_top(rtmp->n);
639
640 res = EVP_PKEY_new();
641 EVP_PKEY_assign_RSA(res, rtmp);
642
643 return res;
644 err:
645 if (res)
646 EVP_PKEY_free(res);
647 if (rtmp)
648 RSA_free(rtmp);
649 return NULL;
650 }
651
652static EVP_PKEY *hwcrhk_load_pubkey(const char *key_id, const char *passphrase)
653 {
654 EVP_PKEY *res = hwcrhk_load_privkey(key_id, passphrase);
655
656 if (res)
657 switch(res->type)
658 {
659 case EVP_PKEY_RSA:
660 {
661 RSA *rsa = NULL;
662
663 CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
664 rsa = res->pkey.rsa;
665 res->pkey.rsa = RSA_new();
666 res->pkey.rsa->n = rsa->n;
667 res->pkey.rsa->e = rsa->e;
668 CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
669 RSA_free(rsa);
670 }
671 default:
672 ENGINEerr(ENGINE_F_HWCRHK_LOAD_PUBKEY,
673 ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
674 goto err;
675 }
676
677 return res;
678 err:
679 if (res)
680 EVP_PKEY_free(res);
681 return NULL;
682 }
683
684/* A little mod_exp */
685static int hwcrhk_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
686 const BIGNUM *m, BN_CTX *ctx)
687 {
688 char tempbuf[1024];
689 HWCryptoHook_ErrMsgBuf rmsg;
690 /* Since HWCryptoHook_MPI is pretty compatible with BIGNUM's,
691 we use them directly, plus a little macro magic. We only
692 thing we need to make sure of is that enough space is allocated. */
693 HWCryptoHook_MPI m_a, m_p, m_n, m_r;
694 int to_return, ret;
695
696 to_return = 0; /* expect failure */
697 rmsg.buf = tempbuf;
698 rmsg.size = 1024;
699
700 if(!hwcrhk_context)
701 {
702 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
703 goto err;
704 }
705 /* Prepare the params */
706 bn_expand2(r, m->top); /* Check for error !! */
707 BN2MPI(m_a, a);
708 BN2MPI(m_p, p);
709 BN2MPI(m_n, m);
710 MPI2BN(r, m_r);
711
712 /* Perform the operation */
713 ret = p_hwcrhk_ModExp(hwcrhk_context, m_a, m_p, m_n, &m_r, &rmsg);
714
715 /* Convert the response */
716 r->top = m_r.size / sizeof(BN_ULONG);
717 bn_fix_top(r);
718
719 if (ret < 0)
720 {
721 /* FIXME: When this error is returned, HWCryptoHook is
722 telling us that falling back to software computation
723 might be a good thing. */
724 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
725 {
726 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
727 }
728 else
729 {
730 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_REQUEST_FAILED);
731 }
732 ERR_add_error_data(1,rmsg.buf);
733 goto err;
734 }
735
736 to_return = 1;
737err:
738 return to_return;
739 }
740
741static int hwcrhk_rsa_mod_exp(BIGNUM *r, BIGNUM *I, RSA *rsa)
742 {
743 char tempbuf[1024];
744 HWCryptoHook_ErrMsgBuf rmsg;
745 HWCryptoHook_RSAKeyHandle *hptr;
746 int to_return = 0, ret;
747
748 if(!hwcrhk_context)
749 {
750 ENGINEerr(ENGINE_F_HWCRHK_MOD_EXP,ENGINE_R_NOT_INITIALISED);
751 goto err;
752 }
753
754 /* This provides support for nForce keys. Since that's opaque data
755 all we do is provide a handle to the proper key and let HWCryptoHook
756 take care of the rest. */
757 if ((hptr = (HWCryptoHook_RSAKeyHandle *) RSA_get_ex_data(rsa, hndidx))
758 != NULL)
759 {
760 HWCryptoHook_MPI m_a, m_r;
761
762 if(!rsa->n)
763 {
764 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
765 ENGINE_R_MISSING_KEY_COMPONENTS);
766 goto err;
767 }
768
769 rmsg.buf = tempbuf;
770 rmsg.size = 1024;
771
772 /* Prepare the params */
773 bn_expand2(r, rsa->n->top); /* Check for error !! */
774 BN2MPI(m_a, I);
775 MPI2BN(r, m_r);
776
777 /* Perform the operation */
778 ret = p_hwcrhk_RSA(m_a, *hptr, &m_r, &rmsg);
779
780 /* Convert the response */
781 r->top = m_r.size / sizeof(BN_ULONG);
782 bn_fix_top(r);
783
784 if (ret < 0)
785 {
786 /* FIXME: When this error is returned, HWCryptoHook is
787 telling us that falling back to software computation
788 might be a good thing. */
789 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
790 {
791 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
792 }
793 else
794 {
795 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
796 }
797 ERR_add_error_data(1,rmsg.buf);
798 goto err;
799 }
800 }
801 else
802 {
803 HWCryptoHook_MPI m_a, m_p, m_q, m_dmp1, m_dmq1, m_iqmp, m_r;
804
805 if(!rsa->p || !rsa->q || !rsa->dmp1 || !rsa->dmq1 || !rsa->iqmp)
806 {
807 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,
808 ENGINE_R_MISSING_KEY_COMPONENTS);
809 goto err;
810 }
811
812 rmsg.buf = tempbuf;
813 rmsg.size = 1024;
814
815 /* Prepare the params */
816 bn_expand2(r, rsa->n->top); /* Check for error !! */
817 BN2MPI(m_a, I);
818 BN2MPI(m_p, rsa->p);
819 BN2MPI(m_q, rsa->q);
820 BN2MPI(m_dmp1, rsa->dmp1);
821 BN2MPI(m_dmq1, rsa->dmq1);
822 BN2MPI(m_iqmp, rsa->iqmp);
823 MPI2BN(r, m_r);
824
825 /* Perform the operation */
826 ret = p_hwcrhk_ModExpCRT(hwcrhk_context, m_a, m_p, m_q,
827 m_dmp1, m_dmq1, m_iqmp, &m_r, NULL);
828
829 /* Convert the response */
830 r->top = m_r.size / sizeof(BN_ULONG);
831 bn_fix_top(r);
832
833 if (ret < 0)
834 {
835 /* FIXME: When this error is returned, HWCryptoHook is
836 telling us that falling back to software computation
837 might be a good thing. */
838 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
839 {
840 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FALLBACK);
841 }
842 else
843 {
844 ENGINEerr(ENGINE_F_HWCRHK_RSA_MOD_EXP,ENGINE_R_REQUEST_FAILED);
845 }
846 ERR_add_error_data(1,rmsg.buf);
847 goto err;
848 }
849 }
850 /* If we're here, we must be here with some semblance of success :-) */
851 to_return = 1;
852err:
853 return to_return;
854 }
855
856/* This function is aliased to mod_exp (with the mont stuff dropped). */
857static int hwcrhk_mod_exp_mont(BIGNUM *r, BIGNUM *a, const BIGNUM *p,
858 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
859 {
860 return hwcrhk_mod_exp(r, a, p, m, ctx);
861 }
862
863/* This function is aliased to mod_exp (with the dh and mont dropped). */
864static int hwcrhk_mod_exp_dh(DH *dh, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
865 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
866 {
867 return hwcrhk_mod_exp(r, a, p, m, ctx);
868 }
869
870/* Random bytes are good */
871static int hwcrhk_rand_bytes(unsigned char *buf, int num)
872 {
873 char tempbuf[1024];
874 HWCryptoHook_ErrMsgBuf rmsg;
875 int to_return = 0; /* assume failure */
876 int ret;
877
878 rmsg.buf = tempbuf;
879 rmsg.size = 1024;
880
881 if(!hwcrhk_context)
882 {
883 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_NOT_INITIALISED);
884 goto err;
885 }
886
887 ret = p_hwcrhk_RandomBytes(hwcrhk_context, buf, num, &rmsg);
888 if (ret < 0)
889 {
890 /* FIXME: When this error is returned, HWCryptoHook is
891 telling us that falling back to software computation
892 might be a good thing. */
893 if(ret == HWCRYPTOHOOK_ERROR_FALLBACK)
894 {
895 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FALLBACK);
896 }
897 else
898 {
899 ENGINEerr(ENGINE_F_HWCRHK_RAND_BYTES,ENGINE_R_REQUEST_FAILED);
900 }
901 ERR_add_error_data(1,rmsg.buf);
902 goto err;
903 }
904 to_return = 1;
905 err:
906 return to_return;
907 }
908
909static int hwcrhk_rand_status(void)
910 {
911 return 1;
912 }
913
914/* This cleans up an RSA KM key, called when ex_data is freed */
915
916static void hwcrhk_ex_free(void *obj, void *item, CRYPTO_EX_DATA *ad,
917 int index,long argl, void *argp)
918{
919 char tempbuf[1024];
920 HWCryptoHook_ErrMsgBuf rmsg;
921 HWCryptoHook_RSAKeyHandle *hptr;
922 int ret;
923
924 rmsg.buf = tempbuf;
925 rmsg.size = 1024;
926
927 hptr = (HWCryptoHook_RSAKeyHandle *) item;
928 if(!hptr) return;
929 ret = p_hwcrhk_RSAUnloadKey(*hptr, NULL);
930 OPENSSL_free(hptr);
931}
932
933/* Mutex calls: since the HWCryptoHook model closely follows the POSIX model
934 * these just wrap the POSIX functions and add some logging.
935 */
936
937static int hwcrhk_mutex_init(HWCryptoHook_Mutex* mt,
938 HWCryptoHook_CallerContext *cactx)
939 {
940 mt->lockid = CRYPTO_get_new_dynlockid();
941 if (mt->lockid == 0)
942 return 0;
943 return 1;
944 }
945
946static int hwcrhk_mutex_lock(HWCryptoHook_Mutex *mt)
947 {
948 CRYPTO_w_lock(mt->lockid);
949 return 1;
950 }
951
952void hwcrhk_mutex_unlock(HWCryptoHook_Mutex * mt)
953 {
954 CRYPTO_w_unlock(mt->lockid);
955 }
956
957static void hwcrhk_mutex_destroy(HWCryptoHook_Mutex *mt)
958 {
959 CRYPTO_destroy_dynlockid(mt->lockid);
960 }
961
962static int hwcrhk_get_pass(const char *prompt_info,
963 int *len_io, char *buf,
964 HWCryptoHook_PassphraseContext *ppctx,
965 HWCryptoHook_CallerContext *cactx)
966 {
967 int l = 0;
968 char prompt[1024];
969
970 if (password_callback == NULL)
971 {
972 ENGINEerr(ENGINE_F_HWCRHK_GET_PASS,ENGINE_R_NO_CALLBACK);
973 return -1;
974 }
975 if (prompt_info)
976 {
977 strncpy(prompt, "Card: \"", sizeof(prompt));
978 l += 5;
979 strncpy(prompt + l, prompt_info, sizeof(prompt) - l);
980 l += strlen(prompt_info);
981 if (l + 2 < sizeof(prompt))
982 {
983 strncpy(prompt + l, "\"\n", sizeof(prompt) - l);
984 l += 2;
985 }
986 }
987 if (l < sizeof(prompt) - 1)
988 {
989 strncpy(prompt, "Enter Passphrase <enter to cancel>:",
990 sizeof(prompt) - l);
991 l += 35;
992 }
993 prompt[l] = '\0';
994
995 /* I know, passing on the prompt instead of the user data *is*
996 a bad thing. However, that's all we have right now.
997 -- Richard Levitte */
998 *len_io = password_callback(buf, *len_io, 0, prompt);
999 if(!*len_io)
1000 return -1;
1001 return 0;
1002 }
1003
1004static void hwcrhk_log_message(void *logstream, const char *message)
1005 {
1006 BIO *lstream = NULL;
1007
1008 CRYPTO_w_lock(CRYPTO_LOCK_BIO);
1009 if (logstream)
1010 lstream=*(BIO **)logstream;
1011 if (lstream)
1012 {
1013 BIO_write(lstream, message, strlen(message));
1014 }
1015 CRYPTO_w_unlock(CRYPTO_LOCK_BIO);
1016 }
1017
1018#endif /* !NO_HW_NCIPHER */
1019#endif /* !NO_HW */