diff --git a/lib/libcryptsetup.h b/lib/libcryptsetup.h index 822028ab..a7bd1338 100644 --- a/lib/libcryptsetup.h +++ b/lib/libcryptsetup.h @@ -3036,6 +3036,26 @@ void crypt_safe_memzero(void *data, size_t size); */ void crypt_set_keyring_to_link(struct crypt_device *cd, int keyring_to_link_vk); +/** + * Set the type of volume key stored in keyring. + * + * @param cd crypt device handle + * @param key_type_desc the type of keyring key (e.g. "user" or "logon"), when + * @e NULL is specified, key type will be reset to default (logon) + * + * @return @e 0 on success or negative errno value when unknown key type was specified. + */ +int crypt_set_vk_keyring_type(struct crypt_device *cd, const char *key_type_desc); + +/** + * Get the type of volume key stored in keyring. + * + * @param cd crypt device handle + * + * @return string description of the keyring type (e.g. "user") or "logon" when cd is NULL + */ +const char *crypt_get_vk_keyring_type(struct crypt_device *cd); + /** @} */ #ifdef __cplusplus diff --git a/lib/libcryptsetup.sym b/lib/libcryptsetup.sym index a17b1157..4371a7dc 100644 --- a/lib/libcryptsetup.sym +++ b/lib/libcryptsetup.sym @@ -172,8 +172,10 @@ CRYPTSETUP_2.7 { crypt_format_luks2_opal; crypt_get_hw_encryption_type; crypt_get_hw_encryption_key_size; + crypt_get_vk_keyring_type; crypt_keyslot_context_init_by_keyring; crypt_resume_by_keyslot_context; crypt_set_keyring_to_link; + crypt_set_vk_keyring_type; crypt_wipe_hw_opal; } CRYPTSETUP_2.6; diff --git a/lib/libdevmapper.c b/lib/libdevmapper.c index 25f506f2..6d72527a 100644 --- a/lib/libdevmapper.c +++ b/lib/libdevmapper.c @@ -545,7 +545,7 @@ static char *_uf(char *buf, size_t buf_size, const char *s, unsigned u) } /* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt */ -static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags) +static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags, key_type_t key_type) { int r, max_size, null_cipher = 0, num_options = 0, keystr_len = 0; char *params = NULL, *hexkey = NULL; @@ -602,7 +602,8 @@ static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags) hexkey = crypt_safe_alloc(keystr_len); if (!hexkey) goto out; - r = snprintf(hexkey, keystr_len, ":%zu:logon:%s", tgt->u.crypt.vk->keylength, tgt->u.crypt.vk->key_description); + r = snprintf(hexkey, keystr_len, ":%zu:%s:%s", tgt->u.crypt.vk->keylength, + key_type_name(key_type), tgt->u.crypt.vk->key_description); if (r < 0 || r >= keystr_len) goto out; } else @@ -1246,14 +1247,14 @@ static void _destroy_dm_targets_params(struct crypt_dm_active_device *dmd) } while (t); } -static int _create_dm_targets_params(struct crypt_dm_active_device *dmd) +static int _create_dm_targets_params(struct crypt_dm_active_device *dmd, key_type_t key_type) { int r; struct dm_target *tgt = &dmd->segment; do { if (tgt->type == DM_CRYPT) - tgt->params = get_dm_crypt_params(tgt, dmd->flags); + tgt->params = get_dm_crypt_params(tgt, dmd->flags, key_type); else if (tgt->type == DM_VERITY) tgt->params = get_dm_verity_params(tgt, dmd->flags); else if (tgt->type == DM_INTEGRITY) @@ -1311,7 +1312,7 @@ static int _dm_create_device(struct crypt_device *cd, const char *name, const ch if ((dmd->flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt)) goto out; - r = _create_dm_targets_params(dmd); + r = _create_dm_targets_params(dmd, key_type_by_name(crypt_get_vk_keyring_type(cd))); if (r) goto out; @@ -1423,7 +1424,7 @@ static int _dm_reload_device(struct crypt_device *cd, const char *name, if ((dmd->flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt)) goto out; - r = _create_dm_targets_params(dmd); + r = _create_dm_targets_params(dmd, key_type_by_name(crypt_get_vk_keyring_type(cd))); if (r) goto out; @@ -1906,7 +1907,7 @@ static int _dm_target_query_crypt(struct crypt_device *cd, uint32_t get_flags, int r; size_t key_size; struct device *data_device = NULL; - char *cipher = NULL, *integrity = NULL; + char *cipher = NULL, *integrity = NULL, *key_type = NULL; struct volume_key *vk = NULL; tgt->type = DM_CRYPT; @@ -2025,12 +2026,16 @@ static int _dm_target_query_crypt(struct crypt_device *cd, uint32_t get_flags, /* ::: */ key_desc = NULL; endp = strpbrk(key_ + 1, ":"); + key_type = endp + 1; if (endp) key_desc = strpbrk(endp + 1, ":"); if (!key_desc) { r = -ENOMEM; goto err; } + /* replace colon with zero character */ + key_desc[0] = '\0'; + key_desc++; crypt_volume_key_set_description(vk, key_desc); } else { @@ -2056,6 +2061,8 @@ static int _dm_target_query_crypt(struct crypt_device *cd, uint32_t get_flags, tgt->data_device = data_device; if (vk) tgt->u.crypt.vk = vk; + if (key_type) + crypt_set_vk_keyring_type(cd, key_type); return 0; err: free(cipher); @@ -2994,7 +3001,8 @@ int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name, } if (vk->key_description) { - r = snprintf(msg, msg_size, "key set :%zu:logon:%s", vk->keylength, vk->key_description); + r = snprintf(msg, msg_size, "key set :%zu:%s:%s", vk->keylength, + crypt_get_vk_keyring_type(cd), vk->key_description); } else { key = crypt_bytes_to_hex(vk->keylength, vk->key); if (!key) { diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c index fbf13783..74ea067c 100644 --- a/lib/luks2/luks2_json_metadata.c +++ b/lib/luks2/luks2_json_metadata.c @@ -2864,7 +2864,8 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr tgt = &dmdc.segment; while (tgt) { if (tgt->type == DM_CRYPT) - crypt_drop_keyring_key_by_description(cd, tgt->u.crypt.vk->key_description, LOGON_KEY); + crypt_drop_keyring_key_by_description(cd, tgt->u.crypt.vk->key_description, + key_type_by_name(crypt_get_vk_keyring_type(cd))); tgt = tgt->next; } } @@ -2899,7 +2900,8 @@ int LUKS2_deactivate(struct crypt_device *cd, const char *name, struct luks2_hdr tgt = &dmdc.segment; while (tgt) { if (tgt->type == DM_CRYPT) - crypt_drop_keyring_key_by_description(cd, tgt->u.crypt.vk->key_description, LOGON_KEY); + crypt_drop_keyring_key_by_description(cd, tgt->u.crypt.vk->key_description, + key_type_by_name(crypt_get_vk_keyring_type(cd))); tgt = tgt->next; } } diff --git a/lib/setup.c b/lib/setup.c index d6e6d279..91fdf728 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -62,6 +62,7 @@ struct crypt_device { bool link_vk_to_keyring; int keyring_to_link_vk; + key_type_t keyring_key_type; uint64_t data_offset; uint64_t metadata_size; /* Used in LUKS2 format */ @@ -3939,7 +3940,7 @@ int crypt_suspend(struct crypt_device *cd, goto out; } - crypt_drop_keyring_key_by_description(cd, key_desc, LOGON_KEY); + crypt_drop_keyring_key_by_description(cd, key_desc, cd->keyring_key_type); if (dm_opal_uuid && (!crypt_data_device(cd) || opal_lock(cd, crypt_data_device(cd), opal_segment_number))) log_err(cd, _("Device %s was suspended but hardware OPAL device cannot be locked."), name); @@ -7190,7 +7191,7 @@ int crypt_volume_key_keyring(struct crypt_device *cd __attribute__((unused)), in int crypt_volume_key_load_in_keyring(struct crypt_device *cd, struct volume_key *vk) { int r; - const char *type_name = key_type_name(LOGON_KEY); + const char *type_name = key_type_name(cd->keyring_key_type); if (!vk || !cd || !type_name) return -EINVAL; @@ -7202,7 +7203,7 @@ int crypt_volume_key_load_in_keyring(struct crypt_device *cd, struct volume_key log_dbg(cd, "Loading key (%zu bytes, type %s) in thread keyring.", vk->keylength, type_name); - r = keyring_add_key_in_thread_keyring(LOGON_KEY, vk->key_description, vk->key, vk->keylength); + r = keyring_add_key_in_thread_keyring(cd->keyring_key_type, vk->key_description, vk->key, vk->keylength); if (r) { log_dbg(cd, "keyring_add_key_in_thread_keyring failed (error %d)", r); log_err(cd, _("Failed to load key in kernel keyring.")); @@ -7211,7 +7212,7 @@ int crypt_volume_key_load_in_keyring(struct crypt_device *cd, struct volume_key if (!r && cd->link_vk_to_keyring) { log_dbg(cd, "Linking volume key to the specified keyring"); - r = keyring_link_key_to_keyring(LOGON_KEY, vk->key_description, cd->keyring_to_link_vk); + r = keyring_link_key_to_keyring(cd->keyring_key_type, vk->key_description, cd->keyring_to_link_vk); if (r) { log_err(cd, _("Failed to link key to the specified keyring.")); log_dbg(cd, "The keyring_link_key_to_keyring function failed (error %d).", r); @@ -7261,6 +7262,24 @@ void crypt_set_keyring_to_link(struct crypt_device *cd, int keyring_to_link_vk) } } +int crypt_set_vk_keyring_type(struct crypt_device *cd, const char *key_type_desc) +{ + if (!cd) + return -EINVAL; + + key_type_t key_type = key_type_desc ? key_type_by_name(key_type_desc) : LOGON_KEY; + if (key_type != LOGON_KEY && key_type != USER_KEY) + return -EINVAL; + + cd->keyring_key_type = key_type; + return 0; +} + +const char *crypt_get_vk_keyring_type(struct crypt_device *cd) +{ + return key_type_name(cd ? cd->keyring_key_type : LOGON_KEY); +} + /* internal only */ void crypt_drop_keyring_key(struct crypt_device *cd, struct volume_key *vks) { diff --git a/lib/utils_keyring.c b/lib/utils_keyring.c index 4750c6a4..72704006 100644 --- a/lib/utils_keyring.c +++ b/lib/utils_keyring.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,9 @@ static const struct { } key_types[] = { { LOGON_KEY, "logon" }, { USER_KEY, "user" }, + { BIG_KEY, "big_key" }, + { TRUSTED_KEY, "trusted" }, + { ENCRYPTED_KEY, "encrypted" }, }; #include @@ -249,6 +253,18 @@ const char *key_type_name(key_type_t type) return NULL; } +key_type_t key_type_by_name(const char *name) +{ +#ifdef KERNEL_KEYRING + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(key_types); i++) + if (!strcmp(key_types[i].type_name, name)) + return key_types[i].type; +#endif + return INVALID_KEY; +} + int keyring_link_key_to_keyring(key_type_t ktype, const char *key_desc, key_serial_t keyring_to_link) { return keyring_link_key_to_keyring_key_type(key_type_name(ktype), key_desc, keyring_to_link); diff --git a/lib/utils_keyring.h b/lib/utils_keyring.h index 79424809..91465626 100644 --- a/lib/utils_keyring.h +++ b/lib/utils_keyring.h @@ -24,9 +24,10 @@ #include -typedef enum { LOGON_KEY = 0, USER_KEY } key_type_t; +typedef enum { LOGON_KEY = 0, USER_KEY, BIG_KEY, TRUSTED_KEY, ENCRYPTED_KEY, INVALID_KEY } key_type_t; const char *key_type_name(key_type_t ktype); +key_type_t key_type_by_name(const char *name); int keyring_check(void); diff --git a/src/cryptsetup.c b/src/cryptsetup.c index 39626564..68a1f4a6 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -1654,6 +1654,16 @@ static int action_open_luks(void) set_activation_flags(&activate_flags); + if (ARG_SET(OPT_VOLUME_KEY_TYPE_ID)) { + r = crypt_set_vk_keyring_type(cd, ARG_STR(OPT_VOLUME_KEY_TYPE_ID)); + + if (r) { + log_err(_("The specified keyring key type %s is invalid."), + ARG_STR(OPT_VOLUME_KEY_TYPE_ID)); + goto out; + } + } + if (ARG_SET(OPT_LINK_VK_TO_KEYRING_ID)) crypt_set_keyring_to_link(cd, ARG_INT32(OPT_LINK_VK_TO_KEYRING_ID)); @@ -2512,6 +2522,16 @@ static int action_luksResume(void) return r; r = -EINVAL; + if (ARG_SET(OPT_VOLUME_KEY_TYPE_ID)) { + r = crypt_set_vk_keyring_type(cd, ARG_STR(OPT_VOLUME_KEY_TYPE_ID)); + + if (r) { + log_err(_("The specified keyring key type %s is invalid."), + ARG_STR(OPT_VOLUME_KEY_TYPE_ID)); + goto out; + } + } + if (ARG_SET(OPT_LINK_VK_TO_KEYRING_ID)) crypt_set_keyring_to_link(cd, ARG_INT32(OPT_LINK_VK_TO_KEYRING_ID)); diff --git a/src/cryptsetup_arg_list.h b/src/cryptsetup_arg_list.h index 534a707d..b4826890 100644 --- a/src/cryptsetup_arg_list.h +++ b/src/cryptsetup_arg_list.h @@ -119,6 +119,8 @@ ARG(OPT_LUKS2_METADATA_SIZE, '\0', POPT_ARG_STRING, N_("LUKS2 header metadata ar ARG(OPT_VOLUME_KEY_FILE, '\0', POPT_ARG_STRING, N_("Use the volume key from file."), NULL, CRYPT_ARG_STRING, {}, {}) +ARG(OPT_VOLUME_KEY_TYPE, '\0', POPT_ARG_STRING, N_("Specify the type of the volume key stored in keyring"), NULL, CRYPT_ARG_STRING, {}, {}) + ARG(OPT_NEW_KEYFILE, '\0', POPT_ARG_STRING, N_("Read the key for a new slot from a file"), NULL, CRYPT_ARG_STRING, {}, OPT_NEW_KEYFILE_ACTIONS) ARG(OPT_NEW_KEY_SLOT, '\0', POPT_ARG_STRING, N_("Slot number for new key (default is first free)"), "INT", CRYPT_ARG_INT32, { .i32_value = CRYPT_ANY_SLOT }, OPT_NEW_KEY_SLOT_ACTIONS) diff --git a/src/utils_arg_names.h b/src/utils_arg_names.h index f64f18b2..8f212ed0 100644 --- a/src/utils_arg_names.h +++ b/src/utils_arg_names.h @@ -110,6 +110,7 @@ #define OPT_LUKS2_METADATA_SIZE "luks2-metadata-size" #define OPT_MASTER_KEY_FILE "master-key-file" #define OPT_VOLUME_KEY_FILE "volume-key-file" +#define OPT_VOLUME_KEY_TYPE "volume-key-type" #define OPT_NEW "new" #define OPT_NEW_KEY_SLOT "new-key-slot" #define OPT_NEW_KEYFILE "new-keyfile"