mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-17 05:40:13 +01:00
Allow activation, resume and luksAddKey using VK stored in keyring.
Add --volume-key-keyring option, which takes a name of a key in keyring, which will be used as a VK during device activation. The key can be specified in keyctl-compatible syntax "%<key_type>:<key_name>".
This commit is contained in:
@@ -235,6 +235,17 @@ partially predictable volume key which will compromise security.
|
|||||||
endif::[]
|
endif::[]
|
||||||
endif::[]
|
endif::[]
|
||||||
|
|
||||||
|
ifdef::ACTION_OPEN,ACTION_LUKSRESUME,ACTION_LUKSADDKEY[]
|
||||||
|
*--volume-key-keyring* _<key description>_::
|
||||||
|
Use a volume key stored in a keyring.
|
||||||
|
This allows one to open _luks_ and device types without giving a passphrase.
|
||||||
|
The volume key has to be of user type, in order to validate the digest.
|
||||||
|
+
|
||||||
|
The _<key description>_ uses keyctl-compatible syntax. This can either be a
|
||||||
|
numeric key ID or a string name in the format _%<key type>:<key name>_. See
|
||||||
|
also *KEY IDENTIFIERS* section of *keyctl*(1).
|
||||||
|
endif::[]
|
||||||
|
|
||||||
ifdef::ACTION_LUKSDUMP[]
|
ifdef::ACTION_LUKSDUMP[]
|
||||||
*--dump-json-metadata*::
|
*--dump-json-metadata*::
|
||||||
For _luksDump_ (LUKS2 only) this option prints content of LUKS2 header
|
For _luksDump_ (LUKS2 only) this option prints content of LUKS2 header
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ cryptsetup-luksAddKey - add a new passphrase
|
|||||||
Adds a keyslot protected by a new passphrase. An existing passphrase
|
Adds a keyslot protected by a new passphrase. An existing passphrase
|
||||||
must be supplied interactively, via --key-file or LUKS2 token (plugin).
|
must be supplied interactively, via --key-file or LUKS2 token (plugin).
|
||||||
Alternatively to existing passphrase user may pass directly volume key
|
Alternatively to existing passphrase user may pass directly volume key
|
||||||
(via --volume-key-file). The new passphrase to be added can be specified
|
(via --volume-key-file or --volume-key-keyring). The new passphrase to be added
|
||||||
interactively, read from the file given as the positional argument (also
|
can be specified interactively, read from the file given as the positional
|
||||||
via --new-keyfile parameter) or via LUKS2 token.
|
argument (also via --new-keyfile parameter) or via LUKS2 token.
|
||||||
|
|
||||||
*NOTE:* with --unbound option the action creates new unbound LUKS2
|
*NOTE:* with --unbound option the action creates new unbound LUKS2
|
||||||
keyslot. The keyslot cannot be used for device activation. If you don't
|
keyslot. The keyslot cannot be used for device activation. If you don't
|
||||||
@@ -34,11 +34,11 @@ algorithm is always the same for all keyslots.
|
|||||||
|
|
||||||
*<options>* can be [--key-file, --keyfile-offset, --keyfile-size,
|
*<options>* can be [--key-file, --keyfile-offset, --keyfile-size,
|
||||||
--new-keyfile, --new-keyfile-offset, --new-keyfile-size, --key-slot,
|
--new-keyfile, --new-keyfile-offset, --new-keyfile-size, --key-slot,
|
||||||
--new-key-slot, --volume-key-file, --force-password, --hash, --header,
|
--new-key-slot, --volume-key-file, --volume-key-keyring, --force-password,
|
||||||
--disable-locks, --iter-time, --pbkdf, --pbkdf-force-iterations,
|
--hash, --header, --disable-locks, --iter-time, --pbkdf,
|
||||||
--pbkdf-memory, --pbkdf-parallel, --unbound, --type, --keyslot-cipher,
|
--pbkdf-force-iterations, --pbkdf-memory, --pbkdf-parallel, --unbound, --type,
|
||||||
--keyslot-key-size, --key-size, --timeout, --token-id, --token-type,
|
--keyslot-cipher, --keyslot-key-size, --key-size, --timeout, --token-id,
|
||||||
--token-only, --new-token-id, --verify-passphrase].
|
--token-type, --token-only, --new-token-id, --verify-passphrase].
|
||||||
|
|
||||||
include::man/common_options.adoc[]
|
include::man/common_options.adoc[]
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ interactively for a passphrase if no token is usable (LUKS2 only) or
|
|||||||
*<options>* can be [--key-file, --keyfile-size, --keyfile-offset,
|
*<options>* can be [--key-file, --keyfile-size, --keyfile-offset,
|
||||||
--key-slot, --header, --disable-keyring, --disable-locks, --token-id,
|
--key-slot, --header, --disable-keyring, --disable-locks, --token-id,
|
||||||
--token-only, --token-type, --disable-external-tokens, --type, --tries,
|
--token-only, --token-type, --disable-external-tokens, --type, --tries,
|
||||||
--timeout, --verify-passphrase].
|
--timeout, --verify-passphrase, --volume-key-keyring].
|
||||||
|
|
||||||
include::man/common_options.adoc[]
|
include::man/common_options.adoc[]
|
||||||
include::man/common_footer.adoc[]
|
include::man/common_footer.adoc[]
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ matching PIN protected token.
|
|||||||
--volume-key-file, --token-id, --token-only, --token-type,
|
--volume-key-file, --token-id, --token-only, --token-type,
|
||||||
--disable-external-tokens, --disable-keyring, --disable-locks, --type,
|
--disable-external-tokens, --disable-keyring, --disable-locks, --type,
|
||||||
--refresh, --serialize-memory-hard-pbkdf, --unbound, --tries, --timeout,
|
--refresh, --serialize-memory-hard-pbkdf, --unbound, --tries, --timeout,
|
||||||
--verify-passphrase, --persistent].
|
--verify-passphrase, --persistent, --volume-key-keyring].
|
||||||
|
|
||||||
=== loopAES
|
=== loopAES
|
||||||
*open --type loopaes <device> <name> --key-file <keyfile>* +
|
*open --type loopaes <device> <name> --key-file <keyfile>* +
|
||||||
|
|||||||
@@ -1616,6 +1616,7 @@ static int action_open_luks(void)
|
|||||||
char *password = NULL;
|
char *password = NULL;
|
||||||
size_t passwordLen;
|
size_t passwordLen;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
struct crypt_keyslot_context *kc = NULL;
|
||||||
|
|
||||||
if (ARG_SET(OPT_REFRESH_ID)) {
|
if (ARG_SET(OPT_REFRESH_ID)) {
|
||||||
activated_name = action_argc > 1 ? action_argv[1] : action_argv[0];
|
activated_name = action_argc > 1 ? action_argv[1] : action_argv[0];
|
||||||
@@ -1683,6 +1684,13 @@ static int action_open_luks(void)
|
|||||||
goto out;
|
goto out;
|
||||||
r = crypt_activate_by_volume_key(cd, activated_name,
|
r = crypt_activate_by_volume_key(cd, activated_name,
|
||||||
key, keysize, activate_flags);
|
key, keysize, activate_flags);
|
||||||
|
} else if (ARG_SET(OPT_VOLUME_KEY_KEYRING_ID)) {
|
||||||
|
r = crypt_keyslot_context_init_by_vk_in_keyring(cd, ARG_STR(OPT_VOLUME_KEY_KEYRING_ID), &kc);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
r = crypt_activate_by_keyslot_context(cd, activated_name, CRYPT_ANY_SLOT, kc, activate_flags);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
r = crypt_activate_by_token_pin(cd, activated_name, ARG_STR(OPT_TOKEN_TYPE_ID),
|
r = crypt_activate_by_token_pin(cd, activated_name, ARG_STR(OPT_TOKEN_TYPE_ID),
|
||||||
ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL, activate_flags);
|
ARG_INT32(OPT_TOKEN_ID_ID), NULL, 0, NULL, activate_flags);
|
||||||
@@ -1719,6 +1727,7 @@ out:
|
|||||||
(crypt_get_active_device(cd, activated_name, &cad) ||
|
(crypt_get_active_device(cd, activated_name, &cad) ||
|
||||||
crypt_persistent_flags_set(cd, CRYPT_FLAGS_ACTIVATION, cad.flags & activate_flags)))
|
crypt_persistent_flags_set(cd, CRYPT_FLAGS_ACTIVATION, cad.flags & activate_flags)))
|
||||||
log_err(_("Device activated but cannot make flags persistent."));
|
log_err(_("Device activated but cannot make flags persistent."));
|
||||||
|
crypt_keyslot_context_free(kc);
|
||||||
|
|
||||||
crypt_safe_free(key);
|
crypt_safe_free(key);
|
||||||
crypt_safe_free(password);
|
crypt_safe_free(password);
|
||||||
@@ -2082,6 +2091,8 @@ static int action_luksAddKey(void)
|
|||||||
ARG_UINT32(OPT_KEYFILE_SIZE_ID),
|
ARG_UINT32(OPT_KEYFILE_SIZE_ID),
|
||||||
ARG_UINT64(OPT_KEYFILE_OFFSET_ID),
|
ARG_UINT64(OPT_KEYFILE_OFFSET_ID),
|
||||||
&kc);
|
&kc);
|
||||||
|
else if (ARG_SET(OPT_VOLUME_KEY_KEYRING_ID))
|
||||||
|
r = crypt_keyslot_context_init_by_vk_in_keyring(cd, ARG_STR(OPT_VOLUME_KEY_KEYRING_ID), &kc);
|
||||||
else if (ARG_SET(OPT_TOKEN_ID_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) || ARG_SET(OPT_TOKEN_ONLY_ID)) {
|
else if (ARG_SET(OPT_TOKEN_ID_ID) || ARG_SET(OPT_TOKEN_TYPE_ID) || ARG_SET(OPT_TOKEN_ONLY_ID)) {
|
||||||
r = crypt_keyslot_context_init_by_token(cd,
|
r = crypt_keyslot_context_init_by_token(cd,
|
||||||
ARG_INT32(OPT_TOKEN_ID_ID),
|
ARG_INT32(OPT_TOKEN_ID_ID),
|
||||||
@@ -2516,6 +2527,7 @@ static int action_luksResume(void)
|
|||||||
int r, tries;
|
int r, tries;
|
||||||
struct crypt_active_device cad;
|
struct crypt_active_device cad;
|
||||||
const char *req_type = luksType(device_type);
|
const char *req_type = luksType(device_type);
|
||||||
|
struct crypt_keyslot_context *kc = NULL;
|
||||||
|
|
||||||
if (req_type && !isLUKS(req_type))
|
if (req_type && !isLUKS(req_type))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -2573,6 +2585,14 @@ static int action_luksResume(void)
|
|||||||
if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
|
if (r >= 0 || quit || ARG_SET(OPT_TOKEN_ONLY_ID))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
|
if (ARG_SET(OPT_VOLUME_KEY_KEYRING_ID)) {
|
||||||
|
r = crypt_keyslot_context_init_by_vk_in_keyring(cd, ARG_STR(OPT_VOLUME_KEY_KEYRING_ID), &kc);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
r = crypt_resume_by_keyslot_context(cd, action_argv[0], CRYPT_ANY_SLOT, kc);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
tries = set_tries_tty();
|
tries = set_tries_tty();
|
||||||
do {
|
do {
|
||||||
r = tools_get_key(NULL, &password, &passwordLen,
|
r = tools_get_key(NULL, &password, &passwordLen,
|
||||||
@@ -2591,6 +2611,7 @@ static int action_luksResume(void)
|
|||||||
password = NULL;
|
password = NULL;
|
||||||
} while ((r == -EPERM || r == -ERANGE) && (--tries > 0));
|
} while ((r == -EPERM || r == -ERANGE) && (--tries > 0));
|
||||||
out:
|
out:
|
||||||
|
crypt_keyslot_context_free(kc);
|
||||||
crypt_safe_free(password);
|
crypt_safe_free(password);
|
||||||
crypt_free(cd);
|
crypt_free(cd);
|
||||||
return r;
|
return r;
|
||||||
|
|||||||
@@ -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_FILE, '\0', POPT_ARG_STRING, N_("Use the volume key from file."), NULL, CRYPT_ARG_STRING, {}, {})
|
||||||
|
|
||||||
|
ARG(OPT_VOLUME_KEY_KEYRING, '\0', POPT_ARG_STRING, N_("Use the specified keyring key as a volume key."), 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_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_KEYFILE, '\0', POPT_ARG_STRING, N_("Read the key for a new slot from a file"), NULL, CRYPT_ARG_STRING, {}, OPT_NEW_KEYFILE_ACTIONS)
|
||||||
|
|||||||
@@ -110,6 +110,7 @@
|
|||||||
#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"
|
||||||
#define OPT_VOLUME_KEY_FILE "volume-key-file"
|
#define OPT_VOLUME_KEY_FILE "volume-key-file"
|
||||||
|
#define OPT_VOLUME_KEY_KEYRING "volume-key-keyring"
|
||||||
#define OPT_VOLUME_KEY_TYPE "volume-key-type"
|
#define OPT_VOLUME_KEY_TYPE "volume-key-type"
|
||||||
#define OPT_NEW "new"
|
#define OPT_NEW "new"
|
||||||
#define OPT_NEW_KEY_SLOT "new-key-slot"
|
#define OPT_NEW_KEY_SLOT "new-key-slot"
|
||||||
|
|||||||
@@ -304,6 +304,40 @@ test_vk_link() {
|
|||||||
keyctl unlink "%$KEY_TYPE:$1" "$2" || fail
|
keyctl unlink "%$KEY_TYPE:$1" "$2" || fail
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# $1 key name
|
||||||
|
# $2 keyring to link VK to
|
||||||
|
# $3 key type (optional)
|
||||||
|
test_vk_link_and_reactivate() {
|
||||||
|
KEY_TYPE=${3:-logon}
|
||||||
|
KEY_TYPE_ARG=""
|
||||||
|
if [ ! -z "$3" ]; then
|
||||||
|
KEY_TYPE_ARG="--volume-key-type $3"
|
||||||
|
fi
|
||||||
|
|
||||||
|
LINKED_KEY_NAME="%$KEY_TYPE:$1"
|
||||||
|
|
||||||
|
echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring "$2" $KEY_TYPE_ARG || fail
|
||||||
|
keyctl search "$2" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after activation."
|
||||||
|
$CRYPTSETUP close $DEV_NAME || fail
|
||||||
|
keyctl search "$2" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after deactivation."
|
||||||
|
$CRYPTSETUP open $LOOPDEV $DEV_NAME --volume-key-keyring $LINKED_KEY_NAME || fail "Failed to unlock volume via a VK in keyring."
|
||||||
|
$CRYPTSETUP luksSuspend $DEV_NAME || fail "Failed to suspend device."
|
||||||
|
$CRYPTSETUP luksResume $DEV_NAME --volume-key-keyring $LINKED_KEY_NAME || fail "Failed to resume via a VK in keyring."
|
||||||
|
|
||||||
|
echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase 2>/dev/null || fail
|
||||||
|
echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase 2>/dev/null && fail
|
||||||
|
echo $PWD2 | $CRYPTSETUP luksAddKey $FAST_PBKDF2 --volume-key-keyring $LINKED_KEY_NAME $LOOPDEV --new-key-slot 1 || fail "Failed to add passphrase by VK in keyring."
|
||||||
|
echo $PWD2 | $CRYPTSETUP luksOpen $LOOPDEV --test-passphrase 2>/dev/null || fail
|
||||||
|
$CRYPTSETUP luksKillSlot -q $LOOPDEV 1 2>/dev/null || fail
|
||||||
|
|
||||||
|
$CRYPTSETUP close $DEV_NAME || fail
|
||||||
|
# zero-out the key in keyring
|
||||||
|
keyctl pipe $LINKED_KEY_NAME | tr -c '\0' '\0' | keyctl pupdate $LINKED_KEY_NAME
|
||||||
|
$CRYPTSETUP open $LOOPDEV $DEV_NAME --volume-key-keyring $LINKED_KEY_NAME > /dev/null 2>&1 && fail "Unlocked volume via a bad VK in keyring."
|
||||||
|
keyctl search "$2" $KEY_TYPE $1 > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after bad activation."
|
||||||
|
keyctl unlink "%$KEY_TYPE:$1" "$2" || fail
|
||||||
|
}
|
||||||
|
|
||||||
export LANG=C
|
export LANG=C
|
||||||
|
|
||||||
[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
|
[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
|
||||||
@@ -1244,7 +1278,6 @@ if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then
|
|||||||
KID=$(echo -n test | keyctl padd user my_token @us)
|
KID=$(echo -n test | keyctl padd user my_token @us)
|
||||||
keyctl unlink $KID >/dev/null 2>&1 @us && USER_SESSION_KEYRING_WORKS=1
|
keyctl unlink $KID >/dev/null 2>&1 @us && USER_SESSION_KEYRING_WORKS=1
|
||||||
|
|
||||||
|
|
||||||
test_vk_link $KEY_NAME "@u"
|
test_vk_link $KEY_NAME "@u"
|
||||||
test_vk_link $KEY_NAME "@u" "user"
|
test_vk_link $KEY_NAME "@u" "user"
|
||||||
[[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_vk_link $KEY_NAME "@s"
|
[[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_vk_link $KEY_NAME "@s"
|
||||||
@@ -1256,6 +1289,13 @@ if [ $HAVE_KEYRING -gt 0 -a -d /proc/sys/kernel/keys ]; then
|
|||||||
# explicitly specify keyring key type
|
# explicitly specify keyring key type
|
||||||
test_vk_link $KEY_NAME "%keyring:$TEST_KEYRING_NAME"
|
test_vk_link $KEY_NAME "%keyring:$TEST_KEYRING_NAME"
|
||||||
|
|
||||||
|
test_vk_link_and_reactivate $KEY_NAME "@u" "user"
|
||||||
|
[[ ! -z "$SESSION_KEYRING_WORKS" ]] && test_vk_link_and_reactivate $KEY_NAME "@s" "user"
|
||||||
|
[[ ! -z "$USER_SESSION_KEYRING_WORKS" ]] && test_vk_link_and_reactivate $KEY_NAME "@us" "user"
|
||||||
|
test_vk_link_and_reactivate $KEY_NAME "%:$TEST_KEYRING_NAME" "user"
|
||||||
|
# explicitly specify keyring key type
|
||||||
|
test_vk_link_and_reactivate $KEY_NAME "%keyring:$TEST_KEYRING_NAME" "user"
|
||||||
|
|
||||||
# test numeric keyring name -5 is user session (@us) keyring
|
# test numeric keyring name -5 is user session (@us) keyring
|
||||||
echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring -5 --volume-key-type logon || fail
|
echo $PWD1 | $CRYPTSETUP open $LOOPDEV $DEV_NAME --link-vk-to-keyring -5 --volume-key-type logon || fail
|
||||||
keyctl search @us logon $KEY_NAME > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after activation."
|
keyctl search @us logon $KEY_NAME > /dev/null 2>&1 || fail "VK is not linked to the specified keyring after activation."
|
||||||
|
|||||||
Reference in New Issue
Block a user