]> git.proxmox.com Git - grub2.git/blame - grub-core/fs/zfs/zfscrypt.c
malloc: Use overflow checking primitives where we do complex allocations
[grub2.git] / grub-core / fs / zfs / zfscrypt.c
CommitLineData
f003a8c5
VS
1/*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 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
19#include <grub/err.h>
20#include <grub/file.h>
21#include <grub/mm.h>
22#include <grub/misc.h>
23#include <grub/disk.h>
24#include <grub/partition.h>
3f05d693 25#include <grub/safemath.h>
f003a8c5
VS
26#include <grub/dl.h>
27#include <grub/types.h>
28#include <grub/zfs/zfs.h>
29#include <grub/zfs/zio.h>
30#include <grub/zfs/dnode.h>
31#include <grub/zfs/uberblock_impl.h>
32#include <grub/zfs/vdev_impl.h>
33#include <grub/zfs/zio_checksum.h>
34#include <grub/zfs/zap_impl.h>
35#include <grub/zfs/zap_leaf.h>
36#include <grub/zfs/zfs_znode.h>
37#include <grub/zfs/dmu.h>
38#include <grub/zfs/dmu_objset.h>
39#include <grub/zfs/sa_impl.h>
40#include <grub/zfs/dsl_dir.h>
41#include <grub/zfs/dsl_dataset.h>
42#include <grub/crypto.h>
43#include <grub/extcmd.h>
44#include <grub/i18n.h>
45
46GRUB_MOD_LICENSE ("GPLv3+");
47
2f53a9ed
VS
48/*
49 Mostly based on following article:
50 https://blogs.oracle.com/darren/entry/zfs_encryption_what_is_on
51 */
52
f003a8c5
VS
53enum grub_zfs_algo
54 {
55 GRUB_ZFS_ALGO_CCM,
56 GRUB_ZFS_ALGO_GCM,
57 };
58
59struct grub_zfs_key
60{
61 grub_uint64_t algo;
62 grub_uint8_t enc_nonce[13];
63 grub_uint8_t unused[3];
64 grub_uint8_t enc_key[48];
65 grub_uint8_t unknown_purpose_nonce[13];
66 grub_uint8_t unused2[3];
67 grub_uint8_t unknown_purpose_key[48];
68};
69
70struct grub_zfs_wrap_key
71{
72 struct grub_zfs_wrap_key *next;
ed746949
VS
73 grub_size_t keylen;
74 int is_passphrase;
75 grub_uint64_t key[0];
f003a8c5
VS
76};
77
78static struct grub_zfs_wrap_key *zfs_wrap_keys;
79
80grub_err_t
ed746949
VS
81grub_zfs_add_key (grub_uint8_t *key_in,
82 grub_size_t keylen,
83 int passphrase)
f003a8c5
VS
84{
85 struct grub_zfs_wrap_key *key;
3f05d693
PJ
86 grub_size_t sz;
87
ed746949
VS
88 if (!passphrase && keylen > 32)
89 keylen = 32;
3f05d693
PJ
90 if (grub_add (sizeof (*key), keylen, &sz))
91 return GRUB_ERR_OUT_OF_RANGE;
92 key = grub_malloc (sz);
f003a8c5
VS
93 if (!key)
94 return grub_errno;
ed746949
VS
95 key->is_passphrase = passphrase;
96 key->keylen = keylen;
97 grub_memcpy (key->key, key_in, keylen);
f003a8c5
VS
98 key->next = zfs_wrap_keys;
99 zfs_wrap_keys = key;
100 return GRUB_ERR_NONE;
101}
102
4a19b601 103static gcry_err_code_t
f003a8c5
VS
104grub_ccm_decrypt (grub_crypto_cipher_handle_t cipher,
105 grub_uint8_t *out, const grub_uint8_t *in,
106 grub_size_t psize,
107 void *mac_out, const void *nonce,
108 unsigned l, unsigned m)
109{
110 grub_uint8_t iv[16];
111 grub_uint8_t mul[16];
112 grub_uint32_t mac[4];
113 unsigned i, j;
4a19b601 114 gcry_err_code_t err;
f003a8c5
VS
115
116 grub_memcpy (iv + 1, nonce, 15 - l);
117
118 iv[0] = (l - 1) | (((m-2) / 2) << 3);
119 for (j = 0; j < l; j++)
120 iv[15 - j] = psize >> (8 * j);
121 err = grub_crypto_ecb_encrypt (cipher, mac, iv, 16);
122 if (err)
123 return err;
124
125 iv[0] = l - 1;
126
127 for (i = 0; i < (psize + 15) / 16; i++)
128 {
129 grub_size_t csize;
130 csize = 16;
131 if (csize > psize - 16 * i)
132 csize = psize - 16 * i;
133 for (j = 0; j < l; j++)
134 iv[15 - j] = (i + 1) >> (8 * j);
135 err = grub_crypto_ecb_encrypt (cipher, mul, iv, 16);
136 if (err)
137 return err;
138 grub_crypto_xor (out + 16 * i, in + 16 * i, mul, csize);
139 grub_crypto_xor (mac, mac, out + 16 * i, csize);
140 err = grub_crypto_ecb_encrypt (cipher, mac, mac, 16);
141 if (err)
142 return err;
143 }
144 for (j = 0; j < l; j++)
145 iv[15 - j] = 0;
146 err = grub_crypto_ecb_encrypt (cipher, mul, iv, 16);
147 if (err)
148 return err;
149 if (mac_out)
150 grub_crypto_xor (mac_out, mac, mul, m);
8b66bb5d 151 return GPG_ERR_NO_ERROR;
f003a8c5
VS
152}
153
bc1de0bc
VS
154static void
155grub_gcm_mul_x (grub_uint8_t *a)
156{
157 int i;
158 int c = 0, d = 0;
159 for (i = 0; i < 16; i++)
160 {
161 c = a[i] & 0x1;
162 a[i] = (a[i] >> 1) | (d << 7);
163 d = c;
164 }
165 if (d)
166 a[0] ^= 0xe1;
167}
168
169static void
170grub_gcm_mul (grub_uint8_t *a, const grub_uint8_t *b)
171{
172 grub_uint8_t res[16], bs[16];
173 int i;
174 grub_memcpy (bs, b, 16);
175 grub_memset (res, 0, 16);
176 for (i = 0; i < 128; i++)
177 {
178 if ((a[i / 8] << (i % 8)) & 0x80)
179 grub_crypto_xor (res, res, bs, 16);
180 grub_gcm_mul_x (bs);
181 }
182
183 grub_memcpy (a, res, 16);
184}
185
4a19b601 186static gcry_err_code_t
bc1de0bc
VS
187grub_gcm_decrypt (grub_crypto_cipher_handle_t cipher,
188 grub_uint8_t *out, const grub_uint8_t *in,
189 grub_size_t psize,
190 void *mac_out, const void *nonce,
191 unsigned nonce_len, unsigned m)
192{
193 grub_uint8_t iv[16];
194 grub_uint8_t mul[16];
195 grub_uint8_t mac[16], h[16], mac_xor[16];
196 unsigned i, j;
4a19b601 197 gcry_err_code_t err;
bc1de0bc
VS
198
199 grub_memset (mac, 0, sizeof (mac));
200
201 err = grub_crypto_ecb_encrypt (cipher, h, mac, 16);
202 if (err)
203 return err;
204
205 if (nonce_len == 12)
206 {
207 grub_memcpy (iv, nonce, 12);
208 iv[12] = 0;
209 iv[13] = 0;
210 iv[14] = 0;
211 iv[15] = 1;
212 }
213 else
214 {
215 grub_memset (iv, 0, sizeof (iv));
216 grub_memcpy (iv, nonce, nonce_len);
217 grub_gcm_mul (iv, h);
218 iv[15] ^= nonce_len * 8;
219 grub_gcm_mul (iv, h);
220 }
221
222 err = grub_crypto_ecb_encrypt (cipher, mac_xor, iv, 16);
223 if (err)
224 return err;
225
226 for (i = 0; i < (psize + 15) / 16; i++)
227 {
228 grub_size_t csize;
229 csize = 16;
230 if (csize > psize - 16 * i)
231 csize = psize - 16 * i;
232 for (j = 0; j < 4; j++)
233 {
234 iv[15 - j]++;
235 if (iv[15 - j] != 0)
236 break;
237 }
238 grub_crypto_xor (mac, mac, in + 16 * i, csize);
239 grub_gcm_mul (mac, h);
240 err = grub_crypto_ecb_encrypt (cipher, mul, iv, 16);
241 if (err)
242 return err;
243 grub_crypto_xor (out + 16 * i, in + 16 * i, mul, csize);
244 }
245 for (j = 0; j < 8; j++)
916733ea 246 mac[15 - j] ^= ((((grub_uint64_t) psize) * 8) >> (8 * j));
bc1de0bc
VS
247 grub_gcm_mul (mac, h);
248
249 if (mac_out)
250 grub_crypto_xor (mac_out, mac, mac_xor, m);
251
8b66bb5d 252 return GPG_ERR_NO_ERROR;
bc1de0bc
VS
253}
254
255
4a19b601 256static gcry_err_code_t
bc1de0bc
VS
257algo_decrypt (grub_crypto_cipher_handle_t cipher, grub_uint64_t algo,
258 grub_uint8_t *out, const grub_uint8_t *in,
259 grub_size_t psize,
260 void *mac_out, const void *nonce,
261 unsigned l, unsigned m)
262{
263 switch (algo)
264 {
265 case 0:
8b66bb5d
VS
266 return grub_ccm_decrypt (cipher, out, in, psize,
267 mac_out, nonce, l, m);
bc1de0bc 268 case 1:
8b66bb5d
VS
269 return grub_gcm_decrypt (cipher, out, in, psize,
270 mac_out, nonce,
bc1de0bc
VS
271 15 - l, m);
272 default:
8b66bb5d 273 return GPG_ERR_CIPHER_ALGO;
bc1de0bc
VS
274 }
275}
276
f003a8c5 277static grub_err_t
bc1de0bc
VS
278grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher,
279 grub_uint64_t algo,
280 void *nonce,
f003a8c5
VS
281 char *buf, grub_size_t size,
282 const grub_uint32_t *expected_mac,
283 grub_zfs_endian_t endian)
284{
285 grub_uint32_t mac[4];
286 unsigned i;
287 grub_uint32_t sw[4];
8b66bb5d 288 gcry_err_code_t err;
f003a8c5
VS
289
290 grub_memcpy (sw, nonce, 16);
3ae17eb8
VS
291 if (endian != GRUB_ZFS_BIG_ENDIAN)
292 for (i = 0; i < 4; i++)
293 sw[i] = grub_swap_bytes32 (sw[i]);
f003a8c5
VS
294
295 if (!cipher)
296 return grub_error (GRUB_ERR_ACCESS_DENIED,
d61386e2 297 N_("no decryption key available"));
bc1de0bc
VS
298 err = algo_decrypt (cipher, algo,
299 (grub_uint8_t *) buf,
300 (grub_uint8_t *) buf,
301 size, mac,
302 sw + 1, 3, 12);
f003a8c5 303 if (err)
8b66bb5d 304 return grub_crypto_gcry_error (err);
f003a8c5
VS
305
306 for (i = 0; i < 3; i++)
307 if (grub_zfs_to_cpu32 (expected_mac[i], endian)
308 != grub_be_to_cpu32 (mac[i]))
d61386e2 309 return grub_error (GRUB_ERR_BAD_FS, N_("MAC verification failed"));
f003a8c5
VS
310 return GRUB_ERR_NONE;
311}
312
313static grub_crypto_cipher_handle_t
314grub_zfs_load_key_real (const struct grub_zfs_key *key,
ed746949 315 grub_size_t keysize,
bc1de0bc
VS
316 grub_uint64_t salt,
317 grub_uint64_t algo)
f003a8c5
VS
318{
319 unsigned keylen;
320 struct grub_zfs_wrap_key *wrap_key;
321 grub_crypto_cipher_handle_t ret = NULL;
f003a8c5
VS
322
323 if (keysize != sizeof (*key))
324 {
325 grub_dprintf ("zfs", "Unexpected key size %" PRIuGRUB_SIZE "\n", keysize);
326 return 0;
327 }
328
329 if (grub_memcmp (key->enc_key + 32, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)
330 == 0)
331 keylen = 16;
332 else if (grub_memcmp (key->enc_key + 40, "\0\0\0\0\0\0\0\0", 8) == 0)
333 keylen = 24;
334 else
335 keylen = 32;
336
337 for (wrap_key = zfs_wrap_keys; wrap_key; wrap_key = wrap_key->next)
338 {
339 grub_crypto_cipher_handle_t cipher;
ed746949 340 grub_uint8_t decrypted[32], mac[32], wrap_key_real[32];
4a19b601 341 gcry_err_code_t err;
f003a8c5
VS
342 cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES);
343 if (!cipher)
344 {
345 grub_errno = GRUB_ERR_NONE;
346 return 0;
347 }
ed746949 348 grub_memset (wrap_key_real, 0, sizeof (wrap_key_real));
4a19b601 349 err = 0;
ed746949
VS
350 if (!wrap_key->is_passphrase)
351 grub_memcpy(wrap_key_real, wrap_key->key,
352 wrap_key->keylen < keylen ? wrap_key->keylen : keylen);
353 else
4a19b601
VS
354 err = grub_crypto_pbkdf2 (GRUB_MD_SHA1,
355 (const grub_uint8_t *) wrap_key->key,
356 wrap_key->keylen,
357 (const grub_uint8_t *) &salt, sizeof (salt),
358 1000, wrap_key_real, keylen);
359 if (err)
360 {
361 grub_errno = GRUB_ERR_NONE;
fa13e605 362 grub_crypto_cipher_close (cipher);
4a19b601
VS
363 continue;
364 }
ed746949
VS
365
366 err = grub_crypto_cipher_set_key (cipher, wrap_key_real,
f003a8c5
VS
367 keylen);
368 if (err)
369 {
370 grub_errno = GRUB_ERR_NONE;
fa13e605 371 grub_crypto_cipher_close (cipher);
f003a8c5
VS
372 continue;
373 }
374
bc1de0bc
VS
375 err = algo_decrypt (cipher, algo, decrypted, key->unknown_purpose_key, 32,
376 mac, key->unknown_purpose_nonce, 2, 16);
f003a8c5
VS
377 if (err || (grub_crypto_memcmp (mac, key->unknown_purpose_key + 32, 16)
378 != 0))
379 {
380 grub_dprintf ("zfs", "key loading failed\n");
381 grub_errno = GRUB_ERR_NONE;
fa13e605 382 grub_crypto_cipher_close (cipher);
f003a8c5
VS
383 continue;
384 }
385
bc1de0bc
VS
386 err = algo_decrypt (cipher, algo, decrypted, key->enc_key, keylen, mac,
387 key->enc_nonce, 2, 16);
f003a8c5
VS
388 if (err || grub_crypto_memcmp (mac, key->enc_key + keylen, 16) != 0)
389 {
390 grub_dprintf ("zfs", "key loading failed\n");
391 grub_errno = GRUB_ERR_NONE;
fa13e605 392 grub_crypto_cipher_close (cipher);
f003a8c5
VS
393 continue;
394 }
395 ret = grub_crypto_cipher_open (GRUB_CIPHER_AES);
396 if (!ret)
397 {
398 grub_errno = GRUB_ERR_NONE;
fa13e605 399 grub_crypto_cipher_close (cipher);
f003a8c5
VS
400 continue;
401 }
402 err = grub_crypto_cipher_set_key (ret, decrypted, keylen);
403 if (err)
404 {
3900726f
AB
405 grub_errno = GRUB_ERR_NONE;
406 grub_crypto_cipher_close (ret);
407 grub_crypto_cipher_close (cipher);
408 continue;
409 }
fa13e605 410 grub_crypto_cipher_close (cipher);
f003a8c5
VS
411 return ret;
412 }
413 return NULL;
414}
415
416static const struct grub_arg_option options[] =
417 {
418 {"raw", 'r', 0, N_("Assume input is raw."), 0, 0},
419 {"hex", 'h', 0, N_("Assume input is hex."), 0, 0},
420 {"passphrase", 'p', 0, N_("Assume input is passphrase."), 0, 0},
421 {0, 0, 0, 0, 0, 0}
422 };
423
424static grub_err_t
425grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args)
426{
427 grub_uint8_t buf[1024];
428 grub_ssize_t real_size;
429
430 if (argc > 0)
431 {
432 grub_file_t file;
ca0a4f68 433 file = grub_file_open (args[0], GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY);
f003a8c5
VS
434 if (!file)
435 return grub_errno;
436 real_size = grub_file_read (file, buf, 1024);
437 if (real_size < 0)
438 return grub_errno;
439 }
ed746949 440 else
f003a8c5 441 {
6e0632e2 442 grub_xputs (_("Enter ZFS password: "));
ed746949
VS
443 if (!grub_password_get ((char *) buf, 1023))
444 return grub_errno;
445 real_size = grub_strlen ((char *) buf);
f003a8c5
VS
446 }
447
448 if (ctxt->state[1].set)
449 {
450 int i;
451 grub_err_t err;
ed746949 452 for (i = 0; i < real_size / 2; i++)
f003a8c5
VS
453 {
454 char c1 = grub_tolower (buf[2 * i]) - '0';
455 char c2 = grub_tolower (buf[2 * i + 1]) - '0';
456 if (c1 > 9)
457 c1 += '0' - 'a' + 10;
458 if (c2 > 9)
459 c2 += '0' - 'a' + 10;
460 buf[i] = (c1 << 4) | c2;
461 }
ed746949 462 err = grub_zfs_add_key (buf, real_size / 2, 0);
f003a8c5
VS
463 if (err)
464 return err;
465 return GRUB_ERR_NONE;
466 }
ed746949
VS
467
468 return grub_zfs_add_key (buf, real_size,
469 ctxt->state[2].set
470 || (argc == 0 && !ctxt->state[0].set
471 && !ctxt->state[1].set));
f003a8c5
VS
472}
473
474static grub_extcmd_t cmd_key;
475
e2d22baf 476GRUB_MOD_INIT(zfscrypt)
f003a8c5
VS
477{
478 grub_zfs_decrypt = grub_zfs_decrypt_real;
479 grub_zfs_load_key = grub_zfs_load_key_real;
480 cmd_key = grub_register_extcmd ("zfskey", grub_cmd_zfs_key, 0,
6e0632e2
VS
481 N_("[-h|-p|-r] [FILE]"),
482 N_("Import ZFS wrapping key stored in FILE."),
f003a8c5
VS
483 options);
484}
485
e2d22baf 486GRUB_MOD_FINI(zfscrypt)
f003a8c5
VS
487{
488 grub_zfs_decrypt = 0;
489 grub_zfs_load_key = 0;
490 grub_unregister_extcmd (cmd_key);
491}