summaryrefslogtreecommitdiff
path: root/libre/grub-crypt-git/v6-0005-cryptodisk-enable-the-backends-to-implement-key-f.patch
blob: b9f727211f51a117206d8ef746ffc82c60c3ba05 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
From f17a54035876808331c7ab753a0706de4bf46a7a Mon Sep 17 00:00:00 2001
From: John Lane <john@lane.uk.net>
Date: Tue, 23 Jun 2015 11:16:30 +0100
Subject: [PATCH v6 5/6] cryptodisk: enable the backends to implement key files

Signed-off-by: John Lane <john@lane.uk.net>
GNUtoo@cyberdimension.org: rebase, patch split, small fixes, commit message
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
Reviewed-by: Patrick Steinhardt <ps@pks.im>
---
 grub-core/disk/cryptodisk.c | 87 ++++++++++++++++++++++++++++++++++++-
 grub-core/disk/geli.c       |  7 +--
 grub-core/disk/luks.c       |  7 ++-
 grub-core/disk/luks2.c      |  7 +--
 include/grub/cryptodisk.h   |  5 ++-
 include/grub/file.h         |  2 +
 6 files changed, 106 insertions(+), 9 deletions(-)

diff --git a/grub-core/disk/cryptodisk.c b/grub-core/disk/cryptodisk.c
index 6ad2e486e..dd94736d3 100644
--- a/grub-core/disk/cryptodisk.c
+++ b/grub-core/disk/cryptodisk.c
@@ -42,6 +42,9 @@ static const struct grub_arg_option options[] =
     {"all", 'a', 0, N_("Mount all."), 0, 0},
     {"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0},
     {"header", 'H', 0, N_("Read header from file"), 0, ARG_TYPE_STRING},
+    {"keyfile", 'k', 0, N_("Key file"), 0, ARG_TYPE_STRING},
+    {"keyfile-offset", 'O', 0, N_("Key file offset (bytes)"), 0, ARG_TYPE_INT},
+    {"keyfile-size", 'S', 0, N_("Key file data size (bytes)"), 0, ARG_TYPE_INT},
     {0, 0, 0, 0, 0, 0}
   };
 
@@ -972,6 +975,8 @@ grub_util_cryptodisk_get_uuid (grub_disk_t disk)
 static int check_boot, have_it;
 static char *search_uuid;
 static grub_file_t hdr;
+static grub_uint8_t *key, keyfile_buffer[GRUB_CRYPTODISK_MAX_KEYFILE_SIZE];
+static grub_ssize_t key_size;
 
 static void
 cryptodisk_close (grub_cryptodisk_t dev)
@@ -1002,7 +1007,7 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
     if (!dev)
       continue;
     
-    err = cr->recover_key (source, dev, hdr);
+    err = cr->recover_key (source, dev, hdr, key, key_size);
     if (err)
     {
       cryptodisk_close (dev);
@@ -1112,6 +1117,86 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
     hdr = NULL;
 
   have_it = 0;
+  key = NULL;
+
+  if (state[4].set) /* keyfile */
+    {
+      const char *p = NULL;
+      grub_file_t keyfile;
+      int keyfile_offset;
+      grub_size_t requested_keyfile_size = 0;
+
+
+      if (state[5].set) /* keyfile-offset */
+	{
+	  keyfile_offset = grub_strtoul (state[5].arg, &p, 0);
+
+	  if (grub_errno != GRUB_ERR_NONE)
+	    return grub_errno;
+
+	  if (*p != '\0')
+	    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+			       N_("unrecognized number"));
+	}
+      else
+	{
+	  keyfile_offset = 0;
+	}
+
+      if (state[6].set) /* keyfile-size */
+	{
+	  requested_keyfile_size = grub_strtoul (state[6].arg, &p, 0);
+
+	  if (*p != '\0')
+	    return grub_error (GRUB_ERR_BAD_ARGUMENT,
+			       N_("unrecognized number"));
+
+	  if (grub_errno != GRUB_ERR_NONE)
+	    return grub_errno;
+
+	  if (requested_keyfile_size > GRUB_CRYPTODISK_MAX_KEYFILE_SIZE)
+	    return grub_error (GRUB_ERR_OUT_OF_RANGE,
+			      N_("Key file size exceeds maximum (%"
+				 PRIuGRUB_SIZE ")\n"),
+			      GRUB_CRYPTODISK_MAX_KEYFILE_SIZE);
+
+	  if (requested_keyfile_size == 0)
+	    return grub_error (GRUB_ERR_OUT_OF_RANGE,
+			      N_("Key file size is 0\n"));
+	}
+
+      keyfile = grub_file_open (state[4].arg,
+				GRUB_FILE_TYPE_CRYPTODISK_ENCRYPTION_KEY);
+      if (!keyfile)
+	return grub_errno;
+
+      if (grub_file_seek (keyfile, keyfile_offset) == (grub_off_t)-1)
+	return grub_errno;
+
+      if (requested_keyfile_size)
+	{
+	  if (requested_keyfile_size > (keyfile->size - keyfile_offset))
+	    return grub_error (GRUB_ERR_FILE_READ_ERROR,
+			       N_("Keyfile is too small: "
+				  "requested %" PRIuGRUB_SIZE " bytes, "
+				  "but the file only has %" PRIuGRUB_SIZE
+				  " bytes.\n"),
+			       requested_keyfile_size,
+			       keyfile->size);
+
+	  key_size = requested_keyfile_size;
+	}
+      else
+	{
+	  key_size = keyfile->size - keyfile_offset;
+	}
+
+      if (grub_file_read (keyfile, keyfile_buffer, key_size) != key_size)
+	return grub_error (GRUB_ERR_FILE_READ_ERROR,
+			   (N_("Error reading key file\n")));
+      key = keyfile_buffer;
+    }
+
   if (state[0].set)
     {
       grub_cryptodisk_t dev;
diff --git a/grub-core/disk/geli.c b/grub-core/disk/geli.c
index acd09d874..159ac0f96 100644
--- a/grub-core/disk/geli.c
+++ b/grub-core/disk/geli.c
@@ -404,7 +404,8 @@ geli_scan (grub_disk_t disk, const char *check_uuid, int boot_only,
 }
 
 static grub_err_t
-geli_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_file_t hdr)
+geli_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_file_t hdr,
+		  grub_uint8_t *key, grub_size_t keyfile_size)
 {
   grub_size_t keysize;
   grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN];
