e_chil.c 37 KB

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