0003-Cryptomount-luks-allow-multiple-passphrase-attempts.patch 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. From f39e8ee5696f15860c73b07e652a8b59fcc834c7 Mon Sep 17 00:00:00 2001
  2. From: John Lane <john@lane.uk.net>
  3. Date: Fri, 26 Jun 2015 13:49:58 +0100
  4. Subject: [PATCH 04/10] Cryptomount luks allow multiple passphrase attempts
  5. ---
  6. grub-core/disk/luks.c | 278 ++++++++++++++++++++++++++------------------------
  7. 1 file changed, 143 insertions(+), 135 deletions(-)
  8. diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
  9. index 5882368..11e437e 100644
  10. --- a/grub-core/disk/luks.c
  11. +++ b/grub-core/disk/luks.c
  12. @@ -321,10 +321,10 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
  13. static grub_err_t
  14. luks_recover_key (grub_disk_t source,
  15. - grub_cryptodisk_t dev,
  16. - grub_file_t hdr,
  17. - grub_uint8_t *keyfile_bytes,
  18. - grub_size_t keyfile_bytes_size)
  19. + grub_cryptodisk_t dev,
  20. + grub_file_t hdr,
  21. + grub_uint8_t *keyfile_bytes,
  22. + grub_size_t keyfile_bytes_size)
  23. {
  24. struct grub_luks_phdr header;
  25. grub_size_t keysize;
  26. @@ -339,6 +339,7 @@ luks_recover_key (grub_disk_t source,
  27. grub_size_t max_stripes = 1;
  28. char *tmp;
  29. grub_uint32_t sector;
  30. + unsigned attempts = 2;
  31. err = GRUB_ERR_NONE;
  32. @@ -361,151 +362,158 @@ luks_recover_key (grub_disk_t source,
  33. for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
  34. if (grub_be_to_cpu32 (header.keyblock[i].active) == LUKS_KEY_ENABLED
  35. - && grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes)
  36. + && grub_be_to_cpu32 (header.keyblock[i].stripes) > max_stripes)
  37. max_stripes = grub_be_to_cpu32 (header.keyblock[i].stripes);
  38. split_key = grub_malloc (keysize * max_stripes);
  39. if (!split_key)
  40. return grub_errno;
  41. - if (keyfile_bytes)
  42. + while (attempts)
  43. {
  44. - /* Use bytestring from key file as passphrase */
  45. - passphrase = keyfile_bytes;
  46. - passphrase_length = keyfile_bytes_size;
  47. - }
  48. - else
  49. - {
  50. - /* Get the passphrase from the user. */
  51. - tmp = NULL;
  52. - if (source->partition)
  53. - tmp = grub_partition_get_name (source->partition);
  54. - grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
  55. - source->partition ? "," : "", tmp ? : "", dev->uuid);
  56. - grub_free (tmp);
  57. - if (!grub_password_get (interactive_passphrase, MAX_PASSPHRASE))
  58. + if (keyfile_bytes)
  59. {
  60. - grub_free (split_key);
  61. - return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
  62. - }
  63. -
  64. - passphrase = (grub_uint8_t *)interactive_passphrase;
  65. - passphrase_length = grub_strlen (interactive_passphrase);
  66. -
  67. - }
  68. -
  69. - /* Try to recover master key from each active keyslot. */
  70. - for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
  71. - {
  72. - gcry_err_code_t gcry_err;
  73. - grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
  74. - grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN];
  75. -
  76. - /* Check if keyslot is enabled. */
  77. - if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED)
  78. - continue;
  79. -
  80. - grub_dprintf ("luks", "Trying keyslot %d\n", i);
  81. -
  82. - /* Calculate the PBKDF2 of the user supplied passphrase. */
  83. - gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
  84. - passphrase_length,
  85. - header.keyblock[i].passwordSalt,
  86. - sizeof (header.keyblock[i].passwordSalt),
  87. - grub_be_to_cpu32 (header.keyblock[i].
  88. - passwordIterations),
  89. - digest, keysize);
  90. -
  91. - if (gcry_err)
  92. - {
  93. - grub_free (split_key);
  94. - return grub_crypto_gcry_error (gcry_err);
  95. - }
  96. -
  97. - grub_dprintf ("luks", "PBKDF2 done\n");
  98. -
  99. - gcry_err = grub_cryptodisk_setkey (dev, digest, keysize);
  100. - if (gcry_err)
  101. - {
  102. - grub_free (split_key);
  103. - return grub_crypto_gcry_error (gcry_err);
  104. - }
  105. -
  106. - sector = grub_be_to_cpu32 (header.keyblock[i].keyMaterialOffset);
  107. - length = (keysize * grub_be_to_cpu32 (header.keyblock[i].stripes));
  108. -
  109. - /* Read and decrypt the key material from the disk. */
  110. - if (hdr)
  111. - {
  112. - grub_file_seek (hdr, sector * 512);
  113. - if (grub_file_read (hdr, split_key, length) != (grub_ssize_t)length)
  114. - err = GRUB_ERR_READ_ERROR;
  115. + /* Use bytestring from key file as passphrase */
  116. + passphrase = keyfile_bytes;
  117. + passphrase_length = keyfile_bytes_size;
  118. + keyfile_bytes = NULL; /* use it only once */
  119. }
  120. else
  121. - err = grub_disk_read (source, sector, 0, length, split_key);
  122. - if (err)
  123. - {
  124. - grub_free (split_key);
  125. - return err;
  126. - }
  127. -
  128. - gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
  129. - if (gcry_err)
  130. - {
  131. - grub_free (split_key);
  132. - return grub_crypto_gcry_error (gcry_err);
  133. - }
  134. -
  135. - /* Merge the decrypted key material to get the candidate master key. */
  136. - gcry_err = AF_merge (dev->hash, split_key, candidate_key, keysize,
  137. - grub_be_to_cpu32 (header.keyblock[i].stripes));
  138. - if (gcry_err)
  139. - {
  140. - grub_free (split_key);
  141. - return grub_crypto_gcry_error (gcry_err);
  142. - }
  143. -
  144. - grub_dprintf ("luks", "candidate key recovered\n");
  145. -
  146. - /* Calculate the PBKDF2 of the candidate master key. */
  147. - gcry_err = grub_crypto_pbkdf2 (dev->hash, candidate_key,
  148. - grub_be_to_cpu32 (header.keyBytes),
  149. - header.mkDigestSalt,
  150. - sizeof (header.mkDigestSalt),
  151. - grub_be_to_cpu32
  152. - (header.mkDigestIterations),
  153. - candidate_digest,
  154. - sizeof (candidate_digest));
  155. - if (gcry_err)
  156. - {
  157. - grub_free (split_key);
  158. - return grub_crypto_gcry_error (gcry_err);
  159. - }
  160. -
  161. - /* Compare the calculated PBKDF2 to the digest stored
  162. - in the header to see if it's correct. */
  163. - if (grub_memcmp (candidate_digest, header.mkDigest,
  164. - sizeof (header.mkDigest)) != 0)
  165. - {
  166. - grub_dprintf ("luks", "bad digest\n");
  167. - continue;
  168. - }
  169. + {
  170. + /* Get the passphrase from the user. */
  171. + tmp = NULL;
  172. + if (source->partition)
  173. + tmp = grub_partition_get_name (source->partition);
  174. + grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source->name,
  175. + source->partition ? "," : "", tmp ? : "", dev->uuid);
  176. + grub_free (tmp);
  177. + if (!grub_password_get (interactive_passphrase, MAX_PASSPHRASE))
  178. + {
  179. + grub_free (split_key);
  180. + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Passphrase not supplied");
  181. + }
  182. +
  183. + passphrase = (grub_uint8_t *)interactive_passphrase;
  184. + passphrase_length = grub_strlen (interactive_passphrase);
  185. - /* TRANSLATORS: It's a cryptographic key slot: one element of an array
  186. - where each element is either empty or holds a key. */
  187. - grub_printf_ (N_("Slot %d opened\n"), i);
  188. + }
  189. - /* Set the master key. */
  190. - gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize);
  191. - if (gcry_err)
  192. - {
  193. - grub_free (split_key);
  194. - return grub_crypto_gcry_error (gcry_err);
  195. - }
  196. + /* Try to recover master key from each active keyslot. */
  197. + for (i = 0; i < ARRAY_SIZE (header.keyblock); i++)
  198. + {
  199. + gcry_err_code_t gcry_err;
  200. + grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
  201. + grub_uint8_t digest[GRUB_CRYPTODISK_MAX_KEYLEN];
  202. +
  203. + /* Check if keyslot is enabled. */
  204. + if (grub_be_to_cpu32 (header.keyblock[i].active) != LUKS_KEY_ENABLED)
  205. + continue;
  206. +
  207. + grub_dprintf ("luks", "Trying keyslot %d\n", i);
  208. +
  209. + /* Calculate the PBKDF2 of the user supplied passphrase. */
  210. + gcry_err = grub_crypto_pbkdf2 (dev->hash, (grub_uint8_t *) passphrase,
  211. + passphrase_length,
  212. + header.keyblock[i].passwordSalt,
  213. + sizeof (header.keyblock[i].passwordSalt),
  214. + grub_be_to_cpu32 (header.keyblock[i].
  215. + passwordIterations),
  216. + digest, keysize);
  217. +
  218. + if (gcry_err)
  219. + {
  220. + grub_free (split_key);
  221. + return grub_crypto_gcry_error (gcry_err);
  222. + }
  223. +
  224. + grub_dprintf ("luks", "PBKDF2 done\n");
  225. +
  226. + gcry_err = grub_cryptodisk_setkey (dev, digest, keysize);
  227. + if (gcry_err)
  228. + {
  229. + grub_free (split_key);
  230. + return grub_crypto_gcry_error (gcry_err);
  231. + }
  232. +
  233. + sector = grub_be_to_cpu32 (header.keyblock[i].keyMaterialOffset);
  234. + length = (keysize * grub_be_to_cpu32 (header.keyblock[i].stripes));
  235. +
  236. + /* Read and decrypt the key material from the disk. */
  237. + if (hdr)
  238. + {
  239. + grub_file_seek (hdr, sector * 512);
  240. + if (grub_file_read (hdr, split_key, length) != (grub_ssize_t)length)
  241. + err = GRUB_ERR_READ_ERROR;
  242. + }
  243. + else
  244. + err = grub_disk_read (source, sector, 0, length, split_key);
  245. + if (err)
  246. + {
  247. + grub_free (split_key);
  248. + return err;
  249. + }
  250. +
  251. + gcry_err = grub_cryptodisk_decrypt (dev, split_key, length, 0);
  252. + if (gcry_err)
  253. + {
  254. + grub_free (split_key);
  255. + return grub_crypto_gcry_error (gcry_err);
  256. + }
  257. +
  258. + /* Merge the decrypted key material to get the candidate master key. */
  259. + gcry_err = AF_merge (dev->hash, split_key, candidate_key, keysize,
  260. + grub_be_to_cpu32 (header.keyblock[i].stripes));
  261. + if (gcry_err)
  262. + {
  263. + grub_free (split_key);
  264. + return grub_crypto_gcry_error (gcry_err);
  265. + }
  266. +
  267. + grub_dprintf ("luks", "candidate key recovered\n");
  268. +
  269. + /* Calculate the PBKDF2 of the candidate master key. */
  270. + gcry_err = grub_crypto_pbkdf2 (dev->hash, candidate_key,
  271. + grub_be_to_cpu32 (header.keyBytes),
  272. + header.mkDigestSalt,
  273. + sizeof (header.mkDigestSalt),
  274. + grub_be_to_cpu32
  275. + (header.mkDigestIterations),
  276. + candidate_digest,
  277. + sizeof (candidate_digest));
  278. + if (gcry_err)
  279. + {
  280. + grub_free (split_key);
  281. + return grub_crypto_gcry_error (gcry_err);
  282. + }
  283. +
  284. + /* Compare the calculated PBKDF2 to the digest stored
  285. + in the header to see if it's correct. */
  286. + if (grub_memcmp (candidate_digest, header.mkDigest,
  287. + sizeof (header.mkDigest)) != 0)
  288. + {
  289. + grub_dprintf ("luks", "bad digest\n");
  290. + continue;
  291. + }
  292. +
  293. + /* TRANSLATORS: It's a cryptographic key slot: one element of an array
  294. + where each element is either empty or holds a key. */
  295. + grub_printf_ (N_("Slot %d opened\n"), i);
  296. +
  297. + /* Set the master key. */
  298. + gcry_err = grub_cryptodisk_setkey (dev, candidate_key, keysize);
  299. + if (gcry_err)
  300. + {
  301. + grub_free (split_key);
  302. + return grub_crypto_gcry_error (gcry_err);
  303. + }
  304. - grub_free (split_key);
  305. + grub_free (split_key);
  306. - return GRUB_ERR_NONE;
  307. + return GRUB_ERR_NONE;
  308. + }
  309. + grub_printf_ (N_("Failed to decrypt master key.\n"));
  310. + if (--attempts) grub_printf_ (N_("%u attempt%s remaining.\n"), attempts,
  311. + (attempts==1) ? "" : "s");
  312. }
  313. grub_free (split_key);
  314. --
  315. 1.9.1