cryptodisk: Add infrastructure to pass data from cryptomount to cryptodisk modules

Previously, the cryptomount arguments were passed by global variable and
function call argument, neither of which are ideal. This change passes data
via a grub_cryptomount_args struct, which can be added to over time as
opposed to continually adding arguments to the cryptodisk scan and
recover_key.

As an example, passing a password as a cryptomount argument is implemented.
However, the backends are not implemented, so testing this will return a not
implemented error.

Also, add comments to cryptomount argument parsing to make it more obvious
which argument states are being handled.

Signed-off-by: Glenn Washburn <development@efficientek.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
Glenn Washburn 2021-12-09 11:14:55 -06:00 committed by Daniel Kiper
parent e1d22da580
commit be62f0836c
5 changed files with 46 additions and 14 deletions

View File

@ -41,6 +41,7 @@ static const struct grub_arg_option options[] =
/* TRANSLATORS: It's still restricted to cryptodisks only. */
{"all", 'a', 0, N_("Mount all."), 0, 0},
{"boot", 'b', 0, N_("Mount all volumes with `boot' flag set."), 0, 0},
{"password", 'p', 0, N_("Password to open volumes."), 0, ARG_TYPE_STRING},
{0, 0, 0, 0, 0, 0}
};
@ -996,7 +997,9 @@ cryptodisk_close (grub_cryptodisk_t dev)
}
static grub_cryptodisk_t
grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
grub_cryptodisk_scan_device_real (const char *name,
grub_disk_t source,
grub_cryptomount_args_t cargs)
{
grub_err_t err;
grub_cryptodisk_t dev;
@ -1015,7 +1018,7 @@ grub_cryptodisk_scan_device_real (const char *name, grub_disk_t source)
if (!dev)
continue;
err = cr->recover_key (source, dev);
err = cr->recover_key (source, dev, cargs);
if (err)
{
cryptodisk_close (dev);
@ -1080,11 +1083,12 @@ grub_cryptodisk_cheat_mount (const char *sourcedev, const char *cheat)
static int
grub_cryptodisk_scan_device (const char *name,
void *data __attribute__ ((unused)))
void *data)
{
int ret = 0;
grub_disk_t source;
grub_cryptodisk_t dev;
grub_cryptomount_args_t cargs = data;
grub_errno = GRUB_ERR_NONE;
/* Try to open disk. */
@ -1095,7 +1099,7 @@ grub_cryptodisk_scan_device (const char *name,
return 0;
}
dev = grub_cryptodisk_scan_device_real (name, source);
dev = grub_cryptodisk_scan_device_real (name, source, cargs);
if (dev)
{
ret = (search_uuid != NULL && grub_strcasecmp (search_uuid, dev->uuid) == 0);
@ -1124,6 +1128,7 @@ static grub_err_t
grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
{
struct grub_arg_list *state = ctxt->state;
struct grub_cryptomount_args cargs = {0};
if (argc < 1 && !state[1].set && !state[2].set)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "device name required");
@ -1131,7 +1136,13 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
if (grub_cryptodisk_list == NULL)
return grub_error (GRUB_ERR_BAD_MODULE, "no cryptodisk modules loaded");
if (state[0].set)
if (state[3].set) /* password */
{
cargs.key_data = (grub_uint8_t *) state[3].arg;
cargs.key_len = grub_strlen (state[3].arg);
}
if (state[0].set) /* uuid */
{
int found_uuid;
grub_cryptodisk_t dev;
@ -1146,7 +1157,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
check_boot = state[2].set;
search_uuid = args[0];
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
found_uuid = grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
search_uuid = NULL;
if (found_uuid)
@ -1163,11 +1174,11 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
}
return grub_errno;
}
else if (state[1].set || (argc == 0 && state[2].set))
else if (state[1].set || (argc == 0 && state[2].set)) /* -a|-b */
{
search_uuid = NULL;
check_boot = state[2].set;
grub_device_iterate (&grub_cryptodisk_scan_device, NULL);
grub_device_iterate (&grub_cryptodisk_scan_device, &cargs);
search_uuid = NULL;
return GRUB_ERR_NONE;
}
@ -1208,7 +1219,7 @@ grub_cmd_cryptomount (grub_extcmd_context_t ctxt, int argc, char **args)
return GRUB_ERR_NONE;
}
dev = grub_cryptodisk_scan_device_real (diskname, disk);
dev = grub_cryptodisk_scan_device_real (diskname, disk, &cargs);
grub_disk_close (disk);
if (disklast)
@ -1347,7 +1358,7 @@ GRUB_MOD_INIT (cryptodisk)
{
grub_disk_dev_register (&grub_cryptodisk_dev);
cmd = grub_register_extcmd ("cryptomount", grub_cmd_cryptomount, 0,
N_("SOURCE|-u UUID|-a|-b"),
N_("[-p password] <SOURCE|-u UUID|-a|-b>"),
N_("Mount a crypto device."), options);
grub_procfs_register ("luks_script", &luks_script);
}

View File

@ -398,7 +398,7 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
}
static grub_err_t
recover_key (grub_disk_t source, grub_cryptodisk_t dev)
recover_key (grub_disk_t source, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs)
{
grub_size_t keysize;
grub_uint8_t digest[GRUB_CRYPTO_MAX_MDLEN];
@ -414,6 +414,10 @@ recover_key (grub_disk_t source, grub_cryptodisk_t dev)
grub_disk_addr_t sector;
grub_err_t err;
/* Keyfiles are not implemented yet */
if (cargs->key_data != NULL || cargs->key_len)
return GRUB_ERR_NOT_IMPLEMENTED_YET;
if (dev->cipher->cipher->blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
return grub_error (GRUB_ERR_BUG, "cipher block is too long");

View File

@ -152,7 +152,8 @@ configure_ciphers (grub_disk_t disk, const char *check_uuid,
static grub_err_t
luks_recover_key (grub_disk_t source,
grub_cryptodisk_t dev)
grub_cryptodisk_t dev,
grub_cryptomount_args_t cargs)
{
struct grub_luks_phdr header;
grub_size_t keysize;
@ -165,6 +166,10 @@ luks_recover_key (grub_disk_t source,
grub_size_t max_stripes = 1;
char *tmp;
/* Keyfiles are not implemented yet */
if (cargs->key_data != NULL || cargs->key_len)
return GRUB_ERR_NOT_IMPLEMENTED_YET;
err = grub_disk_read (source, 0, 0, sizeof (header), &header);
if (err)
return err;

View File

@ -545,7 +545,8 @@ luks2_decrypt_key (grub_uint8_t *out_key,
static grub_err_t
luks2_recover_key (grub_disk_t source,
grub_cryptodisk_t crypt)
grub_cryptodisk_t crypt,
grub_cryptomount_args_t cargs)
{
grub_uint8_t candidate_key[GRUB_CRYPTODISK_MAX_KEYLEN];
char passphrase[MAX_PASSPHRASE], cipher[32];
@ -559,6 +560,10 @@ luks2_recover_key (grub_disk_t source,
grub_json_t *json = NULL, keyslots;
grub_err_t ret;
/* Keyfiles are not implemented yet */
if (cargs->key_data != NULL || cargs->key_len)
return GRUB_ERR_NOT_IMPLEMENTED_YET;
ret = luks2_read_header (source, &header);
if (ret)
return ret;

View File

@ -66,6 +66,13 @@ typedef gcry_err_code_t
(*grub_cryptodisk_rekey_func_t) (struct grub_cryptodisk *dev,
grub_uint64_t zoneno);
struct grub_cryptomount_args
{
grub_uint8_t *key_data;
grub_size_t key_len;
};
typedef struct grub_cryptomount_args *grub_cryptomount_args_t;
struct grub_cryptodisk
{
struct grub_cryptodisk *next;
@ -119,7 +126,7 @@ struct grub_cryptodisk_dev
grub_cryptodisk_t (*scan) (grub_disk_t disk, const char *check_uuid,
int boot_only);
grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev);
grub_err_t (*recover_key) (grub_disk_t disk, grub_cryptodisk_t dev, grub_cryptomount_args_t cargs);
};
typedef struct grub_cryptodisk_dev *grub_cryptodisk_dev_t;