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