2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2011 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/>.
20 #include <grub/file.h>
22 #include <grub/misc.h>
23 #include <grub/disk.h>
24 #include <grub/partition.h>
26 #include <grub/types.h>
27 #include <grub/zfs/zfs.h>
28 #include <grub/zfs/zio.h>
29 #include <grub/zfs/dnode.h>
30 #include <grub/zfs/uberblock_impl.h>
31 #include <grub/zfs/vdev_impl.h>
32 #include <grub/zfs/zio_checksum.h>
33 #include <grub/zfs/zap_impl.h>
34 #include <grub/zfs/zap_leaf.h>
35 #include <grub/zfs/zfs_znode.h>
36 #include <grub/zfs/dmu.h>
37 #include <grub/zfs/dmu_objset.h>
38 #include <grub/zfs/sa_impl.h>
39 #include <grub/zfs/dsl_dir.h>
40 #include <grub/zfs/dsl_dataset.h>
41 #include <grub/crypto.h>
42 #include <grub/extcmd.h>
43 #include <grub/i18n.h>
45 GRUB_MOD_LICENSE ("GPLv3+");
48 Mostly based on following article:
49 https://blogs.oracle.com/darren/entry/zfs_encryption_what_is_on
61 grub_uint8_t enc_nonce
[13];
62 grub_uint8_t unused
[3];
63 grub_uint8_t enc_key
[48];
64 grub_uint8_t unknown_purpose_nonce
[13];
65 grub_uint8_t unused2
[3];
66 grub_uint8_t unknown_purpose_key
[48];
69 struct grub_zfs_wrap_key
71 struct grub_zfs_wrap_key
*next
;
77 static struct grub_zfs_wrap_key
*zfs_wrap_keys
;
80 grub_zfs_add_key (grub_uint8_t
*key_in
,
84 struct grub_zfs_wrap_key
*key
;
85 if (!passphrase
&& keylen
> 32)
87 key
= grub_malloc (sizeof (*key
) + keylen
);
90 key
->is_passphrase
= passphrase
;
92 grub_memcpy (key
->key
, key_in
, keylen
);
93 key
->next
= zfs_wrap_keys
;
98 static gcry_err_code_t
99 grub_ccm_decrypt (grub_crypto_cipher_handle_t cipher
,
100 grub_uint8_t
*out
, const grub_uint8_t
*in
,
102 void *mac_out
, const void *nonce
,
103 unsigned l
, unsigned m
)
106 grub_uint8_t mul
[16];
107 grub_uint32_t mac
[4];
111 grub_memcpy (iv
+ 1, nonce
, 15 - l
);
113 iv
[0] = (l
- 1) | (((m
-2) / 2) << 3);
114 for (j
= 0; j
< l
; j
++)
115 iv
[15 - j
] = psize
>> (8 * j
);
116 err
= grub_crypto_ecb_encrypt (cipher
, mac
, iv
, 16);
122 for (i
= 0; i
< (psize
+ 15) / 16; i
++)
126 if (csize
> psize
- 16 * i
)
127 csize
= psize
- 16 * i
;
128 for (j
= 0; j
< l
; j
++)
129 iv
[15 - j
] = (i
+ 1) >> (8 * j
);
130 err
= grub_crypto_ecb_encrypt (cipher
, mul
, iv
, 16);
133 grub_crypto_xor (out
+ 16 * i
, in
+ 16 * i
, mul
, csize
);
134 grub_crypto_xor (mac
, mac
, out
+ 16 * i
, csize
);
135 err
= grub_crypto_ecb_encrypt (cipher
, mac
, mac
, 16);
139 for (j
= 0; j
< l
; j
++)
141 err
= grub_crypto_ecb_encrypt (cipher
, mul
, iv
, 16);
145 grub_crypto_xor (mac_out
, mac
, mul
, m
);
146 return GRUB_ERR_NONE
;
150 grub_gcm_mul_x (grub_uint8_t
*a
)
154 for (i
= 0; i
< 16; i
++)
157 a
[i
] = (a
[i
] >> 1) | (d
<< 7);
165 grub_gcm_mul (grub_uint8_t
*a
, const grub_uint8_t
*b
)
167 grub_uint8_t res
[16], bs
[16];
169 grub_memcpy (bs
, b
, 16);
170 grub_memset (res
, 0, 16);
171 for (i
= 0; i
< 128; i
++)
173 if ((a
[i
/ 8] << (i
% 8)) & 0x80)
174 grub_crypto_xor (res
, res
, bs
, 16);
178 grub_memcpy (a
, res
, 16);
181 static gcry_err_code_t
182 grub_gcm_decrypt (grub_crypto_cipher_handle_t cipher
,
183 grub_uint8_t
*out
, const grub_uint8_t
*in
,
185 void *mac_out
, const void *nonce
,
186 unsigned nonce_len
, unsigned m
)
189 grub_uint8_t mul
[16];
190 grub_uint8_t mac
[16], h
[16], mac_xor
[16];
194 grub_memset (mac
, 0, sizeof (mac
));
196 err
= grub_crypto_ecb_encrypt (cipher
, h
, mac
, 16);
202 grub_memcpy (iv
, nonce
, 12);
210 grub_memset (iv
, 0, sizeof (iv
));
211 grub_memcpy (iv
, nonce
, nonce_len
);
212 grub_gcm_mul (iv
, h
);
213 iv
[15] ^= nonce_len
* 8;
214 grub_gcm_mul (iv
, h
);
217 err
= grub_crypto_ecb_encrypt (cipher
, mac_xor
, iv
, 16);
221 for (i
= 0; i
< (psize
+ 15) / 16; i
++)
225 if (csize
> psize
- 16 * i
)
226 csize
= psize
- 16 * i
;
227 for (j
= 0; j
< 4; j
++)
233 grub_crypto_xor (mac
, mac
, in
+ 16 * i
, csize
);
234 grub_gcm_mul (mac
, h
);
235 err
= grub_crypto_ecb_encrypt (cipher
, mul
, iv
, 16);
238 grub_crypto_xor (out
+ 16 * i
, in
+ 16 * i
, mul
, csize
);
240 for (j
= 0; j
< 8; j
++)
241 mac
[15 - j
] ^= ((psize
* 8) >> (8 * j
));
242 grub_gcm_mul (mac
, h
);
245 grub_crypto_xor (mac_out
, mac
, mac_xor
, m
);
247 return GRUB_ERR_NONE
;
251 static gcry_err_code_t
252 algo_decrypt (grub_crypto_cipher_handle_t cipher
, grub_uint64_t algo
,
253 grub_uint8_t
*out
, const grub_uint8_t
*in
,
255 void *mac_out
, const void *nonce
,
256 unsigned l
, unsigned m
)
261 return grub_ccm_decrypt (cipher
, out
, in
, psize
, mac_out
, nonce
, l
, m
);
263 return grub_gcm_decrypt (cipher
, out
, in
, psize
, mac_out
, nonce
,
266 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
, "algorithm %"
267 PRIuGRUB_UINT64_T
" is not supported yet", algo
);
272 grub_zfs_decrypt_real (grub_crypto_cipher_handle_t cipher
,
275 char *buf
, grub_size_t size
,
276 const grub_uint32_t
*expected_mac
,
277 grub_zfs_endian_t endian
)
279 grub_uint32_t mac
[4];
284 grub_memcpy (sw
, nonce
, 16);
285 if (endian
!= GRUB_ZFS_BIG_ENDIAN
)
286 for (i
= 0; i
< 4; i
++)
287 sw
[i
] = grub_swap_bytes32 (sw
[i
]);
290 return grub_error (GRUB_ERR_ACCESS_DENIED
,
291 N_("no decryption key available"));
292 err
= algo_decrypt (cipher
, algo
,
293 (grub_uint8_t
*) buf
,
294 (grub_uint8_t
*) buf
,
300 for (i
= 0; i
< 3; i
++)
301 if (grub_zfs_to_cpu32 (expected_mac
[i
], endian
)
302 != grub_be_to_cpu32 (mac
[i
]))
303 return grub_error (GRUB_ERR_BAD_FS
, N_("MAC verification failed"));
304 return GRUB_ERR_NONE
;
307 static grub_crypto_cipher_handle_t
308 grub_zfs_load_key_real (const struct grub_zfs_key
*key
,
314 struct grub_zfs_wrap_key
*wrap_key
;
315 grub_crypto_cipher_handle_t ret
= NULL
;
317 if (keysize
!= sizeof (*key
))
319 grub_dprintf ("zfs", "Unexpected key size %" PRIuGRUB_SIZE
"\n", keysize
);
323 if (grub_memcmp (key
->enc_key
+ 32, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16)
326 else if (grub_memcmp (key
->enc_key
+ 40, "\0\0\0\0\0\0\0\0", 8) == 0)
331 for (wrap_key
= zfs_wrap_keys
; wrap_key
; wrap_key
= wrap_key
->next
)
333 grub_crypto_cipher_handle_t cipher
;
334 grub_uint8_t decrypted
[32], mac
[32], wrap_key_real
[32];
336 cipher
= grub_crypto_cipher_open (GRUB_CIPHER_AES
);
339 grub_errno
= GRUB_ERR_NONE
;
342 grub_memset (wrap_key_real
, 0, sizeof (wrap_key_real
));
344 if (!wrap_key
->is_passphrase
)
345 grub_memcpy(wrap_key_real
, wrap_key
->key
,
346 wrap_key
->keylen
< keylen
? wrap_key
->keylen
: keylen
);
348 err
= grub_crypto_pbkdf2 (GRUB_MD_SHA1
,
349 (const grub_uint8_t
*) wrap_key
->key
,
351 (const grub_uint8_t
*) &salt
, sizeof (salt
),
352 1000, wrap_key_real
, keylen
);
355 grub_errno
= GRUB_ERR_NONE
;
359 err
= grub_crypto_cipher_set_key (cipher
, wrap_key_real
,
363 grub_errno
= GRUB_ERR_NONE
;
367 err
= algo_decrypt (cipher
, algo
, decrypted
, key
->unknown_purpose_key
, 32,
368 mac
, key
->unknown_purpose_nonce
, 2, 16);
369 if (err
|| (grub_crypto_memcmp (mac
, key
->unknown_purpose_key
+ 32, 16)
372 grub_dprintf ("zfs", "key loading failed\n");
373 grub_errno
= GRUB_ERR_NONE
;
377 err
= algo_decrypt (cipher
, algo
, decrypted
, key
->enc_key
, keylen
, mac
,
378 key
->enc_nonce
, 2, 16);
379 if (err
|| grub_crypto_memcmp (mac
, key
->enc_key
+ keylen
, 16) != 0)
381 grub_dprintf ("zfs", "key loading failed\n");
382 grub_errno
= GRUB_ERR_NONE
;
385 ret
= grub_crypto_cipher_open (GRUB_CIPHER_AES
);
388 grub_errno
= GRUB_ERR_NONE
;
391 err
= grub_crypto_cipher_set_key (ret
, decrypted
, keylen
);
394 grub_errno
= GRUB_ERR_NONE
;
395 grub_crypto_cipher_close (ret
);
403 static const struct grub_arg_option options
[] =
405 {"raw", 'r', 0, N_("Assume input is raw."), 0, 0},
406 {"hex", 'h', 0, N_("Assume input is hex."), 0, 0},
407 {"passphrase", 'p', 0, N_("Assume input is passphrase."), 0, 0},
412 grub_cmd_zfs_key (grub_extcmd_context_t ctxt
, int argc
, char **args
)
414 grub_uint8_t buf
[1024];
415 grub_ssize_t real_size
;
420 file
= grub_file_open (args
[0]);
423 real_size
= grub_file_read (file
, buf
, 1024);
429 grub_xputs (_("Enter ZFS password: "));
430 if (!grub_password_get ((char *) buf
, 1023))
432 real_size
= grub_strlen ((char *) buf
);
435 if (ctxt
->state
[1].set
)
439 for (i
= 0; i
< real_size
/ 2; i
++)
441 char c1
= grub_tolower (buf
[2 * i
]) - '0';
442 char c2
= grub_tolower (buf
[2 * i
+ 1]) - '0';
444 c1
+= '0' - 'a' + 10;
446 c2
+= '0' - 'a' + 10;
447 buf
[i
] = (c1
<< 4) | c2
;
449 err
= grub_zfs_add_key (buf
, real_size
/ 2, 0);
452 return GRUB_ERR_NONE
;
455 return grub_zfs_add_key (buf
, real_size
,
457 || (argc
== 0 && !ctxt
->state
[0].set
458 && !ctxt
->state
[1].set
));
461 static grub_extcmd_t cmd_key
;
463 GRUB_MOD_INIT(zfscrypt
)
465 grub_zfs_decrypt
= grub_zfs_decrypt_real
;
466 grub_zfs_load_key
= grub_zfs_load_key_real
;
467 cmd_key
= grub_register_extcmd ("zfskey", grub_cmd_zfs_key
, 0,
468 N_("[-h|-p|-r] [FILE]"),
469 N_("Import ZFS wrapping key stored in FILE."),
473 GRUB_MOD_FINI(zfscrypt
)
475 grub_zfs_decrypt
= 0;
476 grub_zfs_load_key
= 0;
477 grub_unregister_extcmd (cmd_key
);