2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2019 Free Software Foundation, Inc.
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.
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.
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/>.
19 #include <grub/cryptodisk.h>
20 #include <grub/types.h>
21 #include <grub/misc.h>
25 #include <grub/disk.h>
26 #include <grub/crypto.h>
27 #include <grub/partition.h>
28 #include <grub/i18n.h>
33 GRUB_MOD_LICENSE ("GPLv3+");
35 #define LUKS_MAGIC_1ST "LUKS\xBA\xBE"
36 #define LUKS_MAGIC_2ND "SKUL\xBA\xBE"
38 #define MAX_PASSPHRASE 256
40 enum grub_luks2_kdf_type
42 LUKS2_KDF_TYPE_ARGON2I
,
45 typedef enum grub_luks2_kdf_type grub_luks2_kdf_type_t
;
47 /* On disk LUKS header */
48 struct grub_luks2_header
51 grub_uint16_t version
;
52 grub_uint64_t hdr_size
;
56 grub_uint8_t salt
[64];
59 grub_uint64_t hdr_offset
;
61 grub_uint8_t csum
[64];
62 char _padding4096
[7*512];
64 typedef struct grub_luks2_header grub_luks2_header_t
;
66 struct grub_luks2_keyslot
68 /* The integer key to the associative array of keyslots. */
70 grub_int64_t key_size
;
71 grub_int64_t priority
;
74 const char *encryption
;
77 grub_int64_t key_size
;
86 grub_luks2_kdf_type_t type
;
99 grub_int64_t iterations
;
104 typedef struct grub_luks2_keyslot grub_luks2_keyslot_t
;
106 struct grub_luks2_segment
109 grub_uint64_t offset
;
111 const char *encryption
;
112 grub_int64_t sector_size
;
114 typedef struct grub_luks2_segment grub_luks2_segment_t
;
116 struct grub_luks2_digest
119 /* Both keyslots and segments are interpreted as bitfields here */
120 grub_uint64_t keyslots
;
121 grub_uint64_t segments
;
125 grub_int64_t iterations
;
127 typedef struct grub_luks2_digest grub_luks2_digest_t
;
129 gcry_err_code_t
AF_merge (const gcry_md_spec_t
* hash
, grub_uint8_t
* src
,
130 grub_uint8_t
* dst
, grub_size_t blocksize
,
131 grub_size_t blocknumbers
);
134 luks2_parse_keyslot (grub_luks2_keyslot_t
*out
, const grub_json_t
*keyslot
)
136 grub_json_t area
, af
, kdf
;
139 if (grub_json_getstring (&type
, keyslot
, "type"))
140 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Missing or invalid keyslot");
141 else if (grub_strcmp (type
, "luks2"))
142 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Unsupported keyslot type %s", type
);
143 else if (grub_json_getint64 (&out
->key_size
, keyslot
, "key_size"))
144 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Missing keyslot information");
145 if (grub_json_getint64 (&out
->priority
, keyslot
, "priority"))
148 if (grub_json_getvalue (&area
, keyslot
, "area") ||
149 grub_json_getstring (&type
, &area
, "type"))
150 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Missing or invalid key area");
151 else if (grub_strcmp (type
, "raw"))
152 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Unsupported key area type: %s", type
);
153 else if (grub_json_getuint64 (&out
->area
.offset
, &area
, "offset") ||
154 grub_json_getuint64 (&out
->area
.size
, &area
, "size") ||
155 grub_json_getstring (&out
->area
.encryption
, &area
, "encryption") ||
156 grub_json_getint64 (&out
->area
.key_size
, &area
, "key_size"))
157 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Missing key area information");
159 if (grub_json_getvalue (&kdf
, keyslot
, "kdf") ||
160 grub_json_getstring (&type
, &kdf
, "type") ||
161 grub_json_getstring (&out
->kdf
.salt
, &kdf
, "salt"))
162 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Missing or invalid KDF");
163 else if (!grub_strcmp (type
, "argon2i") || !grub_strcmp (type
, "argon2id"))
165 out
->kdf
.type
= LUKS2_KDF_TYPE_ARGON2I
;
166 if (grub_json_getint64 (&out
->kdf
.u
.argon2i
.time
, &kdf
, "time") ||
167 grub_json_getint64 (&out
->kdf
.u
.argon2i
.memory
, &kdf
, "memory") ||
168 grub_json_getint64 (&out
->kdf
.u
.argon2i
.cpus
, &kdf
, "cpus"))
169 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Missing Argon2i parameters");
171 else if (!grub_strcmp (type
, "pbkdf2"))
173 out
->kdf
.type
= LUKS2_KDF_TYPE_PBKDF2
;
174 if (grub_json_getstring (&out
->kdf
.u
.pbkdf2
.hash
, &kdf
, "hash") ||
175 grub_json_getint64 (&out
->kdf
.u
.pbkdf2
.iterations
, &kdf
, "iterations"))
176 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Missing PBKDF2 parameters");
179 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Unsupported KDF type %s", type
);
181 if (grub_json_getvalue (&af
, keyslot
, "af") ||
182 grub_json_getstring (&type
, &af
, "type"))
183 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "missing or invalid area");
184 if (grub_strcmp (type
, "luks1"))
185 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Unsupported AF type %s", type
);
186 if (grub_json_getint64 (&out
->af
.stripes
, &af
, "stripes") ||
187 grub_json_getstring (&out
->af
.hash
, &af
, "hash"))
188 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Missing AF parameters");
190 return GRUB_ERR_NONE
;
194 luks2_parse_segment (grub_luks2_segment_t
*out
, const grub_json_t
*segment
)
198 if (grub_json_getstring (&type
, segment
, "type"))
199 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Invalid segment type");
200 else if (grub_strcmp (type
, "crypt"))
201 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Unsupported segment type %s", type
);
203 if (grub_json_getuint64 (&out
->offset
, segment
, "offset") ||
204 grub_json_getstring (&out
->size
, segment
, "size") ||
205 grub_json_getstring (&out
->encryption
, segment
, "encryption") ||
206 grub_json_getint64 (&out
->sector_size
, segment
, "sector_size"))
207 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Missing segment parameters");
209 return GRUB_ERR_NONE
;
213 luks2_parse_digest (grub_luks2_digest_t
*out
, const grub_json_t
*digest
)
215 grub_json_t segments
, keyslots
, o
;
220 if (grub_json_getstring (&type
, digest
, "type"))
221 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Invalid digest type");
222 else if (grub_strcmp (type
, "pbkdf2"))
223 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Unsupported digest type %s", type
);
225 if (grub_json_getvalue (&segments
, digest
, "segments") ||
226 grub_json_getvalue (&keyslots
, digest
, "keyslots") ||
227 grub_json_getstring (&out
->salt
, digest
, "salt") ||
228 grub_json_getstring (&out
->digest
, digest
, "digest") ||
229 grub_json_getstring (&out
->hash
, digest
, "hash") ||
230 grub_json_getint64 (&out
->iterations
, digest
, "iterations"))
231 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Missing digest parameters");
233 if (grub_json_getsize (&size
, &segments
))
234 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
235 "Digest references no segments");
238 for (i
= 0; i
< size
; i
++)
240 if (grub_json_getchild (&o
, &segments
, i
) ||
241 grub_json_getuint64 (&bit
, &o
, NULL
))
242 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Invalid segment");
243 out
->segments
|= (1 << bit
);
246 if (grub_json_getsize (&size
, &keyslots
))
247 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
248 "Digest references no keyslots");
251 for (i
= 0; i
< size
; i
++)
253 if (grub_json_getchild (&o
, &keyslots
, i
) ||
254 grub_json_getuint64 (&bit
, &o
, NULL
))
255 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Invalid keyslot");
256 out
->keyslots
|= (1 << bit
);
259 return GRUB_ERR_NONE
;
263 luks2_get_keyslot (grub_luks2_keyslot_t
*k
, grub_luks2_digest_t
*d
, grub_luks2_segment_t
*s
,
264 const grub_json_t
*root
, grub_size_t keyslot_json_idx
)
266 grub_json_t keyslots
, keyslot
, digests
, digest
, segments
, segment
;
267 grub_size_t json_idx
, size
;
269 /* Get nth keyslot */
270 if (grub_json_getvalue (&keyslots
, root
, "keyslots") ||
271 grub_json_getchild (&keyslot
, &keyslots
, keyslot_json_idx
) ||
272 grub_json_getuint64 (&k
->idx
, &keyslot
, NULL
) ||
273 grub_json_getchild (&keyslot
, &keyslot
, 0) ||
274 luks2_parse_keyslot (k
, &keyslot
))
275 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Could not parse keyslot index %"PRIuGRUB_SIZE
, keyslot_json_idx
);
277 /* Get digest that matches the keyslot. */
278 if (grub_json_getvalue (&digests
, root
, "digests") ||
279 grub_json_getsize (&size
, &digests
))
280 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Could not get digests");
281 for (json_idx
= 0; json_idx
< size
; json_idx
++)
283 if (grub_json_getchild (&digest
, &digests
, json_idx
) ||
284 grub_json_getuint64 (&d
->idx
, &digest
, NULL
) ||
285 grub_json_getchild (&digest
, &digest
, 0) ||
286 luks2_parse_digest (d
, &digest
))
287 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Could not parse digest index %"PRIuGRUB_SIZE
, json_idx
);
289 if ((d
->keyslots
& (1 << k
->idx
)))
292 if (json_idx
== size
)
293 return grub_error (GRUB_ERR_FILE_NOT_FOUND
, "No digest for keyslot \"%"PRIuGRUB_UINT64_T
"\"", k
->idx
);
295 /* Get segment that matches the digest. */
296 if (grub_json_getvalue (&segments
, root
, "segments") ||
297 grub_json_getsize (&size
, &segments
))
298 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Could not get segments");
299 for (json_idx
= 0; json_idx
< size
; json_idx
++)
301 if (grub_json_getchild (&segment
, &segments
, json_idx
) ||
302 grub_json_getuint64 (&s
->idx
, &segment
, NULL
) ||
303 grub_json_getchild (&segment
, &segment
, 0) ||
304 luks2_parse_segment (s
, &segment
))
305 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Could not parse segment index %"PRIuGRUB_SIZE
, json_idx
);
307 if ((d
->segments
& (1 << s
->idx
)))
310 if (json_idx
== size
)
311 return grub_error (GRUB_ERR_FILE_NOT_FOUND
, "No segment for digest \"%"PRIuGRUB_UINT64_T
"\"", d
->idx
);
313 return GRUB_ERR_NONE
;
316 /* Determine whether to use primary or secondary header */
318 luks2_read_header (grub_disk_t disk
, grub_luks2_header_t
*outhdr
)
320 grub_luks2_header_t primary
, secondary
, *header
= &primary
;
323 /* Read the primary LUKS header. */
324 ret
= grub_disk_read (disk
, 0, 0, sizeof (primary
), &primary
);
328 /* Look for LUKS magic sequence. */
329 if (grub_memcmp (primary
.magic
, LUKS_MAGIC_1ST
, sizeof (primary
.magic
)) ||
330 grub_be_to_cpu16 (primary
.version
) != 2)
331 return GRUB_ERR_BAD_SIGNATURE
;
333 /* Read the secondary header. */
334 ret
= grub_disk_read (disk
, 0, grub_be_to_cpu64 (primary
.hdr_size
), sizeof (secondary
), &secondary
);
338 /* Look for LUKS magic sequence. */
339 if (grub_memcmp (secondary
.magic
, LUKS_MAGIC_2ND
, sizeof (secondary
.magic
)) ||
340 grub_be_to_cpu16 (secondary
.version
) != 2)
341 return GRUB_ERR_BAD_SIGNATURE
;
343 if (grub_be_to_cpu64 (primary
.seqid
) < grub_be_to_cpu64 (secondary
.seqid
))
345 grub_memcpy (outhdr
, header
, sizeof (*header
));
347 return GRUB_ERR_NONE
;
350 static grub_cryptodisk_t
351 luks2_scan (grub_disk_t disk
, const char *check_uuid
, int check_boot
)
353 grub_cryptodisk_t cryptodisk
;
354 grub_luks2_header_t header
;
355 char uuid
[sizeof (header
.uuid
) + 1];
361 if (luks2_read_header (disk
, &header
))
363 grub_errno
= GRUB_ERR_NONE
;
367 for (i
= 0, j
= 0; i
< sizeof (header
.uuid
); i
++)
368 if (header
.uuid
[i
] != '-')
369 uuid
[j
++] = header
.uuid
[i
];
372 if (check_uuid
&& grub_strcasecmp (check_uuid
, uuid
) != 0)
375 cryptodisk
= grub_zalloc (sizeof (*cryptodisk
));
379 COMPILE_TIME_ASSERT (sizeof (cryptodisk
->uuid
) >= sizeof (uuid
));
380 grub_memcpy (cryptodisk
->uuid
, uuid
, sizeof (uuid
));
382 cryptodisk
->modname
= "luks2";
387 luks2_verify_key (grub_luks2_digest_t
*d
, grub_uint8_t
*candidate_key
,
388 grub_size_t candidate_key_len
)
390 grub_uint8_t candidate_digest
[GRUB_CRYPTODISK_MAX_KEYLEN
];
391 grub_uint8_t digest
[GRUB_CRYPTODISK_MAX_KEYLEN
], salt
[GRUB_CRYPTODISK_MAX_KEYLEN
];
392 grub_size_t saltlen
= sizeof (salt
), digestlen
= sizeof (digest
);
393 const gcry_md_spec_t
*hash
;
394 gcry_err_code_t gcry_ret
;
396 /* Decode both digest and salt */
397 if (!base64_decode (d
->digest
, grub_strlen (d
->digest
), (char *)digest
, &digestlen
))
398 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Invalid digest");
399 if (!base64_decode (d
->salt
, grub_strlen (d
->salt
), (char *)salt
, &saltlen
))
400 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Invalid digest salt");
402 /* Configure the hash used for the digest. */
403 hash
= grub_crypto_lookup_md_by_name (d
->hash
);
405 return grub_error (GRUB_ERR_FILE_NOT_FOUND
, "Couldn't load %s hash", d
->hash
);
407 /* Calculate the candidate key's digest */
408 gcry_ret
= grub_crypto_pbkdf2 (hash
,
409 candidate_key
, candidate_key_len
,
412 candidate_digest
, digestlen
);
414 return grub_crypto_gcry_error (gcry_ret
);
416 if (grub_memcmp (candidate_digest
, digest
, digestlen
) != 0)
417 return grub_error (GRUB_ERR_ACCESS_DENIED
, "Mismatching digests");
419 return GRUB_ERR_NONE
;
423 luks2_decrypt_key (grub_uint8_t
*out_key
,
424 grub_disk_t source
, grub_cryptodisk_t crypt
,
425 grub_luks2_keyslot_t
*k
,
426 const grub_uint8_t
*passphrase
, grub_size_t passphraselen
)
428 grub_uint8_t area_key
[GRUB_CRYPTODISK_MAX_KEYLEN
];
429 grub_uint8_t salt
[GRUB_CRYPTODISK_MAX_KEYLEN
];
430 grub_uint8_t
*split_key
= NULL
;
431 grub_size_t saltlen
= sizeof (salt
);
433 const gcry_md_spec_t
*hash
;
434 gcry_err_code_t gcry_ret
;
437 if (!base64_decode (k
->kdf
.salt
, grub_strlen (k
->kdf
.salt
),
438 (char *)salt
, &saltlen
))
440 ret
= grub_error (GRUB_ERR_BAD_ARGUMENT
, "Invalid keyslot salt");
444 /* Calculate the binary area key of the user supplied passphrase. */
447 case LUKS2_KDF_TYPE_ARGON2I
:
448 ret
= grub_error (GRUB_ERR_BAD_ARGUMENT
, "Argon2 not supported");
450 case LUKS2_KDF_TYPE_PBKDF2
:
451 hash
= grub_crypto_lookup_md_by_name (k
->kdf
.u
.pbkdf2
.hash
);
454 ret
= grub_error (GRUB_ERR_FILE_NOT_FOUND
, "Couldn't load %s hash",
455 k
->kdf
.u
.pbkdf2
.hash
);
459 gcry_ret
= grub_crypto_pbkdf2 (hash
, (grub_uint8_t
*) passphrase
,
462 k
->kdf
.u
.pbkdf2
.iterations
,
463 area_key
, k
->area
.key_size
);
466 ret
= grub_crypto_gcry_error (gcry_ret
);
473 /* Set up disk encryption parameters for the key area */
474 grub_strncpy (cipher
, k
->area
.encryption
, sizeof (cipher
));
475 p
= grub_memchr (cipher
, '-', grub_strlen (cipher
));
477 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Invalid encryption");
480 ret
= grub_cryptodisk_setcipher (crypt
, cipher
, p
+ 1);
484 gcry_ret
= grub_cryptodisk_setkey (crypt
, area_key
, k
->area
.key_size
);
487 ret
= grub_crypto_gcry_error (gcry_ret
);
491 /* Read and decrypt the binary key area with the area key. */
492 split_key
= grub_malloc (k
->area
.size
);
499 grub_errno
= GRUB_ERR_NONE
;
500 ret
= grub_disk_read (source
, 0, k
->area
.offset
, k
->area
.size
, split_key
);
503 grub_error (GRUB_ERR_IO
, "Read error: %s\n", grub_errmsg
);
508 * The key slots area is always encrypted in 512-byte sectors,
509 * regardless of encrypted data sector size.
511 gcry_ret
= grub_cryptodisk_decrypt (crypt
, split_key
, k
->area
.size
, 0,
512 GRUB_LUKS1_LOG_SECTOR_SIZE
);
515 ret
= grub_crypto_gcry_error (gcry_ret
);
519 /* Configure the hash used for anti-forensic merging. */
520 hash
= grub_crypto_lookup_md_by_name (k
->af
.hash
);
523 ret
= grub_error (GRUB_ERR_FILE_NOT_FOUND
, "Couldn't load %s hash",
528 /* Merge the decrypted key material to get the candidate master key. */
529 gcry_ret
= AF_merge (hash
, split_key
, out_key
, k
->key_size
, k
->af
.stripes
);
532 ret
= grub_crypto_gcry_error (gcry_ret
);
536 grub_dprintf ("luks2", "Candidate key recovered\n");
539 grub_free (split_key
);
544 luks2_recover_key (grub_disk_t source
,
545 grub_cryptodisk_t crypt
)
547 grub_uint8_t candidate_key
[GRUB_CRYPTODISK_MAX_KEYLEN
];
548 char passphrase
[MAX_PASSPHRASE
], cipher
[32];
549 char *json_header
= NULL
, *part
= NULL
, *ptr
;
550 grub_size_t candidate_key_len
= 0, json_idx
, size
;
551 grub_luks2_header_t header
;
552 grub_luks2_keyslot_t keyslot
;
553 grub_luks2_digest_t digest
;
554 grub_luks2_segment_t segment
;
555 gcry_err_code_t gcry_ret
;
556 grub_json_t
*json
= NULL
, keyslots
;
559 ret
= luks2_read_header (source
, &header
);
563 json_header
= grub_zalloc (grub_be_to_cpu64 (header
.hdr_size
) - sizeof (header
));
565 return GRUB_ERR_OUT_OF_MEMORY
;
567 /* Read the JSON area. */
568 ret
= grub_disk_read (source
, 0, grub_be_to_cpu64 (header
.hdr_offset
) + sizeof (header
),
569 grub_be_to_cpu64 (header
.hdr_size
) - sizeof (header
), json_header
);
573 ptr
= grub_memchr (json_header
, 0, grub_be_to_cpu64 (header
.hdr_size
) - sizeof (header
));
577 ret
= grub_json_parse (&json
, json_header
, grub_be_to_cpu64 (header
.hdr_size
));
580 ret
= grub_error (GRUB_ERR_BAD_ARGUMENT
, "Invalid LUKS2 JSON header");
584 /* Get the passphrase from the user. */
585 if (source
->partition
)
586 part
= grub_partition_get_name (source
->partition
);
587 grub_printf_ (N_("Enter passphrase for %s%s%s (%s): "), source
->name
,
588 source
->partition
? "," : "", part
? : "",
590 if (!grub_password_get (passphrase
, MAX_PASSPHRASE
))
592 ret
= grub_error (GRUB_ERR_BAD_ARGUMENT
, "Passphrase not supplied");
596 if (grub_json_getvalue (&keyslots
, json
, "keyslots") ||
597 grub_json_getsize (&size
, &keyslots
))
599 ret
= grub_error (GRUB_ERR_BAD_ARGUMENT
, "Could not get keyslots");
603 if (grub_disk_native_sectors (source
) == GRUB_DISK_SIZE_UNKNOWN
)
605 /* FIXME: Allow use of source disk, and maybe cause errors in read. */
606 grub_dprintf ("luks2", "Source disk %s has an unknown size, "
607 "conservatively returning error\n", source
->name
);
608 ret
= grub_error (GRUB_ERR_BUG
, "Unknown size of luks2 source device");
612 /* Try all keyslot */
613 for (json_idx
= 0; json_idx
< size
; json_idx
++)
615 typeof (source
->total_sectors
) max_crypt_sectors
= 0;
617 grub_errno
= GRUB_ERR_NONE
;
618 ret
= luks2_get_keyslot (&keyslot
, &digest
, &segment
, json
, json_idx
);
621 if (grub_errno
!= GRUB_ERR_NONE
)
622 grub_dprintf ("luks2", "Ignoring unhandled error %d from luks2_get_keyslot\n", grub_errno
);
624 if (keyslot
.priority
== 0)
626 grub_dprintf ("luks2", "Ignoring keyslot \"%"PRIuGRUB_UINT64_T
"\" due to priority\n", keyslot
.idx
);
630 grub_dprintf ("luks2", "Trying keyslot \"%"PRIuGRUB_UINT64_T
"\"\n", keyslot
.idx
);
632 /* Sector size should be one of 512, 1024, 2048, or 4096. */
633 if (!(segment
.sector_size
== 512 || segment
.sector_size
== 1024 ||
634 segment
.sector_size
== 2048 || segment
.sector_size
== 4096))
636 grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T
"\" sector"
637 " size %"PRIuGRUB_UINT64_T
" is not one of"
638 " 512, 1024, 2048, or 4096\n",
639 segment
.idx
, segment
.sector_size
);
643 /* Set up disk according to keyslot's segment. */
644 crypt
->offset_sectors
= grub_divmod64 (segment
.offset
, segment
.sector_size
, NULL
);
645 crypt
->log_sector_size
= sizeof (unsigned int) * 8
646 - __builtin_clz ((unsigned int) segment
.sector_size
) - 1;
647 /* Set to the source disk/partition size, which is the maximum we allow. */
648 max_crypt_sectors
= grub_disk_native_sectors (source
);
649 max_crypt_sectors
= grub_convert_sector (max_crypt_sectors
, GRUB_DISK_SECTOR_BITS
,
650 crypt
->log_sector_size
);
652 if (max_crypt_sectors
< crypt
->offset_sectors
)
654 grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T
"\" has offset"
655 " %"PRIuGRUB_UINT64_T
" which is greater than"
656 " source disk size %"PRIuGRUB_UINT64_T
","
657 " skipping\n", segment
.idx
, crypt
->offset_sectors
,
662 if (grub_strcmp (segment
.size
, "dynamic") == 0)
663 crypt
->total_sectors
= max_crypt_sectors
- crypt
->offset_sectors
;
666 grub_errno
= GRUB_ERR_NONE
;
668 /* Convert segment.size to sectors, rounding up to nearest sector */
669 crypt
->total_sectors
= grub_strtoull (segment
.size
, NULL
, 10);
671 if (grub_errno
== GRUB_ERR_NONE
)
673 crypt
->total_sectors
= ALIGN_UP (crypt
->total_sectors
,
674 1 << crypt
->log_sector_size
);
675 crypt
->total_sectors
>>= crypt
->log_sector_size
;
677 else if (grub_errno
== GRUB_ERR_BAD_NUMBER
)
679 grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T
"\" size"
680 " \"%s\" is not a parsable number,"
681 " skipping keyslot\n",
682 segment
.idx
, segment
.size
);
685 else if (grub_errno
== GRUB_ERR_OUT_OF_RANGE
)
688 * There was an overflow in parsing segment.size, so disk must
689 * be very large or the string is incorrect.
691 * TODO: Allow reading of at least up max_crypt_sectors. Really,
692 * its very unlikely one would be booting from such a large drive
693 * anyway. Use another smaller LUKS2 boot device.
695 grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T
"\" size"
696 " %s overflowed 64-bit unsigned integer,"
697 " skipping keyslot\n", segment
.idx
, segment
.size
);
702 if (crypt
->total_sectors
== 0)
704 grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T
"\" has zero"
705 " sectors, skipping\n", segment
.idx
);
708 else if (max_crypt_sectors
< (crypt
->offset_sectors
+ crypt
->total_sectors
))
710 grub_dprintf ("luks2", "Segment \"%"PRIuGRUB_UINT64_T
"\" has last"
711 " data position greater than source disk size,"
712 " the end of the crypto device will be"
713 " inaccessible\n", segment
.idx
);
715 /* Allow decryption up to the end of the source disk. */
716 crypt
->total_sectors
= max_crypt_sectors
- crypt
->offset_sectors
;
719 ret
= luks2_decrypt_key (candidate_key
, source
, crypt
, &keyslot
,
720 (const grub_uint8_t
*) passphrase
, grub_strlen (passphrase
));
723 grub_dprintf ("luks2", "Decryption with keyslot \"%"PRIuGRUB_UINT64_T
"\" failed: %s\n",
724 keyslot
.idx
, grub_errmsg
);
728 ret
= luks2_verify_key (&digest
, candidate_key
, keyslot
.key_size
);
731 grub_dprintf ("luks2", "Could not open keyslot \"%"PRIuGRUB_UINT64_T
"\": %s\n",
732 keyslot
.idx
, grub_errmsg
);
737 * TRANSLATORS: It's a cryptographic key slot: one element of an array
738 * where each element is either empty or holds a key.
740 grub_printf_ (N_("Slot \"%"PRIuGRUB_UINT64_T
"\" opened\n"), keyslot
.idx
);
742 candidate_key_len
= keyslot
.key_size
;
745 if (candidate_key_len
== 0)
747 ret
= grub_error (GRUB_ERR_ACCESS_DENIED
, "Invalid passphrase");
751 /* Set up disk cipher. */
752 grub_strncpy (cipher
, segment
.encryption
, sizeof (cipher
));
753 ptr
= grub_memchr (cipher
, '-', grub_strlen (cipher
));
755 return grub_error (GRUB_ERR_BAD_ARGUMENT
, "Invalid encryption");
758 ret
= grub_cryptodisk_setcipher (crypt
, cipher
, ptr
+ 1);
762 /* Set the master key. */
763 gcry_ret
= grub_cryptodisk_setkey (crypt
, candidate_key
, candidate_key_len
);
766 ret
= grub_crypto_gcry_error (gcry_ret
);
772 grub_free (json_header
);
773 grub_json_free (json
);
777 static struct grub_cryptodisk_dev luks2_crypto
= {
779 .recover_key
= luks2_recover_key
782 GRUB_MOD_INIT (luks2
)
784 grub_cryptodisk_dev_register (&luks2_crypto
);
787 GRUB_MOD_FINI (luks2
)
789 grub_cryptodisk_dev_unregister (&luks2_crypto
);