Allow linking VK to a user-specified keyring.

Add a new API crypt_set_keyring_to_link nad CLI option
--link-vk-to-keyring. This allows the user to specify ID of the keyring
where the VK should be linked.
This commit is contained in:
Daniel Zatovic
2023-03-10 11:19:33 +01:00
parent 1b25cc5ed7
commit 138da3e73a
9 changed files with 83 additions and 0 deletions

View File

@@ -3028,6 +3028,14 @@ void *crypt_safe_realloc(void *data, size_t size);
*/ */
void crypt_safe_memzero(void *data, size_t size); void crypt_safe_memzero(void *data, size_t size);
/**
* Link the volume key to the specified keyring.
*
* @param cd crypt device handle
* @param keyring_to_link_vk the ID of the keyring in which volume key should be linked
*/
void crypt_set_keyring_to_link(struct crypt_device *cd, int keyring_to_link_vk);
/** @} */ /** @} */
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -174,5 +174,6 @@ CRYPTSETUP_2.7 {
crypt_get_hw_encryption_key_size; crypt_get_hw_encryption_key_size;
crypt_keyslot_context_init_by_keyring; crypt_keyslot_context_init_by_keyring;
crypt_resume_by_keyslot_context; crypt_resume_by_keyslot_context;
crypt_set_keyring_to_link;
crypt_wipe_hw_opal; crypt_wipe_hw_opal;
} CRYPTSETUP_2.6; } CRYPTSETUP_2.6;

View File

