/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 1999,2000,2001,2002,2003,2004,2009,2010 Free Software Foundation, Inc.
+ * Copyright (C) 1999,2000,2001,2002,2003,2004,2009,2010,2011 Free Software Foundation, Inc.
* Copyright 2010 Sun Microsystems, Inc.
*
* GRUB is free software; you can redistribute it and/or modify
grub_uint8_t unknown_purpose_key[48];
};
+struct grub_zfs_wrap_key
+{
+ struct grub_zfs_wrap_key *next;
+ grub_uint64_t key[GRUB_ZFS_MAX_KEYLEN / 8];
+};
+
extern grub_err_t lzjb_decompress (void *, void *, grub_size_t, grub_size_t);
typedef grub_err_t zfs_decomp_func_t (void *s_start, void *d_start,
grub_uint64_t guid;
};
+static struct grub_zfs_wrap_key *zfs_wrap_keys;
+
+grub_err_t
+grub_zfs_add_key (grub_uint8_t *key_in)
+{
+ struct grub_zfs_wrap_key *key;
+ key = grub_malloc (sizeof (*key));
+ if (!key)
+ return grub_errno;
+ grub_memcpy (key->key, key_in, GRUB_ZFS_MAX_KEYLEN);
+ key->next = zfs_wrap_keys;
+ zfs_wrap_keys = key;
+ return GRUB_ERR_NONE;
+}
+
static grub_err_t
zlib_decompress (void *s, void *d,
grub_size_t slen, grub_size_t dlen)
grub_size_t elemsize)
{
const struct grub_zfs_key *key = val_in;
- grub_crypto_cipher_handle_t cipher;
- grub_uint8_t wrapping_key[32], decrypted[32], mac[32];
unsigned keylen;
+ struct grub_zfs_wrap_key *wrap_key;
if (elemsize != 1 || nelem != sizeof (*key))
{
else
keylen = 32;
- grub_memset (wrapping_key, 0, sizeof (wrapping_key));
-
- cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES);
- if (!cipher)
+ for (wrap_key = zfs_wrap_keys; wrap_key; wrap_key = wrap_key->next)
{
- grub_errno = GRUB_ERR_NONE;
- return 0;
- }
- err = grub_crypto_cipher_set_key (cipher, wrapping_key, keylen);
- if (err)
- {
- grub_errno = GRUB_ERR_NONE;
- return 0;
- }
+ grub_crypto_cipher_handle_t cipher;
+ grub_uint8_t decrypted[32], mac[32];
+ cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES);
+ if (!cipher)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ return 0;
+ }
+ err = grub_crypto_cipher_set_key (cipher,
+ (const grub_uint8_t *) wrap_key->key,
+ keylen);
+ if (err)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
- err = grub_ccm_decrypt (cipher, decrypted, key->unknown_purpose_key, 32,
- mac, key->unknown_purpose_nonce, 2, 16);
- if (err || grub_crypto_memcmp (mac, key->unknown_purpose_key + 32, 16) != 0)
- {
- grub_dprintf ("zfs", "key loading failed\n");
- grub_errno = GRUB_ERR_NONE;
- return 0;
- }
+ err = grub_ccm_decrypt (cipher, decrypted, key->unknown_purpose_key, 32,
+ mac, key->unknown_purpose_nonce, 2, 16);
+ if (err || (grub_crypto_memcmp (mac, key->unknown_purpose_key + 32, 16)
+ != 0))
+ {
+ grub_dprintf ("zfs", "key loading failed\n");
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
- err = grub_ccm_decrypt (cipher, decrypted, key->enc_key, keylen, mac,
- key->enc_nonce, 2, 16);
- if (err || grub_crypto_memcmp (mac, key->enc_key + keylen, 16) != 0)
- {
- grub_dprintf ("zfs", "key loading failed\n");
- grub_errno = GRUB_ERR_NONE;
- return 0;
- }
- subvol->cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES);
- if (!subvol->cipher)
- {
- grub_errno = GRUB_ERR_NONE;
- return 0;
- }
- err = grub_crypto_cipher_set_key (subvol->cipher, decrypted, keylen);
- if (err)
- {
- grub_errno = GRUB_ERR_NONE;
+ err = grub_ccm_decrypt (cipher, decrypted, key->enc_key, keylen, mac,
+ key->enc_nonce, 2, 16);
+ if (err || grub_crypto_memcmp (mac, key->enc_key + keylen, 16) != 0)
+ {
+ grub_dprintf ("zfs", "key loading failed\n");
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+ subvol->cipher = grub_crypto_cipher_open (GRUB_CIPHER_AES);
+ if (!subvol->cipher)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+ err = grub_crypto_cipher_set_key (subvol->cipher, decrypted, keylen);
+ if (err)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
return 0;
}
-
return 0;
}
#include <grub/device.h>
#include <grub/file.h>
#include <grub/command.h>
+#include <grub/extcmd.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/dl.h>
#include <grub/env.h>
+#include <grub/i18n.h>
GRUB_MOD_LICENSE ("GPLv3+");
return GRUB_ERR_NONE;
}
+static const struct grub_arg_option options[] =
+ {
+ {"raw", 'r', 0, N_("Assume input is raw."), 0, 0},
+ {"hex", 'h', 0, N_("Assume input is hex."), 0, 0},
+ {"passphrase", 'p', 0, N_("Assume input is passphrase."), 0, 0},
+ {0, 0, 0, 0, 0, 0}
+ };
+
+static grub_err_t
+grub_cmd_zfs_key (grub_extcmd_context_t ctxt, int argc, char **args)
+{
+ grub_uint8_t buf[1024];
+ grub_ssize_t real_size;
+
+ if (argc > 0)
+ {
+ grub_file_t file;
+ file = grub_file_open (args[0]);
+ if (!file)
+ return grub_errno;
+ real_size = grub_file_read (file, buf, 1024);
+ if (real_size < 0)
+ return grub_errno;
+ }
+ if (ctxt->state[0].set
+ || (argc > 0 && !ctxt->state[1].set && !ctxt->state[2].set))
+ {
+ grub_err_t err;
+ if (real_size < GRUB_ZFS_MAX_KEYLEN)
+ grub_memset (buf + real_size, 0, GRUB_ZFS_MAX_KEYLEN - real_size);
+ err = grub_zfs_add_key (buf);
+ if (err)
+ return err;
+ return GRUB_ERR_NONE;
+ }
+
+ if (ctxt->state[1].set)
+ {
+ int i;
+ grub_err_t err;
+ if (real_size < 2 * GRUB_ZFS_MAX_KEYLEN)
+ grub_memset (buf + real_size, '0', 2 * GRUB_ZFS_MAX_KEYLEN - real_size);
+ for (i = 0; i < GRUB_ZFS_MAX_KEYLEN; i++)
+ {
+ char c1 = grub_tolower (buf[2 * i]) - '0';
+ char c2 = grub_tolower (buf[2 * i + 1]) - '0';
+ if (c1 > 9)
+ c1 += '0' - 'a' + 10;
+ if (c2 > 9)
+ c2 += '0' - 'a' + 10;
+ buf[i] = (c1 << 4) | c2;
+ }
+ err = grub_zfs_add_key (buf);
+ if (err)
+ return err;
+ return GRUB_ERR_NONE;
+ }
+ return GRUB_ERR_NONE;
+}
static grub_command_t cmd_info, cmd_bootfs;
+static grub_extcmd_t cmd_key;
GRUB_MOD_INIT (zfsinfo)
{
cmd_info = grub_register_command ("zfsinfo", grub_cmd_zfsinfo,
"zfsinfo DEVICE",
"Print ZFS info about DEVICE.");
+ cmd_key = grub_register_extcmd ("zfskey", grub_cmd_zfs_key, 0,
+ "zfskey [-h|-p|-r] [FILE]",
+ "Import ZFS wrapping key stored in FILE.",
+ options);
cmd_bootfs = grub_register_command ("zfs-bootfs", grub_cmd_zfs_bootfs,
"zfs-bootfs FILESYSTEM [VARIABLE]",
"Print ZFS-BOOTFSOBJ or set it to VARIABLE");
{
grub_unregister_command (cmd_info);
grub_unregister_command (cmd_bootfs);
+ grub_unregister_extcmd (cmd_key);
}
#include <grub/crypto.h>
#include <grub/command.h>
#include <grub/i18n.h>
+#include <grub/zfs/zfs.h>
#include <stdio.h>
#include <unistd.h>
{"diskcount", 'c', "N", 0, N_("N input files."), 2},
{"debug", 'd', "S", 0, N_("Set debug environment variable."), 2},
{"crypto", 'C', NULL, OPTION_ARG_OPTIONAL, N_("Mount crypto devices."), 2},
+ {"zfs-key-file", 'K', N_("KEY_FILENAME"), 0, N_("Load zfs crypto key."), 2},
{"verbose", 'v', NULL, OPTION_ARG_OPTIONAL, N_("Print verbose messages."), 2},
{"uncompress", 'u', NULL, OPTION_ARG_OPTIONAL, N_("Uncompress data."), 2},
{0, 0, 0, 0, 0, 0}
root = arg;
return 0;
+ case 'K':
+ {
+ FILE *f;
+ ssize_t real_size;
+ grub_uint8_t buf[GRUB_ZFS_MAX_KEYLEN];
+ f = fopen (arg, "rb");
+ if (!f)
+ {
+ printf ("Error loading file %s: %s\n", arg, strerror (errno));
+ return 0;
+ }
+ real_size = fread (buf, 1, GRUB_ZFS_MAX_KEYLEN, f);
+ if (real_size < 0)
+ {
+ printf ("Error loading file %s: %s\n", arg, strerror (errno));
+ fclose (f);
+ return 0;
+ }
+ if (real_size < GRUB_ZFS_MAX_KEYLEN)
+ grub_memset (buf + real_size, 0, GRUB_ZFS_MAX_KEYLEN - real_size);
+ grub_zfs_add_key (buf);
+ }
+ return 0;
+
case 'C':
mount_crypt = 1;
return 0;