mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-05 16:00:05 +01:00
Support trusted & encrypted keyring for plain device.
This commit is contained in:
@@ -64,6 +64,7 @@ struct volume_key *crypt_generate_volume_key(struct crypt_device *cd, size_t key
|
||||
void crypt_free_volume_key(struct volume_key *vk);
|
||||
int crypt_volume_key_set_description(struct volume_key *key,
|
||||
const char *key_description, key_type_t keyring);
|
||||
int crypt_volume_key_set_description_by_name(struct volume_key *vk, const char *key_name);
|
||||
void crypt_volume_key_set_id(struct volume_key *vk, int id);
|
||||
int crypt_volume_key_get_id(const struct volume_key *vk);
|
||||
void crypt_volume_key_add_next(struct volume_key **vks, struct volume_key *vk);
|
||||
|
||||
14
lib/setup.c
14
lib/setup.c
@@ -5336,7 +5336,14 @@ int crypt_activate_by_keyslot_context(struct crypt_device *cd,
|
||||
} else if (isTCRYPT(cd->type)) {
|
||||
r = 0;
|
||||
} else if (name && isPLAIN(cd->type)) {
|
||||
if (kc->get_passphrase && kc->type != CRYPT_KC_TYPE_TOKEN) {
|
||||
if (kc->type == CRYPT_KC_TYPE_VK_KEYRING) {
|
||||
vk = crypt_alloc_volume_key(cd->u.plain.key_size, NULL);
|
||||
if (!vk)
|
||||
return -ENOMEM;
|
||||
r = crypt_volume_key_set_description_by_name(vk, kc->u.vk_kr.key_description);
|
||||
if (r < 0)
|
||||
log_err(cd, _("Cannot use keyring key %s."), kc->u.vk_kr.key_description);
|
||||
} else if (kc->get_passphrase && kc->type != CRYPT_KC_TYPE_TOKEN) {
|
||||
r = kc->get_passphrase(cd, kc, &passphrase, &passphrase_size);
|
||||
if (r < 0)
|
||||
return r;
|
||||
@@ -7295,7 +7302,10 @@ int crypt_use_keyring_for_vk(struct crypt_device *cd)
|
||||
uint32_t dmc_flags;
|
||||
|
||||
/* dm backend must be initialized */
|
||||
if (!cd || !isLUKS2(cd->type))
|
||||
if (!cd)
|
||||
return 0;
|
||||
|
||||
if (!isPLAIN(cd->type) && !isLUKS2(cd->type))
|
||||
return 0;
|
||||
|
||||
if (!_vk_via_keyring || !kernel_keyring_support())
|
||||
|
||||
@@ -277,6 +277,36 @@ const char *key_type_name(key_type_t type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key_type_t keyring_type_and_name(const char *key_name, const char **name)
|
||||
{
|
||||
char type[16], *name_tmp;
|
||||
size_t type_len;
|
||||
|
||||
if (!key_name || key_name[0] != '%')
|
||||
return INVALID_KEY;
|
||||
|
||||
key_name++;
|
||||
if (!*key_name || *key_name == ':')
|
||||
return INVALID_KEY;
|
||||
|
||||
name_tmp = strchr(key_name, ':');
|
||||
if (!name_tmp)
|
||||
return INVALID_KEY;
|
||||
name_tmp++;
|
||||
|
||||
type_len = name_tmp - key_name - 1;
|
||||
if (type_len >= sizeof(type) - 1)
|
||||
return INVALID_KEY;
|
||||
|
||||
memcpy(type, key_name, type_len);
|
||||
type[type_len] = '\0';
|
||||
|
||||
if (name)
|
||||
*name = name_tmp;
|
||||
|
||||
return key_type_by_name(type);
|
||||
}
|
||||
|
||||
key_serial_t keyring_find_key_id_by_name(const char *key_name)
|
||||
{
|
||||
key_serial_t id = 0;
|
||||
@@ -425,6 +455,11 @@ const char *key_type_name(key_type_t type)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
key_type_t keyring_type_and_name(const char *key_name, const char **name)
|
||||
{
|
||||
return INVALID_KEY;
|
||||
}
|
||||
|
||||
key_serial_t keyring_find_key_id_by_name(const char *key_name)
|
||||
{
|
||||
return 0;
|
||||
|
||||
@@ -21,6 +21,7 @@ typedef enum { LOGON_KEY = 0, USER_KEY, BIG_KEY, TRUSTED_KEY, ENCRYPTED_KEY, INV
|
||||
|
||||
const char *key_type_name(key_type_t ktype);
|
||||
key_type_t key_type_by_name(const char *name);
|
||||
key_type_t keyring_type_and_name(const char *key_name, const char **name);
|
||||
key_serial_t keyring_find_key_id_by_name(const char *key_name);
|
||||
key_serial_t keyring_find_keyring_id_by_name(const char *keyring_name);
|
||||
|
||||
|
||||
@@ -57,6 +57,17 @@ int crypt_volume_key_set_description(struct volume_key *vk,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int crypt_volume_key_set_description_by_name(struct volume_key *vk, const char *key_name)
|
||||
{
|
||||
const char *key_description = NULL;
|
||||
key_type_t keyring = keyring_type_and_name(key_name, &key_description);
|
||||
|
||||
if (keyring == INVALID_KEY)
|
||||
return -EINVAL;
|
||||
|
||||
return crypt_volume_key_set_description(vk, key_description, keyring);
|
||||
}
|
||||
|
||||
void crypt_volume_key_set_id(struct volume_key *vk, int id)
|
||||
{
|
||||
if (vk && id >= 0)
|
||||
|
||||
@@ -42,18 +42,35 @@ create <name> <device> (*OBSOLETE syntax*)
|
||||
Opens (creates a mapping with) <name> backed by device <device>.
|
||||
|
||||
*WARNING:* You should always specify options *--cipher*, *--key-size* and
|
||||
(if no keyfile is used) then also *--hash* to avoid incompatibility as
|
||||
(if no keyfile or keyring is used) then also *--hash* to avoid incompatibility as
|
||||
default values can be different in older cryptsetup versions. +
|
||||
|
||||
The plain format also allows retrieving a volume key from a kernel keyring
|
||||
specified by *--volume-key-keyring*. Key in kernel keyring must be configured
|
||||
before issuing cryptsetup commands, as cryptsetup does not upload any keys to
|
||||
the keyring in plain mode. For subsequent commands (like resize), the user must
|
||||
ensure that the key in the keyring is unchanged. Otherwise, reloading the key
|
||||
can cause data corruption after an unexpected key change.
|
||||
|
||||
*<options>* can be [--hash, --cipher, --verify-passphrase, --sector-size,
|
||||
--key-file, --keyfile-size, --keyfile-offset, --key-size, --offset,
|
||||
--skip, --device-size, --size, --readonly, --shared, --allow-discards,
|
||||
--refresh, --timeout, --verify-passphrase, --iv-large-sectors].
|
||||
--refresh, --timeout, --verify-passphrase, --iv-large-sectors, --volume-key-keyring].
|
||||
|
||||
Example: 'cryptsetup open --type plain --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha256 /dev/sda10 e1' maps the raw
|
||||
encrypted device /dev/sda10 to the mapped (decrypted) device
|
||||
/dev/mapper/e1, which can then be mounted, fsck-ed or have a filesystem
|
||||
created on it.
|
||||
*EXAMPLES:*
|
||||
|
||||
To map the encrypted device /dev/sda10 to the decrypted device /dev/mapper/e1, you can use
|
||||
|
||||
*cryptsetup open --type plain --cipher aes-cbc-essiv:sha256 --key-size 256 --hash sha256 /dev/sda10 e1*
|
||||
|
||||
The decrypted device can then be used as a normal block device to mount a filesystem.
|
||||
|
||||
To map a device with a volume key in the preconfigured trusted or encrypted keyring, you need to specify
|
||||
keyring with the key and remove hash specification, for example, to use *%trusted:mykey*:
|
||||
|
||||
*cryptsetup open --type plain /dev/sda10 e1 --volume-key-keyring=%trusted:mykey --cipher aes-xts-plain64 --key-size 256*
|
||||
|
||||
Note that the key size must match the preconfigured key in the keyring.
|
||||
|
||||
=== LUKS
|
||||
*open <device> <name>* +
|
||||
|
||||
@@ -224,7 +224,8 @@ static int action_open_plain(void)
|
||||
.offset = ARG_UINT64(OPT_OFFSET_ID),
|
||||
.sector_size = ARG_UINT32(OPT_SECTOR_SIZE_ID) ?: SECTOR_SIZE
|
||||
};
|
||||
char *password = NULL;
|
||||
struct crypt_keyslot_context *kc = NULL;
|
||||
char *password = NULL, *vk_description_activation = NULL;
|
||||
const char *activated_name = NULL;
|
||||
size_t passwordLen, key_size_max, signatures = 0,
|
||||
key_size = (ARG_UINT32(OPT_KEY_SIZE_ID) ?: DEFAULT_PLAIN_KEYBITS) / 8;
|
||||
@@ -249,12 +250,12 @@ static int action_open_plain(void)
|
||||
cipher, cipher_mode, key_size * 8);
|
||||
compat_warning = true;
|
||||
}
|
||||
if (!ARG_SET(OPT_HASH_ID) && !ARG_SET(OPT_KEY_FILE_ID)) {
|
||||
if (!ARG_SET(OPT_HASH_ID) && !ARG_SET(OPT_KEY_FILE_ID) && !ARG_SET(OPT_VOLUME_KEY_KEYRING_ID)) {
|
||||
log_err(_("WARNING: Using default options for hash (%s) that could be incompatible with older versions."), params.hash);
|
||||
compat_warning = true;
|
||||
}
|
||||
if (compat_warning)
|
||||
log_err(_("For plain mode, always use options --cipher, --key-size and if no keyfile is used, then also --hash."));
|
||||
log_err(_("For plain mode, always use options --cipher, --key-size and if no keyfile or keyring is used, then also --hash."));
|
||||
|
||||
/* FIXME: temporary hack, no hashing for keyfiles in plain mode */
|
||||
if (ARG_SET(OPT_KEY_FILE_ID) && !tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID))) {
|
||||
@@ -264,6 +265,12 @@ static int action_open_plain(void)
|
||||
"in plain mode with keyfile specified.\n"));
|
||||
}
|
||||
|
||||
if (ARG_SET(OPT_VOLUME_KEY_KEYRING_ID)) {
|
||||
r = tools_parse_vk_description(ARG_STR(OPT_VOLUME_KEY_KEYRING_ID), &vk_description_activation);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (params.hash && !strcmp(params.hash, "plain"))
|
||||
params.hash = NULL;
|
||||
|
||||
@@ -349,7 +356,14 @@ static int action_open_plain(void)
|
||||
|
||||
set_activation_flags(&activate_flags);
|
||||
|
||||
if (!tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID))) {
|
||||
if (ARG_SET(OPT_VOLUME_KEY_KEYRING_ID)) {
|
||||
r = crypt_keyslot_context_init_by_vk_in_keyring(cd, vk_description_activation, &kc);
|
||||
if (r < 0)
|
||||
goto out;
|
||||
|
||||
r = crypt_activate_by_keyslot_context(cd, activated_name, CRYPT_ANY_SLOT,
|
||||
kc, CRYPT_ANY_SLOT, NULL, activate_flags | CRYPT_ACTIVATE_KEYRING_KEY);
|
||||
} else if (!tools_is_stdin(ARG_STR(OPT_KEY_FILE_ID))) {
|
||||
/* If no hash, key is read directly, read size is always key_size
|
||||
* (possible --keyfile_size is ignored.
|
||||
* If hash is specified, --keyfile_size is applied.
|
||||
@@ -372,6 +386,8 @@ static int action_open_plain(void)
|
||||
CRYPT_ANY_SLOT, password, passwordLen, activate_flags);
|
||||
}
|
||||
out:
|
||||
free(vk_description_activation);
|
||||
crypt_keyslot_context_free(kc);
|
||||
crypt_free(cd);
|
||||
crypt_free(cd1);
|
||||
crypt_safe_free(password);
|
||||
@@ -3336,7 +3352,7 @@ static const char *verify_tcryptdump(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char * verify_open(void)
|
||||
static const char *verify_open(void)
|
||||
{
|
||||
if (ARG_SET(OPT_PERSISTENT_ID) && ARG_SET(OPT_TEST_PASSPHRASE_ID))
|
||||
return _("Option --persistent is not allowed with --test-passphrase.");
|
||||
@@ -3378,6 +3394,10 @@ static const char * verify_open(void)
|
||||
if (ARG_SET(OPT_UNBOUND_ID) && !ARG_SET(OPT_TEST_PASSPHRASE_ID))
|
||||
return _("Option --unbound cannot be used without --test-passphrase.");
|
||||
|
||||
if (ARG_SET(OPT_VOLUME_KEY_KEYRING_ID) && (ARG_SET(OPT_HASH_ID) ||
|
||||
ARG_SET(OPT_VOLUME_KEY_FILE_ID)) && !strcmp_or_null(device_type, "plain"))
|
||||
return _("Option --volume-key-keyring cannot be combined with --hash or --volume-key-file.");
|
||||
|
||||
/* "open --type tcrypt" and "tcryptDump" checks are identical */
|
||||
return verify_tcryptdump();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user