@@ -60,6 +60,9 @@ struct crypt_device {
/* global context scope settings */ /* global context scope settings */
unsigned key_in_keyring:1; unsigned key_in_keyring:1;
bool link_vk_to_keyring;
int keyring_to_link_vk;
uint64_t data_offset; uint64_t data_offset;
uint64_t metadata_size; /* Used in LUKS2 format */ uint64_t metadata_size; /* Used in LUKS2 format */
uint64_t keyslots_size; /* Used in LUKS2 format */ uint64_t keyslots_size; /* Used in LUKS2 format */
@@ -7206,6 +7209,15 @@ int crypt_volume_key_load_in_keyring(struct crypt_device *cd, struct volume_key
} else } else
crypt_set_key_in_keyring(cd, 1); crypt_set_key_in_keyring(cd, 1);
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);
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);
}
}
return r; return r;
} }
@@ -7241,6 +7253,14 @@ void crypt_drop_keyring_key_by_description(struct crypt_device *cd, const char *
crypt_set_key_in_keyring(cd, 0); crypt_set_key_in_keyring(cd, 0);
} }
void crypt_set_keyring_to_link(struct crypt_device *cd, int keyring_to_link_vk)
{
if (cd) {
cd->link_vk_to_keyring = true;
cd->keyring_to_link_vk = keyring_to_link_vk;
}
}
/* internal only */ /* internal only */
void crypt_drop_keyring_key(struct crypt_device *cd, struct volume_key *vks) void crypt_drop_keyring_key(struct crypt_device *cd, struct volume_key *vks)
{ {

View File

@@ -71,6 +71,12 @@ static long keyctl_read(key_serial_t key, char *buffer, size_t buflen)
return syscall(__NR_keyctl, KEYCTL_READ, key, buffer, buflen); return syscall(__NR_keyctl, KEYCTL_READ, key, buffer, buflen);
} }
/* keyctl_link */
static long keyctl_link(key_serial_t key, key_serial_t keyring)
{
return syscall(__NR_keyctl, KEYCTL_LINK, key, keyring);
}
/* keyctl_unlink */ /* keyctl_unlink */
static long keyctl_unlink(key_serial_t key, key_serial_t keyring) static long keyctl_unlink(key_serial_t key, key_serial_t keyring)
{ {
@@ -180,6 +186,33 @@ int keyring_get_passphrase(const char *key_desc,
#endif #endif
} }
static int keyring_link_key_to_keyring_key_type(const char *type_name, const char *key_desc,
key_serial_t keyring_to_link)
{
#ifdef KERNEL_KEYRING
long r;
key_serial_t kid;
if (!type_name || !key_desc)
return -EINVAL;
do
kid = request_key(type_name, key_desc, NULL, 0);
while (kid < 0 && errno == EINTR);
if (kid < 0)
return 0;
r = keyctl_link(kid, keyring_to_link);
if (r < 0)
return -errno;
return 0;
#else
return -ENOTSUP;
#endif
}
static int keyring_revoke_and_unlink_key_type(const char *type_name, const char *key_desc) static int keyring_revoke_and_unlink_key_type(const char *type_name, const char *key_desc)
{ {
#ifdef KERNEL_KEYRING #ifdef KERNEL_KEYRING
@@ -216,6 +249,11 @@ const char *key_type_name(key_type_t type)
return NULL; return NULL;
} }
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);
}
int keyring_revoke_and_unlink_key(key_type_t ktype, const char *key_desc) int keyring_revoke_and_unlink_key(key_type_t ktype, const char *key_desc)
{ {
return keyring_revoke_and_unlink_key_type(key_type_name(ktype), key_desc); return keyring_revoke_and_unlink_key_type(key_type_name(ktype), key_desc);

View File

@@ -51,5 +51,6 @@ int keyring_add_key_in_user_keyring(
size_t key_size); size_t key_size);
int keyring_revoke_and_unlink_key(key_type_t ktype, const char *key_desc); int keyring_revoke_and_unlink_key(key_type_t ktype, const char *key_desc);
int keyring_link_key_to_keyring(key_type_t ktype, const char *key_desc, int keyring_to_link);
#endif #endif

View File

@@ -1654,6 +1654,9 @@ static int action_open_luks(void)
set_activation_flags(&activate_flags); set_activation_flags(&activate_flags);
if (ARG_SET(OPT_LINK_VK_TO_KEYRING_ID))
crypt_set_keyring_to_link(cd, ARG_INT32(OPT_LINK_VK_TO_KEYRING_ID));
if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) { if (ARG_SET(OPT_VOLUME_KEY_FILE_ID)) {
keysize = crypt_get_volume_key_size(cd); keysize = crypt_get_volume_key_size(cd);
if (!keysize && !ARG_SET(OPT_KEY_SIZE_ID)) { if (!keysize && !ARG_SET(OPT_KEY_SIZE_ID)) {
@@ -2509,6 +2512,9 @@ static int action_luksResume(void)
return r; return r;
r = -EINVAL; r = -EINVAL;
if (ARG_SET(OPT_LINK_VK_TO_KEYRING_ID))
crypt_set_keyring_to_link(cd, ARG_INT32(OPT_LINK_VK_TO_KEYRING_ID));
if (!isLUKS(crypt_get_type(cd))) { if (!isLUKS(crypt_get_type(cd))) {
log_err(_("%s is not active LUKS device name or header is missing."), action_argv[0]); log_err(_("%s is not active LUKS device name or header is missing."), action_argv[0]);
goto out; goto out;
@@ -3655,6 +3661,11 @@ int main(int argc, const char **argv)
_("PBKDF forced iterations cannot be combined with iteration time option."), _("PBKDF forced iterations cannot be combined with iteration time option."),
poptGetInvocationName(popt_context)); poptGetInvocationName(popt_context));
if (ARG_SET(OPT_DISABLE_KEYRING_ID) && ARG_SET(OPT_LINK_VK_TO_KEYRING_ID))
usage(popt_context, EXIT_FAILURE,
_("Cannot link volume key to a keyring when keyring is disabled."),
poptGetInvocationName(popt_context));
if (ARG_SET(OPT_DEBUG_ID) || ARG_SET(OPT_DEBUG_JSON_ID)) { if (ARG_SET(OPT_DEBUG_ID) || ARG_SET(OPT_DEBUG_JSON_ID)) {
crypt_set_debug_level(ARG_SET(OPT_DEBUG_JSON_ID)? CRYPT_DEBUG_JSON : CRYPT_DEBUG_ALL); crypt_set_debug_level(ARG_SET(OPT_DEBUG_JSON_ID)? CRYPT_DEBUG_JSON : CRYPT_DEBUG_ALL);
dbg_version_and_cmd(argc, argv); dbg_version_and_cmd(argc, argv);

View File

@@ -111,6 +111,8 @@ ARG(OPT_KEYSLOT_KEY_SIZE, '\0', POPT_ARG_STRING, N_("LUKS2 keyslot: The size of
ARG(OPT_LABEL, '\0', POPT_ARG_STRING, N_("Set label for the LUKS2 device"), NULL, CRYPT_ARG_STRING, {}, OPT_LABEL_ACTIONS) ARG(OPT_LABEL, '\0', POPT_ARG_STRING, N_("Set label for the LUKS2 device"), NULL, CRYPT_ARG_STRING, {}, OPT_LABEL_ACTIONS)
ARG(OPT_LINK_VK_TO_KEYRING, '\0', POPT_ARG_STRING, N_("Set keyring where to link volume key"), NULL, CRYPT_ARG_INT32, {}, OPT_LINK_VK_TO_KEYRING_ACTIONS)
ARG(OPT_LUKS2_KEYSLOTS_SIZE, '\0', POPT_ARG_STRING, N_("LUKS2 header keyslots area size"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_LUKS2_KEYSLOTS_SIZE_ACTIONS) ARG(OPT_LUKS2_KEYSLOTS_SIZE, '\0', POPT_ARG_STRING, N_("LUKS2 header keyslots area size"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_LUKS2_KEYSLOTS_SIZE_ACTIONS)
ARG(OPT_LUKS2_METADATA_SIZE, '\0', POPT_ARG_STRING, N_("LUKS2 header metadata area size"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_LUKS2_METADATA_SIZE_ACTIONS) ARG(OPT_LUKS2_METADATA_SIZE, '\0', POPT_ARG_STRING, N_("LUKS2 header metadata area size"), N_("bytes"), CRYPT_ARG_UINT64, {}, OPT_LUKS2_METADATA_SIZE_ACTIONS)

View File

@@ -75,6 +75,7 @@
#define OPT_NEW_KEY_SLOT_ACTIONS { ADDKEY_ACTION } #define OPT_NEW_KEY_SLOT_ACTIONS { ADDKEY_ACTION }
#define OPT_NEW_TOKEN_ID_ACTIONS { ADDKEY_ACTION } #define OPT_NEW_TOKEN_ID_ACTIONS { ADDKEY_ACTION }
#define OPT_LABEL_ACTIONS { CONFIG_ACTION, FORMAT_ACTION, REENCRYPT_ACTION } #define OPT_LABEL_ACTIONS { CONFIG_ACTION, FORMAT_ACTION, REENCRYPT_ACTION }
#define OPT_LINK_VK_TO_KEYRING_ACTIONS { OPEN_ACTION, RESUME_ACTION }
#define OPT_LUKS2_KEYSLOTS_SIZE_ACTIONS { REENCRYPT_ACTION, FORMAT_ACTION } #define OPT_LUKS2_KEYSLOTS_SIZE_ACTIONS { REENCRYPT_ACTION, FORMAT_ACTION }
#define OPT_LUKS2_METADATA_SIZE_ACTIONS { REENCRYPT_ACTION, FORMAT_ACTION } #define OPT_LUKS2_METADATA_SIZE_ACTIONS { REENCRYPT_ACTION, FORMAT_ACTION }
#define OPT_OFFSET_ACTIONS { OPEN_ACTION, REENCRYPT_ACTION, FORMAT_ACTION } #define OPT_OFFSET_ACTIONS { OPEN_ACTION, REENCRYPT_ACTION, FORMAT_ACTION }

View File

@@ -105,6 +105,7 @@
#define OPT_NO_WIPE "no-wipe" #define OPT_NO_WIPE "no-wipe"
#define OPT_WIPE "wipe" #define OPT_WIPE "wipe"
#define OPT_LABEL "label" #define OPT_LABEL "label"
#define OPT_LINK_VK_TO_KEYRING "link-vk-to-keyring"
#define OPT_LUKS2_KEYSLOTS_SIZE "luks2-keyslots-size" #define OPT_LUKS2_KEYSLOTS_SIZE "luks2-keyslots-size"
#define OPT_LUKS2_METADATA_SIZE "luks2-metadata-size" #define OPT_LUKS2_METADATA_SIZE "luks2-metadata-size"
#define OPT_MASTER_KEY_FILE "master-key-file" #define OPT_MASTER_KEY_FILE "master-key-file"