crypto.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
  4. * 2007, 2008, 2009 Free Software Foundation, Inc.
  5. *
  6. * GRUB is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * GRUB is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #include <grub/crypto.h>
  20. #include <grub/misc.h>
  21. #include <grub/mm.h>
  22. #include <grub/term.h>
  23. #include <grub/dl.h>
  24. #include <grub/i18n.h>
  25. #include <grub/env.h>
  26. GRUB_MOD_LICENSE ("GPLv3+");
  27. struct grub_crypto_hmac_handle
  28. {
  29. const struct gcry_md_spec *md;
  30. void *ctx;
  31. void *opad;
  32. };
  33. static gcry_cipher_spec_t *grub_ciphers = NULL;
  34. static gcry_md_spec_t *grub_digests = NULL;
  35. void (*grub_crypto_autoload_hook) (const char *name) = NULL;
  36. /* Based on libgcrypt-1.4.4/src/misc.c. */
  37. void
  38. grub_burn_stack (grub_size_t size)
  39. {
  40. char buf[64];
  41. grub_memset (buf, 0, sizeof (buf));
  42. if (size > sizeof (buf))
  43. grub_burn_stack (size - sizeof (buf));
  44. }
  45. void
  46. _gcry_burn_stack (int size)
  47. {
  48. grub_burn_stack (size);
  49. }
  50. void __attribute__ ((noreturn))
  51. _gcry_assert_failed (const char *expr, const char *file, int line,
  52. const char *func)
  53. {
  54. grub_fatal ("assertion %s at %s:%d (%s) failed\n", expr, file, line, func);
  55. }
  56. void _gcry_log_error (const char *fmt, ...)
  57. {
  58. va_list args;
  59. const char *debug = grub_env_get ("debug");
  60. if (! debug)
  61. return;
  62. if (grub_strword (debug, "all") || grub_strword (debug, "gcrypt"))
  63. {
  64. grub_printf ("gcrypt error: ");
  65. va_start (args, fmt);
  66. grub_vprintf (fmt, args);
  67. va_end (args);
  68. grub_refresh ();
  69. }
  70. }
  71. void
  72. grub_cipher_register (gcry_cipher_spec_t *cipher)
  73. {
  74. cipher->next = grub_ciphers;
  75. grub_ciphers = cipher;
  76. }
  77. void
  78. grub_cipher_unregister (gcry_cipher_spec_t *cipher)
  79. {
  80. gcry_cipher_spec_t **ciph;
  81. for (ciph = &grub_ciphers; *ciph; ciph = &((*ciph)->next))
  82. if (*ciph == cipher)
  83. {
  84. *ciph = (*ciph)->next;
  85. break;
  86. }
  87. }
  88. void
  89. grub_md_register (gcry_md_spec_t *digest)
  90. {
  91. digest->next = grub_digests;
  92. grub_digests = digest;
  93. }
  94. void
  95. grub_md_unregister (gcry_md_spec_t *cipher)
  96. {
  97. gcry_md_spec_t **ciph;
  98. for (ciph = &grub_digests; *ciph; ciph = &((*ciph)->next))
  99. if (*ciph == cipher)
  100. {
  101. *ciph = (*ciph)->next;
  102. break;
  103. }
  104. }
  105. void
  106. grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
  107. grub_size_t inlen)
  108. {
  109. GRUB_PROPERLY_ALIGNED_ARRAY (ctx, GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE);
  110. if (hash->contextsize > sizeof (ctx))
  111. grub_fatal ("Too large md context");
  112. hash->init (&ctx);
  113. hash->write (&ctx, in, inlen);
  114. hash->final (&ctx);
  115. grub_memcpy (out, hash->read (&ctx), hash->mdlen);
  116. }
  117. const gcry_md_spec_t *
  118. grub_crypto_lookup_md_by_name (const char *name)
  119. {
  120. const gcry_md_spec_t *md;
  121. int first = 1;
  122. while (1)
  123. {
  124. for (md = grub_digests; md; md = md->next)
  125. if (grub_strcasecmp (name, md->name) == 0)
  126. return md;
  127. if (grub_crypto_autoload_hook && first)
  128. grub_crypto_autoload_hook (name);
  129. else
  130. return NULL;
  131. first = 0;
  132. }
  133. }
  134. const gcry_cipher_spec_t *
  135. grub_crypto_lookup_cipher_by_name (const char *name)
  136. {
  137. const gcry_cipher_spec_t *ciph;
  138. int first = 1;
  139. while (1)
  140. {
  141. for (ciph = grub_ciphers; ciph; ciph = ciph->next)
  142. {
  143. const char **alias;
  144. if (grub_strcasecmp (name, ciph->name) == 0)
  145. return ciph;
  146. if (!ciph->aliases)
  147. continue;
  148. for (alias = ciph->aliases; *alias; alias++)
  149. if (grub_strcasecmp (name, *alias) == 0)
  150. return ciph;
  151. }
  152. if (grub_crypto_autoload_hook && first)
  153. grub_crypto_autoload_hook (name);
  154. else
  155. return NULL;
  156. first = 0;
  157. }
  158. }
  159. grub_crypto_cipher_handle_t
  160. grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher)
  161. {
  162. grub_crypto_cipher_handle_t ret;
  163. ret = grub_malloc (sizeof (*ret) + cipher->contextsize);
  164. if (!ret)
  165. return NULL;
  166. ret->cipher = cipher;
  167. return ret;
  168. }
  169. gcry_err_code_t
  170. grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
  171. const unsigned char *key,
  172. unsigned keylen)
  173. {
  174. return cipher->cipher->setkey (cipher->ctx, key, keylen);
  175. }
  176. gcry_err_code_t
  177. grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
  178. void *out, const void *in, grub_size_t size)
  179. {
  180. const grub_uint8_t *inptr, *end;
  181. grub_uint8_t *outptr;
  182. grub_size_t blocksize;
  183. if (!cipher->cipher->decrypt)
  184. return GPG_ERR_NOT_SUPPORTED;
  185. blocksize = cipher->cipher->blocksize;
  186. if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
  187. || ((size & (blocksize - 1)) != 0))
  188. return GPG_ERR_INV_ARG;
  189. end = (const grub_uint8_t *) in + size;
  190. for (inptr = in, outptr = out; inptr < end;
  191. inptr += blocksize, outptr += blocksize)
  192. cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
  193. return GPG_ERR_NO_ERROR;
  194. }
  195. gcry_err_code_t
  196. grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
  197. void *out, const void *in, grub_size_t size)
  198. {
  199. const grub_uint8_t *inptr, *end;
  200. grub_uint8_t *outptr;
  201. grub_size_t blocksize;
  202. if (!cipher->cipher->encrypt)
  203. return GPG_ERR_NOT_SUPPORTED;
  204. blocksize = cipher->cipher->blocksize;
  205. if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
  206. || ((size & (blocksize - 1)) != 0))
  207. return GPG_ERR_INV_ARG;
  208. end = (const grub_uint8_t *) in + size;
  209. for (inptr = in, outptr = out; inptr < end;
  210. inptr += blocksize, outptr += blocksize)
  211. cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
  212. return GPG_ERR_NO_ERROR;
  213. }
  214. gcry_err_code_t
  215. grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
  216. void *out, const void *in, grub_size_t size,
  217. void *iv_in)
  218. {
  219. grub_uint8_t *outptr;
  220. const grub_uint8_t *inptr, *end;
  221. void *iv;
  222. grub_size_t blocksize;
  223. if (!cipher->cipher->encrypt)
  224. return GPG_ERR_NOT_SUPPORTED;
  225. blocksize = cipher->cipher->blocksize;
  226. if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
  227. || ((size & (blocksize - 1)) != 0))
  228. return GPG_ERR_INV_ARG;
  229. end = (const grub_uint8_t *) in + size;
  230. iv = iv_in;
  231. for (inptr = in, outptr = out; inptr < end;
  232. inptr += blocksize, outptr += blocksize)
  233. {
  234. grub_crypto_xor (outptr, inptr, iv, blocksize);
  235. cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
  236. iv = outptr;
  237. }
  238. grub_memcpy (iv_in, iv, blocksize);
  239. return GPG_ERR_NO_ERROR;
  240. }
  241. gcry_err_code_t
  242. grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
  243. void *out, const void *in, grub_size_t size,
  244. void *iv)
  245. {
  246. const grub_uint8_t *inptr, *end;
  247. grub_uint8_t *outptr;
  248. grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
  249. grub_size_t blocksize;
  250. if (!cipher->cipher->decrypt)
  251. return GPG_ERR_NOT_SUPPORTED;
  252. blocksize = cipher->cipher->blocksize;
  253. if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
  254. || ((size & (blocksize - 1)) != 0))
  255. return GPG_ERR_INV_ARG;
  256. if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
  257. return GPG_ERR_INV_ARG;
  258. end = (const grub_uint8_t *) in + size;
  259. for (inptr = in, outptr = out; inptr < end;
  260. inptr += blocksize, outptr += blocksize)
  261. {
  262. grub_memcpy (ivt, inptr, blocksize);
  263. cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
  264. grub_crypto_xor (outptr, outptr, iv, blocksize);
  265. grub_memcpy (iv, ivt, blocksize);
  266. }
  267. return GPG_ERR_NO_ERROR;
  268. }
  269. /* Based on gcry/cipher/md.c. */
  270. struct grub_crypto_hmac_handle *
  271. grub_crypto_hmac_init (const struct gcry_md_spec *md,
  272. const void *key, grub_size_t keylen)
  273. {
  274. grub_uint8_t *helpkey = NULL;
  275. grub_uint8_t *ipad = NULL, *opad = NULL;
  276. void *ctx = NULL;
  277. struct grub_crypto_hmac_handle *ret = NULL;
  278. unsigned i;
  279. if (md->mdlen > md->blocksize)
  280. return NULL;
  281. ctx = grub_malloc (md->contextsize);
  282. if (!ctx)
  283. goto err;
  284. if ( keylen > md->blocksize )
  285. {
  286. helpkey = grub_malloc (md->mdlen);
  287. if (!helpkey)
  288. goto err;
  289. grub_crypto_hash (md, helpkey, key, keylen);
  290. key = helpkey;
  291. keylen = md->mdlen;
  292. }
  293. ipad = grub_zalloc (md->blocksize);
  294. if (!ipad)
  295. goto err;
  296. opad = grub_zalloc (md->blocksize);
  297. if (!opad)
  298. goto err;
  299. grub_memcpy ( ipad, key, keylen );
  300. grub_memcpy ( opad, key, keylen );
  301. for (i=0; i < md->blocksize; i++ )
  302. {
  303. ipad[i] ^= 0x36;
  304. opad[i] ^= 0x5c;
  305. }
  306. grub_free (helpkey);
  307. helpkey = NULL;
  308. md->init (ctx);
  309. md->write (ctx, ipad, md->blocksize); /* inner pad */
  310. grub_memset (ipad, 0, md->blocksize);
  311. grub_free (ipad);
  312. ipad = NULL;
  313. ret = grub_malloc (sizeof (*ret));
  314. if (!ret)
  315. goto err;
  316. ret->md = md;
  317. ret->ctx = ctx;
  318. ret->opad = opad;
  319. return ret;
  320. err:
  321. grub_free (helpkey);
  322. grub_free (ctx);
  323. grub_free (ipad);
  324. grub_free (opad);
  325. return NULL;
  326. }
  327. void
  328. grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd,
  329. const void *data,
  330. grub_size_t datalen)
  331. {
  332. hnd->md->write (hnd->ctx, data, datalen);
  333. }
  334. gcry_err_code_t
  335. grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
  336. {
  337. grub_uint8_t *p;
  338. grub_uint8_t *ctx2;
  339. ctx2 = grub_malloc (hnd->md->contextsize);
  340. if (!ctx2)
  341. return GPG_ERR_OUT_OF_MEMORY;
  342. hnd->md->final (hnd->ctx);
  343. hnd->md->read (hnd->ctx);
  344. p = hnd->md->read (hnd->ctx);
  345. hnd->md->init (ctx2);
  346. hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize);
  347. hnd->md->write (ctx2, p, hnd->md->mdlen);
  348. hnd->md->final (ctx2);
  349. grub_memset (hnd->opad, 0, hnd->md->blocksize);
  350. grub_free (hnd->opad);
  351. grub_memset (hnd->ctx, 0, hnd->md->contextsize);
  352. grub_free (hnd->ctx);
  353. grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen);
  354. grub_memset (ctx2, 0, hnd->md->contextsize);
  355. grub_free (ctx2);
  356. grub_memset (hnd, 0, sizeof (*hnd));
  357. grub_free (hnd);
  358. return GPG_ERR_NO_ERROR;
  359. }
  360. gcry_err_code_t
  361. grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
  362. const void *key, grub_size_t keylen,
  363. const void *data, grub_size_t datalen, void *out)
  364. {
  365. struct grub_crypto_hmac_handle *hnd;
  366. hnd = grub_crypto_hmac_init (md, key, keylen);
  367. if (!hnd)
  368. return GPG_ERR_OUT_OF_MEMORY;
  369. grub_crypto_hmac_write (hnd, data, datalen);
  370. return grub_crypto_hmac_fini (hnd, out);
  371. }
  372. grub_err_t
  373. grub_crypto_gcry_error (gcry_err_code_t in)
  374. {
  375. if (in == GPG_ERR_NO_ERROR)
  376. return GRUB_ERR_NONE;
  377. return GRUB_ACCESS_DENIED;
  378. }
  379. int
  380. grub_crypto_memcmp (const void *a, const void *b, grub_size_t n)
  381. {
  382. register grub_size_t counter = 0;
  383. const grub_uint8_t *pa, *pb;
  384. for (pa = a, pb = b; n; pa++, pb++, n--)
  385. {
  386. if (*pa != *pb)
  387. counter++;
  388. }
  389. return !!counter;
  390. }
  391. #ifndef GRUB_UTIL
  392. int
  393. grub_password_get (char buf[], unsigned buf_size)
  394. {
  395. unsigned cur_len = 0;
  396. int key;
  397. while (1)
  398. {
  399. key = grub_getkey ();
  400. if (key == '\n' || key == '\r')
  401. break;
  402. if (key == GRUB_TERM_ESC)
  403. {
  404. cur_len = 0;
  405. break;
  406. }
  407. if (key == '\b')
  408. {
  409. if (cur_len)
  410. cur_len--;
  411. continue;
  412. }
  413. if (!grub_isprint (key))
  414. continue;
  415. if (cur_len + 2 < buf_size)
  416. buf[cur_len++] = key;
  417. }
  418. grub_memset (buf + cur_len, 0, buf_size - cur_len);
  419. grub_xputs ("\n");
  420. grub_refresh ();
  421. return (key != GRUB_TERM_ESC);
  422. }
  423. #endif