e_chil.c 43 KB

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