@@ -420,8 +421,8 @@ geli_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_file_t hdr)
   grub_disk_addr_t sector;
   grub_err_t err;
 
-  /* Detached headers are not implemented yet */
-  if (hdr)
+  /* Detached headers and keyfiles are not implemented yet */
+  if (hdr || key || keyfile_size)
     return GRUB_ERR_NOT_IMPLEMENTED_YET;
 
   if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c
index 6286302e7..0dd33b2af 100644
--- a/grub-core/disk/luks.c
+++ b/grub-core/disk/luks.c
@@ -161,7 +161,8 @@ luks_scan (grub_disk_t disk, const char *check_uuid, int check_boot,
 }
 
 static grub_err_t
-luks_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_file_t hdr)
+luks_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_file_t hdr,
+		  grub_uint8_t *keyfile_bytes, grub_size_t keyfile_bytes_size)
 {
   struct grub_luks_phdr header;
   grub_size_t keysize;
@@ -175,6 +176,10 @@ luks_recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_file_t hdr)
   char *tmp;
   grub_uint32_t sector;
 
+  /* Keyfiles are not implemented yet */
+  if (keyfile_bytes || keyfile_bytes_size)
+     return GRUB_ERR_NOT_IMPLEMENTED_YET;
+
   if (hdr)
     {
       if (grub_file_seek (hdr, 0) == (grub_off_t) -1)
diff --git a/grub-core/disk/luks2.c b/grub-core/disk/luks2.c
index bc00e8bbc..6a38a1f4d 100644
--- a/grub-core/disk/luks2.c
+++ b/grub-core/disk/luks2.c
@@ -529,7 +529,8 @@ luks2_decrypt_key (grub_uint8_t *out_key,
 
 static grub_err_t
 luks2_recover_key (grub_disk_t disk, grub_cryptodisk_t crypt,
-		   grub_file_t hdr_file)
+		   grub_file_t hdr_file, grub_uint8_t *key,
+		   grub_size_t keyfile_size)
 {
   grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
   char passphrase[MAX_PASSPHRASE], cipher[32];
@@ -543,8 +544,8 @@ luks2_recover_key (grub_disk_t disk, grub_cryptodisk_t crypt,
   grub_json_t *json = NULL, keyslots;
   grub_err_t ret;
 
-  /* Detached headers are not implemented yet */
-  if (hdr_file)
+  /* Detached headers and keyfiles are not implemented yet */
+  if (hdr_file || key || keyfile_size)
     return GRUB_ERR_NOT_IMPLEMENTED_YET;
 
   ret = luks2_read_header (disk, &header);
diff --git a/include/grub/cryptodisk.h b/include/grub/cryptodisk.h
index e24b1b8cb..6d2610f93 100644
--- a/include/grub/cryptodisk.h
+++ b/include/grub/cryptodisk.h
@@ -55,6 +55,8 @@ typedef enum
 #define GRUB_CRYPTODISK_GF_BYTES (1U << GRUB_CRYPTODISK_GF_LOG_BYTES)
 #define GRUB_CRYPTODISK_MAX_KEYLEN 128
 
+#define GRUB_CRYPTODISK_MAX_KEYFILE_SIZE 8192
+
 struct grub_cryptodisk;
 
 typedef gcry_err_code_t
@@ -110,7 +112,8 @@ struct grub_cryptodisk_dev
   grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid,
 			     int boot_only, grub_file_t hdr);
   grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev,
-			     grub_file_t hdr);
+			     grub_file_t hdr, grub_uint8_t *key,
+			     grub_size_t keyfile_size);
 };
 typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;
 
diff --git a/include/grub/file.h b/include/grub/file.h
index a7d7be853..97678aa45 100644
--- a/include/grub/file.h
+++ b/include/grub/file.h
@@ -92,6 +92,8 @@ enum grub_file_type
     GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY,
     /* File holiding the encryption metadata header */
     GRUB_FILE_TYPE_CRYPTODISK_DETACHED_HEADER,
+    /* File holiding the encryption key */
+    GRUB_FILE_TYPE_CRYPTODISK_ENCRYPTION_KEY,
     /* File we open n grub-fstest.  */
     GRUB_FILE_TYPE_FSTEST,
     /* File we open n grub-mount.  */
-- 
2.28.0