From a8271b1a4ba07cbf1af4406b67ea802f8584d6ed Mon Sep 17 00:00:00 2001 From: matt Date: Sat, 8 Apr 2017 08:26:26 -0400 Subject: [PATCH 4/7] Added grub-install/mkconfig magic for detached header LUKS --- grub-core/disk/luks.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++ util/grub-install.c | 84 +++++++++++++++++++++++++++++++++- 2 files changed, 207 insertions(+), 1 deletion(-) diff --git a/grub-core/disk/luks.c b/grub-core/disk/luks.c index 86c50c6..ab07ba9 100644 --- a/grub-core/disk/luks.c +++ b/grub-core/disk/luks.c @@ -91,6 +91,130 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid, /* Read the LUKS header. */ err = grub_disk_read (disk, 0, 0, sizeof (header), &header); + + +#ifdef GRUB_UTIL + + int have_crypto_device = 0; + if (disk->partition) + { + char *partuuid = 0; + char *crypto_device_name = 0; + crypto_device_name = grub_xasprintf ("%s,%s%d",disk->name, disk->partition->partmap->name,disk->partition->number + 1); + + /* Obtain the partition table from the root device. */ + grub_partition_t crypto_p = disk->partition; + if (crypto_p && (grub_strcmp (crypto_p->partmap->name, "msdos") == 0 || grub_strcmp (crypto_p->partmap->name, "gpt") == 0 )) + { + if (disk->partition->number + 1) + { + partuuid = grub_strdup (crypto_p->partuuid); + if (partuuid) + { + static FILE *fpcrypto_ptuuid_f; /*file pointer to be used as the local program name for crypto device ptuuid */ + static char *crypto_ptuuid_name; /*absolute path for crypto_ptuuid file*/ + crypto_ptuuid_name = grub_util_path_concat (2, GRUB_SYSCONFDIR, "crypto_ptuuid.cfg"); + static char fpcrypto_contents[256]; + static char fpcrypto_contents_2[256]; + int i = 0; + int k = 0; + fpcrypto_ptuuid_f = fopen (crypto_ptuuid_name, "r"); + + if (fpcrypto_ptuuid_f) + { + while(1) + { + k = fgetc(fpcrypto_ptuuid_f); + fpcrypto_contents[i] = k; + if ((k == '\n') || feof(fpcrypto_ptuuid_f)) + break; + i++; + } + fpcrypto_contents[i] = '\0'; + i = 0; + if (!feof(fpcrypto_ptuuid_f)) + while(1) + { + k = fgetc(fpcrypto_ptuuid_f); + fpcrypto_contents_2[i] = k; + if ((k == '\n') || feof(fpcrypto_ptuuid_f)) + break; + i++; + } + fpcrypto_contents_2[i] = '\0'; + if (grub_strcmp (partuuid, fpcrypto_contents) == 0) + if (grub_strcmp (crypto_device_name, fpcrypto_contents_2) == 0) + { + have_crypto_device = 1; + } + } + fclose (fpcrypto_ptuuid_f); /*closing file*/ + grub_free (crypto_ptuuid_name); /*freeing crypto_ptuuid_name*/ + } + } + } + grub_free (partuuid); + grub_free (crypto_device_name); + } + if (have_crypto_device) + { + /*If no header file is given with grub-install then we + use a dummy header file. This does not write data to + the disk. It is only used to make grub-install think this + is a cryptodisk. Since it really is but without a header + grub-install does not know this.*/ + grub_uint8_t num[6] = {'L','U','K','S',0xba,0xbe}; + grub_memcpy (header.magic, num, sizeof(num)); + header.version = 0x0100; + grub_strcpy (header.cipherName, "aes"); + grub_strcpy (header.cipherMode, "xts-plain64"); + grub_strcpy (header.hashSpec, "sha1"); + header.payloadOffset = 0x10000000; + header.keyBytes = 0x20000000; + grub_uint32_t alter_mkDigest[5] = {0x00,0x00,0x00,0x00,0x00}; + grub_memcpy (header.mkDigest,alter_mkDigest, sizeof(alter_mkDigest)); + grub_uint64_t alter_mkDigestSalt[4] = {0x00,0x00,0x00,0x00}; + grub_memcpy (header.mkDigestSalt,alter_mkDigestSalt, sizeof(alter_mkDigestSalt)); + header.mkDigestIterations = 0x0020; + grub_strcpy (header.uuid, "01234567-1234-1234-1234-0123456789ab"); + + /*This is for reading a header file in from grub-install for a detached header cryptodisk*/ + static FILE *fpcrypto_header_f; /*file pointer to be used as the local program name for crypto device ptuuid */ + static char *crypto_header_name; /*absolute path for crypto_ptuuid file*/ + crypto_header_name = grub_util_path_concat (2, GRUB_SYSCONFDIR, "crypto_header.cfg"); + fpcrypto_header_f = fopen (crypto_header_name, "r"); + + if (fpcrypto_header_f) + { + static char header_file_name[256]; /*Length of the header file name including path */ + int i = 0; + int k = 0; + static FILE *fpcrypto_detached_header_f; + + while(1) + { + k = fgetc(fpcrypto_header_f); + header_file_name[i] = k; + if ((k == '\n') || feof(fpcrypto_header_f)) + break; + i++; + } + header_file_name[i] = '\0'; + if (header_file_name[0] != '\0') /*In case the file is opened but empty. If empty then use above dummy header. */ + { + fpcrypto_detached_header_f = fopen (header_file_name, "r"); + if (fread (&header, 1, sizeof (header), fpcrypto_detached_header_f) != sizeof (header)) + err = GRUB_ERR_READ_ERROR; + fclose (fpcrypto_detached_header_f); + } + } + fclose (fpcrypto_header_f); + if (crypto_header_name) + grub_free (crypto_header_name); + } +#endif + + if (err) { if (err == GRUB_ERR_OUT_OF_RANGE) diff --git a/util/grub-install.c b/util/grub-install.c index 109a4e2..4e8803e 100644 --- a/util/grub-install.c +++ b/util/grub-install.c @@ -80,6 +80,8 @@ static char *label_bgcolor; static char *product_version; static int add_rs_codes = 1; static char *mattle_opts_file = NULL; +static char *crypto_device = NULL; +static char *crypto_header = NULL; enum { @@ -111,7 +113,9 @@ enum OPTION_LABEL_COLOR, OPTION_LABEL_BGCOLOR, OPTION_PRODUCT_VERSION, - OPTION_MATTLE_OPTS_FILE + OPTION_MATTLE_OPTS_FILE, + OPTION_CRYPTO_DEVICE, + OPTION_CRYPTO_HEADER }; static int fs_probe = 1; @@ -246,6 +250,16 @@ argp_parser (int key, char *arg, struct argp_state *state) mattle_opts_file = xstrdup (arg); return 0; + case OPTION_CRYPTO_DEVICE: + free (crypto_device); + crypto_device = xstrdup (arg); + return 0; + + case OPTION_CRYPTO_HEADER: + free (crypto_header); + crypto_header = xstrdup (arg); + return 0; + default: return ARGP_ERR_UNKNOWN; } @@ -311,6 +325,12 @@ static struct argp_option options[] = { {"product-version", OPTION_PRODUCT_VERSION, N_("STRING"), 0, N_("use STRING as product version"), 2}, {"mattle-opts-file", OPTION_MATTLE_OPTS_FILE, N_("FILE"), 0, N_("use FILE instead of using %smattle_opts.cfg "), 2}, + {"crypto-device", OPTION_CRYPTO_DEVICE, N_("DEVICE"), 0, N_("DEVICE is the LUKS crypto " + "volume with a detached header that the root filesystem is on. i.e." + " LUKS volume is on /dev/sda1 -> /dev/mapper/luks-volume and /boot may be on that device. " + "Usage --crypto-device=/dev/sdXY"), 2}, + {"crypto-header", OPTION_CRYPTO_HEADER, N_("FILE"), 0, N_("FILE is the detached LUKS header file for --crypto-device=DEVICE." + " A copy of FILE needs to be stored on a different device and must be accessible in order to boot the DEVICE."), 2}, {0, 0, 0, 0, 0, 0} }; @@ -1188,6 +1208,68 @@ main (int argc, char *argv[]) grub_install_mkdir_p (efidir); } + /*Here is the start to adding code for ability to do grub-install on a detached header + LUKS volume i.e --boot-directory=/boot and /boot resides on detached header + LUKS volume. This is placed outside the if (crypto_device) to clear file from + seperate grub-install calls. If placed inside then from each call crypto_ptuuid file will + retain the info and luks.c will access it even if --crypto-device is not called.*/ + static FILE *fpcrypto_ptuuid_f; /*file pointer to be used as the local program name for crypto device uuid*/ + static char *crypto_ptuuid_name; /*absolute path for crypto_ptuuid file*/ + crypto_ptuuid_name = grub_util_path_concat (2, GRUB_SYSCONFDIR, "crypto_ptuuid.cfg"); + fpcrypto_ptuuid_f = grub_util_fopen (crypto_ptuuid_name, "wb"); + + if (crypto_device) + { + grub_device_t crypto_dev = NULL; + char *crypto_grub_devname; + crypto_grub_devname = grub_util_get_grub_dev (crypto_device); + if (crypto_grub_devname) + { + char *partuuid = 0; + crypto_dev = grub_device_open (crypto_grub_devname); + if (crypto_dev && crypto_dev->disk) + { + grub_disk_t crypto_disk = crypto_dev->disk; + grub_partition_t crypto_p = crypto_disk->partition; + if (crypto_disk->partition) + { + /*This means that it wont find devices like /dev/sdX only /dev/sdXY + And only if /dev/sdXY is an msdos or gpt type partition*/ + if (crypto_p && (grub_strcmp (crypto_p->partmap->name, "msdos") == 0 || grub_strcmp (crypto_p->partmap->name, "gpt") == 0 )) + { + if (crypto_disk->partition->number + 1) + { + partuuid = grub_strdup (crypto_p->partuuid); + if (partuuid) + { + fprintf (fpcrypto_ptuuid_f, "%s\n%s", partuuid, crypto_grub_devname); + static FILE *fpcrypto_header_f; /*file pointer to be used as the local program name for crypto device uuid*/ + static char *crypto_header_name; /*absolute path for crypto_ptuuid file*/ + crypto_header_name = grub_util_path_concat (2, GRUB_SYSCONFDIR, "crypto_header.cfg"); + fpcrypto_header_f = grub_util_fopen (crypto_header_name, "wb"); + if (crypto_header) + { + fprintf (fpcrypto_header_f, "%s\n", crypto_header); + } + + fclose (fpcrypto_header_f); /*closing file*/ + free (crypto_header_name); /*freeing crypto_ptuuid_name*/ + } + grub_free (partuuid); + } + } + } + } + } + grub_free (crypto_grub_devname); + if (crypto_dev) + grub_device_close (crypto_dev); + } + + fclose (fpcrypto_ptuuid_f); /*closing file*/ + free (crypto_ptuuid_name); /*freeing crypto_ptuuid_name*/ + + if (platform == GRUB_INSTALL_PLATFORM_POWERPC_IEEE1275) { int is_guess = 0; -- 2.7.4