]>
Commit | Line | Data |
---|---|---|
7fd3d6f6 BH |
1 | From: Josselin Poiret <dev@jpoiret.xyz> |
2 | Date: Thu, 12 Jan 2023 17:05:09 -0600 | |
3 | Subject: osdep/devmapper/getroot: Set up cheated LUKS2 cryptodisk mount from | |
4 | DM parameters | |
5 | Origin: https://git.savannah.gnu.org/cgit/grub.git/commit/?id=aa5172a55cfabdd0bed3161ad44fc228b9d019f7 | |
6 | Bug-Debian: https://bugs.debian.org/1028301 | |
7 | ||
8 | This lets a LUKS2 cryptodisk have its cipher and hash filled out, | |
9 | otherwise they wouldn't be initialized if cheat mounted. | |
10 | ||
11 | Signed-off-by: Josselin Poiret <dev@jpoiret.xyz> | |
12 | Tested-by: Glenn Washburn <development@efficientek.com> | |
13 | Reviewed-by: Patrick Steinhardt <ps@pks.im> | |
14 | Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> | |
15 | --- | |
16 | grub-core/osdep/devmapper/getroot.c | 107 +++++++++++++++++++++++++++++++++++- | |
17 | 1 file changed, 106 insertions(+), 1 deletion(-) | |
18 | ||
19 | diff --git a/grub-core/osdep/devmapper/getroot.c b/grub-core/osdep/devmapper/getroot.c | |
20 | index 2bf4264..cc3f7da 100644 | |
21 | --- a/grub-core/osdep/devmapper/getroot.c | |
22 | +++ b/grub-core/osdep/devmapper/getroot.c | |
23 | @@ -51,6 +51,8 @@ | |
24 | #include <grub/emu/misc.h> | |
25 | #include <grub/emu/hostdisk.h> | |
26 | ||
27 | +#include <grub/cryptodisk.h> | |
28 | + | |
29 | static int | |
30 | grub_util_open_dm (const char *os_dev, struct dm_tree **tree, | |
31 | struct dm_tree_node **node) | |
32 | @@ -186,7 +188,6 @@ grub_util_pull_devmapper (const char *os_dev) | |
33 | && lastsubdev) | |
34 | { | |
35 | char *grdev = grub_util_get_grub_dev (lastsubdev); | |
36 | - dm_tree_free (tree); | |
37 | if (grdev) | |
38 | { | |
39 | grub_err_t err; | |
40 | @@ -194,7 +195,111 @@ grub_util_pull_devmapper (const char *os_dev) | |
41 | if (err) | |
42 | grub_util_error (_("can't mount encrypted volume `%s': %s"), | |
43 | lastsubdev, grub_errmsg); | |
44 | + if (strncmp (uuid, "CRYPT-LUKS2-", sizeof ("CRYPT-LUKS2-") - 1) == 0) | |
45 | + { | |
46 | + /* | |
47 | + * Set LUKS2 cipher from dm parameters, since it is not | |
48 | + * possible to determine the correct one without | |
49 | + * unlocking, as there might be multiple segments. | |
50 | + */ | |
51 | + grub_disk_t source; | |
52 | + grub_cryptodisk_t cryptodisk; | |
53 | + grub_uint64_t start, length; | |
54 | + char *target_type; | |
55 | + char *params; | |
56 | + const char *name; | |
57 | + char *cipher, *cipher_mode; | |
58 | + struct dm_task *dmt; | |
59 | + char *seek_head, *c; | |
60 | + unsigned int remaining; | |
61 | + | |
62 | + source = grub_disk_open (grdev); | |
63 | + if (! source) | |
64 | + grub_util_error (_("cannot open grub disk `%s'"), grdev); | |
65 | + cryptodisk = grub_cryptodisk_get_by_source_disk (source); | |
66 | + if (! cryptodisk) | |
67 | + grub_util_error (_("cannot get cryptodisk from source disk `%s'"), grdev); | |
68 | + grub_disk_close (source); | |
69 | + | |
70 | + /* | |
71 | + * The following function always returns a non-NULL pointer, | |
72 | + * but the string may be empty if the relevant info is not present. | |
73 | + */ | |
74 | + name = dm_tree_node_get_name (node); | |
75 | + if (*name == '\0') | |
76 | + grub_util_error (_("cannot get dm node name for grub dev `%s'"), grdev); | |
77 | + | |
78 | + grub_util_info ("populating parameters of cryptomount `%s' from DM device `%s'", | |
79 | + uuid, name); | |
80 | + | |
81 | + dmt = dm_task_create (DM_DEVICE_TABLE); | |
82 | + if (dmt == NULL) | |
83 | + grub_util_error (_("can't create dm task DM_DEVICE_TABLE")); | |
84 | + if (dm_task_set_name (dmt, name) == 0) | |
85 | + grub_util_error (_("can't set dm task name to `%s'"), name); | |
86 | + if (dm_task_run (dmt) == 0) | |
87 | + grub_util_error (_("can't run dm task for `%s'"), name); | |
88 | + /* | |
89 | + * dm_get_next_target() doesn't have any error modes, everything has | |
90 | + * been handled by dm_task_run(). | |
91 | + */ | |
92 | + dm_get_next_target (dmt, NULL, &start, &length, | |
93 | + &target_type, ¶ms); | |
94 | + if (strncmp (target_type, "crypt", sizeof ("crypt")) != 0) | |
95 | + grub_util_error (_("dm target of type `%s' is not `crypt'"), target_type); | |
96 | + | |
97 | + /* | |
98 | + * The dm target parameters for dm-crypt are | |
99 | + * <cipher> <key> <iv_offset> <device path> <offset> [<#opt_params> <opt_param1> ...] | |
100 | + */ | |
101 | + c = params; | |
102 | + remaining = grub_strlen (c); | |
103 | + | |
104 | + /* First, get the cipher name from the cipher. */ | |
105 | + seek_head = grub_memchr (c, '-', remaining); | |
106 | + if (seek_head == NULL) | |
107 | + grub_util_error (_("can't get cipher from dm-crypt parameters `%s'"), | |
108 | + params); | |
109 | + cipher = grub_strndup (c, seek_head - c); | |
110 | + if (cipher == NULL) | |
8818b1d7 | 111 | + grub_util_error (_("could not strndup cipher of length `%lu'"), (unsigned long)(seek_head - c)); |
7fd3d6f6 BH |
112 | + remaining -= seek_head - c + 1; |
113 | + c = seek_head + 1; | |
114 | + | |
115 | + /* Now, the cipher mode. */ | |
116 | + seek_head = grub_memchr (c, ' ', remaining); | |
117 | + if (seek_head == NULL) | |
118 | + grub_util_error (_("can't get cipher mode from dm-crypt parameters `%s'"), | |
119 | + params); | |
120 | + cipher_mode = grub_strndup (c, seek_head - c); | |
121 | + if (cipher_mode == NULL) | |
8818b1d7 | 122 | + grub_util_error (_("could not strndup cipher_mode of length `%lu'"), (unsigned long)(seek_head - c)); |
7fd3d6f6 BH |
123 | + |
124 | + remaining -= seek_head - c + 1; | |
125 | + c = seek_head + 1; | |
126 | + | |
127 | + err = grub_cryptodisk_setcipher (cryptodisk, cipher, cipher_mode); | |
128 | + if (err) | |
129 | + grub_util_error (_("can't set cipher of cryptodisk `%s' to `%s' with mode `%s'"), | |
130 | + uuid, cipher, cipher_mode); | |
131 | + | |
132 | + grub_free (cipher); | |
133 | + grub_free (cipher_mode); | |
134 | + | |
135 | + /* | |
136 | + * This is the only hash usable by PBKDF2, and we don't | |
137 | + * have Argon2 support yet, so set it by default, | |
138 | + * otherwise grub-probe would miss the required | |
139 | + * abstraction. | |
140 | + */ | |
141 | + cryptodisk->hash = grub_crypto_lookup_md_by_name ("sha256"); | |
142 | + if (cryptodisk->hash == NULL) | |
143 | + grub_util_error (_("can't lookup hash sha256 by name")); | |
144 | + | |
145 | + dm_task_destroy (dmt); | |
146 | + } | |
147 | } | |
148 | + dm_tree_free (tree); | |
149 | grub_free (grdev); | |
150 | } | |
151 | else | |
152 | -- | |
153 | cgit v1.1 | |
154 |