geli.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2003,2007,2010,2011 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /* This file is loosely based on FreeBSD geli implementation
  19. (but no code was directly copied). FreeBSD geli is distributed under
  20. following terms: */
  21. /*-
  22. * Copyright (c) 2005-2006 Pawel Jakub Dawidek <pjd@FreeBSD.org>
  23. * All rights reserved.
  24. *
  25. * Redistribution and use in source and binary forms, with or without
  26. * modification, are permitted provided that the following conditions
  27. * are met:
  28. * 1. Redistributions of source code must retain the above copyright
  29. * notice, this list of conditions and the following disclaimer.
  30. * 2. Redistributions in binary form must reproduce the above copyright
  31. * notice, this list of conditions and the following disclaimer in the
  32. * documentation and/or other materials provided with the distribution.
  33. *
  34. * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
  35. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  36. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  37. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
  38. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  39. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  40. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  41. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  42. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  43. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  44. * SUCH DAMAGE.
  45. */
  46. #include <grub/cryptodisk.h>
  47. #include <grub/types.h>
  48. #include <grub/misc.h>
  49. #include <grub/mm.h>
  50. #include <grub/dl.h>
  51. #include <grub/err.h>
  52. #include <grub/disk.h>
  53. #include <grub/crypto.h>
  54. #include <grub/partition.h>
  55. #include <grub/i18n.h>
  56. GRUB_MOD_LICENSE ("GPLv3+");
  57. /* Dirty trick to solve circular dependency. */
  58. #ifdef GRUB_UTIL
  59. #include <grub/util/misc.h>
  60. #undef GRUB_MD_SHA256
  61. #undef GRUB_MD_SHA512
  62. static const gcry_md_spec_t *
  63. grub_md_sha256_real (void)
  64. {
  65. const gcry_md_spec_t *ret;
  66. ret = grub_crypto_lookup_md_by_name ("sha256");
  67. if (!ret)
  68. grub_util_error ("%s", _("Couldn't load sha256"));
  69. return ret;
  70. }
  71. static const gcry_md_spec_t *
  72. grub_md_sha512_real (void)
  73. {
  74. const gcry_md_spec_t *ret;
  75. ret = grub_crypto_lookup_md_by_name ("sha512");
  76. if (!ret)
  77. grub_util_error ("%s", _("Couldn't load sha512"));
  78. return ret;
  79. }
  80. #define GRUB_MD_SHA256 grub_md_sha256_real()
  81. #define GRUB_MD_SHA512 grub_md_sha512_real()
  82. #endif
  83. struct grub_geli_key
  84. {
  85. grub_uint8_t iv_key[64];
  86. grub_uint8_t cipher_key[64];
  87. grub_uint8_t hmac[64];
  88. } GRUB_PACKED;
  89. struct grub_geli_phdr
  90. {
  91. grub_uint8_t magic[16];
  92. #define GELI_MAGIC "GEOM::ELI"
  93. grub_uint32_t version;
  94. grub_uint32_t flags;
  95. grub_uint16_t alg;
  96. grub_uint16_t keylen;
  97. grub_uint16_t unused3[5];
  98. grub_uint32_t sector_size;
  99. grub_uint8_t keys_used;
  100. grub_uint32_t niter;
  101. grub_uint8_t salt[64];
  102. struct grub_geli_key keys[2];
  103. } GRUB_PACKED;
  104. enum
  105. {
  106. GRUB_GELI_FLAGS_ONETIME = 1,
  107. GRUB_GELI_FLAGS_BOOT = 2,
  108. };
  109. /* FIXME: support version 0. */
  110. /* FIXME: support big-endian pre-version-4 volumes. */
  111. /* FIXME: support for keyfiles. */
  112. /* FIXME: support for HMAC. */
  113. const char *algorithms[] = {
  114. [0x01] = "des",
  115. [0x02] = "3des",
  116. [0x03] = "blowfish",
  117. [0x04] = "cast5",
  118. /* FIXME: 0x05 is skipjack, but we don't have it. */
  119. [0x0b] = "aes",
  120. /* FIXME: 0x10 is null. */
  121. [0x15] = "camellia128",
  122. [0x16] = "aes"
  123. };
  124. static gcry_err_code_t
  125. geli_rekey (struct grub_cryptodisk *dev, grub_uint64_t zoneno)
  126. {
  127. gcry_err_code_t gcry_err;
  128. const struct {
  129. char magic[4];
  130. grub_uint64_t zone;
  131. } GRUB_PACKED tohash
  132. = { {'e', 'k', 'e', 'y'}, grub_cpu_to_le64 (zoneno) };
  133. GRUB_PROPERLY_ALIGNED_ARRAY (key, GRUB_CRYPTO_MAX_MDLEN);
  134. if (dev->hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
  135. return GPG_ERR_INV_ARG;
  136. grub_dprintf ("geli", "rekeying %" PRIuGRUB_UINT64_T " keysize=%d\n",
  137. zoneno, dev->rekey_derived_size);
  138. gcry_err = grub_crypto_hmac_buffer (dev->hash, dev->rekey_key, 64,
  139. &tohash, sizeof (tohash), key);
  140. if (gcry_err)
  141. return gcry_err;
  142. return grub_cryptodisk_setkey (dev, (grub_uint8_t *) key,
  143. dev->rekey_derived_size);
  144. }
  145. static inline gcry_err_code_t
  146. make_uuid (const struct grub_geli_phdr *header,
  147. char *uuid)
  148. {
  149. grub_uint8_t uuidbin[GRUB_CRYPTODISK_MAX_UUID_LENGTH];
  150. gcry_err_code_t err;
  151. grub_uint8_t *iptr;
  152. char *optr;
  153. if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH)
  154. return GPG_ERR_TOO_LARGE;
  155. err = grub_crypto_hmac_buffer (GRUB_MD_SHA256,
  156. header->salt, sizeof (header->salt),
  157. "uuid", sizeof ("uuid") - 1, uuidbin);
  158. if (err)
  159. return err;
  160. optr = uuid;
  161. for (iptr = uuidbin; iptr < &uuidbin[GRUB_MD_SHA256->mdlen]; iptr++)
  162. {
  163. grub_snprintf (optr, 3, "%02x", *iptr);
  164. optr += 2;
  165. }
  166. *optr = 0;
  167. return GPG_ERR_NO_ERROR;
  168. }
  169. #ifdef GRUB_UTIL
  170. #include <grub/emu/hostdisk.h>
  171. #include <grub/emu/misc.h>
  172. char *
  173. grub_util_get_geli_uuid (const char *dev)
  174. {
  175. grub_util_fd_t fd;
  176. grub_uint64_t s;
  177. unsigned log_secsize;
  178. grub_uint8_t hdr[512];
  179. struct grub_geli_phdr *header;
  180. char *uuid;
  181. gcry_err_code_t err;
  182. fd = grub_util_fd_open (dev, GRUB_UTIL_FD_O_RDONLY);
  183. if (!GRUB_UTIL_FD_IS_VALID (fd))
  184. return NULL;
  185. s = grub_util_get_fd_size (fd, dev, &log_secsize);
  186. s >>= log_secsize;
  187. if (grub_util_fd_seek (fd, (s << log_secsize) - 512) < 0)
  188. grub_util_error ("%s", _("couldn't read ELI metadata"));
  189. uuid = xmalloc (GRUB_MD_SHA256->mdlen * 2 + 1);
  190. if (grub_util_fd_read (fd, (void *) &hdr, 512) < 0)
  191. grub_util_error ("%s", _("couldn't read ELI metadata"));
  192. grub_util_fd_close (fd);
  193. COMPILE_TIME_ASSERT (sizeof (header) <= 512);
  194. header = (void *) &hdr;
  195. /* Look for GELI magic sequence. */
  196. if (grub_memcmp (header->magic, GELI_MAGIC, sizeof (GELI_MAGIC))
  197. || grub_le_to_cpu32 (header->version) > 7
  198. || grub_le_to_cpu32 (header->version) < 1)
  199. grub_util_error ("%s", _("wrong ELI magic or version"));
  200. err = make_uuid ((void *) &hdr, uuid);
  201. if (err)
  202. {
  203. grub_free (uuid);
  204. return NULL;
  205. }
  206. return uuid;
  207. }
  208. #endif
  209. static grub_cryptodisk_t
  210. geli_scan (grub_disk_t disk, grub_cryptomount_args_t cargs)
  211. {
  212. grub_cryptodisk_t newdev;
  213. struct grub_geli_phdr header;
  214. grub_crypto_cipher_handle_t cipher = NULL, secondary_cipher = NULL;
  215. const struct gcry_cipher_spec *ciph;
  216. const char *ciphername = NULL;
  217. gcry_err_code_t gcry_err;
  218. char uuid[GRUB_CRYPTODISK_MAX_UUID_LENGTH];
  219. grub_disk_addr_t sector;
  220. grub_err_t err;
  221. /* Detached headers are not implemented yet */
  222. if (cargs->hdr_file != NULL)
  223. return NULL;
  224. if (2 * GRUB_MD_SHA256->mdlen + 1 > GRUB_CRYPTODISK_MAX_UUID_LENGTH)
  225. return NULL;
  226. sector = grub_disk_native_sectors (disk);
  227. if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
  228. return NULL;
  229. /* Read the GELI header. */
  230. err = grub_disk_read (disk, sector - 1, 0, sizeof (header), &header);
  231. if (err)
  232. return NULL;
  233. /* Look for GELI magic sequence. */
  234. if (grub_memcmp (header.magic, GELI_MAGIC, sizeof (GELI_MAGIC))
  235. || grub_le_to_cpu32 (header.version) > 7
  236. || grub_le_to_cpu32 (header.version) < 1)
  237. {
  238. grub_dprintf ("geli", "wrong magic %02x\n", header.magic[0]);
  239. return NULL;
  240. }
  241. if ((grub_le_to_cpu32 (header.sector_size)
  242. & (grub_le_to_cpu32 (header.sector_size) - 1))
  243. || grub_le_to_cpu32 (header.sector_size) == 0)
  244. {
  245. grub_dprintf ("geli", "incorrect sector size %d\n",
  246. grub_le_to_cpu32 (header.sector_size));
  247. return NULL;
  248. }
  249. if (grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_ONETIME)
  250. {
  251. grub_dprintf ("geli", "skipping one-time volume\n");
  252. return NULL;
  253. }
  254. if (cargs->check_boot && !(grub_le_to_cpu32 (header.flags) & GRUB_GELI_FLAGS_BOOT))
  255. {
  256. grub_dprintf ("geli", "not a boot volume\n");
  257. return NULL;
  258. }
  259. gcry_err = make_uuid (&header, uuid);
  260. if (gcry_err)
  261. {
  262. grub_crypto_gcry_error (gcry_err);
  263. return NULL;
  264. }
  265. if (cargs->search_uuid != NULL && grub_uuidcasecmp (cargs->search_uuid, uuid, sizeof (uuid)) != 0)
  266. {
  267. grub_dprintf ("geli", "%s != %s\n", uuid, cargs->search_uuid);
  268. return NULL;
  269. }
  270. if (grub_le_to_cpu16 (header.alg) >= ARRAY_SIZE (algorithms)
  271. || algorithms[grub_le_to_cpu16 (header.alg)] == NULL)
  272. {
  273. grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher 0x%x unknown",
  274. grub_le_to_cpu16 (header.alg));
  275. return NULL;
  276. }
  277. ciphername = algorithms[grub_le_to_cpu16 (header.alg)];
  278. ciph = grub_crypto_lookup_cipher_by_name (ciphername);
  279. if (!ciph)
  280. {
  281. grub_error (GRUB_ERR_FILE_NOT_FOUND, "Cipher %s isn't available",
  282. ciphername);
  283. return NULL;
  284. }
  285. /* Configure the cipher used for the bulk data. */
  286. cipher = grub_crypto_cipher_open (ciph);
  287. if (!cipher)
  288. return NULL;
  289. if (grub_le_to_cpu16 (header.alg) == 0x16)
  290. {
  291. secondary_cipher = grub_crypto_cipher_open (ciph);
  292. if (!secondary_cipher)
  293. {
  294. grub_crypto_cipher_close (cipher);
  295. return NULL;
  296. }
  297. }
  298. if (grub_le_to_cpu16 (header.keylen) > 1024)
  299. {
  300. grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid keysize %d",
  301. grub_le_to_cpu16 (header.keylen));
  302. grub_crypto_cipher_close (cipher);
  303. grub_crypto_cipher_close (secondary_cipher);
  304. return NULL;
  305. }
  306. newdev = grub_zalloc (sizeof (struct grub_cryptodisk));
  307. if (!newdev)
  308. {
  309. grub_crypto_cipher_close (cipher);
  310. grub_crypto_cipher_close (secondary_cipher);
  311. return NULL;
  312. }
  313. newdev->cipher = cipher;
  314. newdev->secondary_cipher = secondary_cipher;
  315. newdev->offset_sectors = 0;
  316. newdev->source_disk = NULL;
  317. newdev->benbi_log = 0;
  318. if (grub_le_to_cpu16 (header.alg) == 0x16)
  319. {
  320. newdev->mode = GRUB_CRYPTODISK_MODE_XTS;
  321. newdev->mode_iv = GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64;
  322. }
  323. else
  324. {
  325. newdev->mode = GRUB_CRYPTODISK_MODE_CBC;
  326. newdev->mode_iv = GRUB_CRYPTODISK_MODE_IV_BYTECOUNT64_HASH;
  327. }
  328. newdev->essiv_cipher = NULL;
  329. newdev->essiv_hash = NULL;
  330. newdev->hash = GRUB_MD_SHA512;
  331. newdev->iv_hash = GRUB_MD_SHA256;
  332. newdev->log_sector_size = grub_log2ull (grub_le_to_cpu32 (header.sector_size));
  333. if (grub_le_to_cpu32 (header.version) >= 5)
  334. {
  335. newdev->rekey = geli_rekey;
  336. newdev->rekey_shift = 20;
  337. }
  338. newdev->modname = "geli";
  339. newdev->total_sectors = grub_disk_native_sectors (disk) - 1;
  340. grub_memcpy (newdev->uuid, uuid, sizeof (newdev->uuid));
  341. COMPILE_TIME_ASSERT (sizeof (newdev->uuid) >= 32 * 2 + 1);
  342. return newdev;
  343. }
  344. static grub_err_t
  345. geli_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs)
  346. {
  347. grub_size_t keysize;
  348. grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN];
  349. grub_uint8_t geomkey[GRUB_CRYPTO_MAX_MDLEN];
  350. grub_uint8_t verify_key[GRUB_CRYPTO_MAX_MDLEN];
  351. grub_uint8_t zero[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
  352. grub_uint8_t geli_cipher_key[64];
  353. unsigned i;
  354. gcry_err_code_t gcry_err;
  355. struct grub_geli_phdr header;
  356. grub_disk_addr_t sector;
  357. grub_err_t err;
  358. if (cargs->key_data == NULL || cargs->key_len == 0)
  359. return grub_error (GRUB_ERR_BAD_ARGUMENT, "no key data");
  360. if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
  361. return grub_error (GRUB_ERR_BUG, "cipher block is too long");
  362. if (dev->hash->mdlen > GRUB_CRYPTO_MAX_MDLEN)
  363. return grub_error (GRUB_ERR_BUG, "mdlen is too long");
  364. sector = grub_disk_native_sectors (source);
  365. if (sector == GRUB_DISK_SIZE_UNKNOWN || sector == 0)
  366. return grub_error (GRUB_ERR_BUG, "not a geli");
  367. /* Read the GELI header. */
  368. err = grub_disk_read (source, sector - 1, 0, sizeof (header), &header);
  369. if (err)
  370. return err;
  371. keysize = grub_le_to_cpu16 (header.keylen) / GRUB_CHAR_BIT;
  372. grub_memset (zero, 0, sizeof (zero));
  373. grub_puts_ (N_("Attempting to decrypt master key..."));
  374. /* Calculate the PBKDF2 of the user supplied passphrase. */
  375. if (grub_le_to_cpu32 (header.niter) != 0)
  376. {
  377. grub_uint8_t pbkdf_key[64];
  378. gcry_err = grub_crypto_pbkdf2 (dev->hash, cargs->key_data,
  379. cargs->key_len,
  380. header.salt,
  381. sizeof (header.salt),
  382. grub_le_to_cpu32 (header.niter),
  383. pbkdf_key, sizeof (pbkdf_key));
  384. if (gcry_err)
  385. return grub_crypto_gcry_error (gcry_err);
  386. gcry_err = grub_crypto_hmac_buffer (dev->hash, NULL, 0, pbkdf_key,
  387. sizeof (pbkdf_key), geomkey);
  388. if (gcry_err)
  389. return grub_crypto_gcry_error (gcry_err);
  390. }
  391. else
  392. {
  393. struct grub_crypto_hmac_handle *hnd;
  394. hnd = grub_crypto_hmac_init (dev->hash, NULL, 0);
  395. if (!hnd)
  396. return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY);
  397. grub_crypto_hmac_write (hnd, header.salt, sizeof (header.salt));
  398. grub_crypto_hmac_write (hnd, cargs->key_data, cargs->key_len);
  399. gcry_err = grub_crypto_hmac_fini (hnd, geomkey);
  400. if (gcry_err)
  401. return grub_crypto_gcry_error (gcry_err);
  402. }
  403. gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey,
  404. dev->hash->mdlen, "\1", 1, digest);
  405. if (gcry_err)
  406. return grub_crypto_gcry_error (gcry_err);
  407. gcry_err = grub_crypto_hmac_buffer (dev->hash, geomkey,
  408. dev->hash->mdlen, "\0", 1, verify_key);
  409. if (gcry_err)
  410. return grub_crypto_gcry_error (gcry_err);
  411. grub_dprintf ("geli", "keylen = %" PRIuGRUB_SIZE "\n", keysize);
  412. /* Try to recover master key from each active keyslot. */
  413. for (i = 0; i < ARRAY_SIZE (header.keys); i++)
  414. {
  415. struct grub_geli_key candidate_key;
  416. grub_uint8_t key_hmac[GRUB_CRYPTO_MAX_MDLEN];
  417. /* Check if keyslot is enabled. */
  418. if (! (header.keys_used & (1 << i)))
  419. continue;
  420. grub_dprintf ("geli", "Trying keyslot %d\n", i);
  421. gcry_err = grub_crypto_cipher_set_key (dev->cipher,
  422. digest, keysize);
  423. if (gcry_err)
  424. return grub_crypto_gcry_error (gcry_err);
  425. gcry_err = grub_crypto_cbc_decrypt (dev->cipher, &candidate_key,
  426. &header.keys[i],
  427. sizeof (candidate_key),
  428. zero);
  429. if (gcry_err)
  430. return grub_crypto_gcry_error (gcry_err);
  431. gcry_err = grub_crypto_hmac_buffer (dev->hash, verify_key,
  432. dev->hash->mdlen,
  433. &candidate_key,
  434. (sizeof (candidate_key)
  435. - sizeof (candidate_key.hmac)),
  436. key_hmac);
  437. if (gcry_err)
  438. return grub_crypto_gcry_error (gcry_err);
  439. if (grub_memcmp (candidate_key.hmac, key_hmac, dev->hash->mdlen) != 0)
  440. continue;
  441. grub_printf_ (N_("Slot %d opened\n"), i);
  442. if (grub_le_to_cpu32 (header.version) >= 7)
  443. {
  444. /* GELI >=7 uses the cipher_key */
  445. grub_memcpy (geli_cipher_key, candidate_key.cipher_key,
  446. sizeof (candidate_key.cipher_key));
  447. }
  448. else
  449. {
  450. /* GELI <=6 uses the iv_key */
  451. grub_memcpy (geli_cipher_key, candidate_key.iv_key,
  452. sizeof (candidate_key.iv_key));
  453. }
  454. /* Set the master key. */
  455. if (!dev->rekey)
  456. {
  457. grub_size_t real_keysize = keysize;
  458. if (grub_le_to_cpu16 (header.alg) == 0x16)
  459. real_keysize *= 2;
  460. gcry_err = grub_cryptodisk_setkey (dev, candidate_key.cipher_key,
  461. real_keysize);
  462. if (gcry_err)
  463. return grub_crypto_gcry_error (gcry_err);
  464. }
  465. else
  466. {
  467. grub_size_t real_keysize = keysize;
  468. if (grub_le_to_cpu16 (header.alg) == 0x16)
  469. real_keysize *= 2;
  470. grub_memcpy (dev->rekey_key, geli_cipher_key,
  471. sizeof (geli_cipher_key));
  472. dev->rekey_derived_size = real_keysize;
  473. dev->last_rekey = -1;
  474. COMPILE_TIME_ASSERT (sizeof (dev->rekey_key)
  475. >= sizeof (geli_cipher_key));
  476. }
  477. dev->iv_prefix_len = sizeof (candidate_key.iv_key);
  478. grub_memcpy (dev->iv_prefix, candidate_key.iv_key,
  479. sizeof (candidate_key.iv_key));
  480. COMPILE_TIME_ASSERT (sizeof (dev->iv_prefix) >= sizeof (candidate_key.iv_key));
  481. return GRUB_ERR_NONE;
  482. }
  483. return GRUB_ACCESS_DENIED;
  484. }
  485. struct grub_cryptodisk_dev geli_crypto = {
  486. .scan = geli_scan,
  487. .recover_key = geli_recover_key
  488. };
  489. GRUB_MOD_INIT (geli)
  490. {
  491. grub_cryptodisk_dev_register (&geli_crypto);
  492. }
  493. GRUB_MOD_FINI (geli)
  494. {
  495. grub_cryptodisk_dev_unregister (&geli_crypto);
  496. }