From 610c7858d6bd3d1837f93a5d3b86ecb0756e4160 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Thu, 8 Mar 2018 15:45:36 -0800 Subject: [PATCH] Add explicit key conversion command Add support for converting a keyslot from one pbkdf to another without opening the device. --- man/cryptsetup.8 | 24 ++++++++++++++++++++++++ src/cryptsetup.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/man/cryptsetup.8 b/man/cryptsetup.8 index f5b31f99..d9755e31 100644 --- a/man/cryptsetup.8 +++ b/man/cryptsetup.8 @@ -323,6 +323,30 @@ inaccessible. \-\-new\-keyfile\-size, \-\-key\-slot, \-\-force\-password, \-\-header, \-\-disable\-locks]. .PP +.PP +\fIluksConvertKey\fR +.IP +Converts an existing LUKS2 keyslot to new pbkdf parameters. The +passphrase for keyslot to be converted must be supplied interactively +or via \-\-key\-file. If no \-\-pbkdf parameters are specified LUKS2 +default pbkdf values will apply. + +If a keyslot is specified (via \-\-key\-slot), the passphrase for that +keyslot must be given. If no keyslot is specified and there is still +a free keyslot, then the new parameters will be put into a free +keyslot before the keyslot containing the old parameters is +purged. If there is no free keyslot, then the keyslot with the old +parameters is overwritten directly. + +\fBWARNING:\fR If a keyslot is overwritten, a media failure during +this operation can cause the overwrite to fail after the old +parameters have been wiped and make the LUKS container inaccessible. + +\fB\fR can be [\-\-key\-file, \-\-keyfile\-offset, +\-\-keyfile\-size, \-\-key\-slot, \-\-header, \-\-disable\-locks, +\-\-iter-time, \-\-pbkdf, \-\-pbkdf\-force\-iterations, +\-\-pbkdf\-memory, \-\-pbkdf\-parallel]. +.PP \fIluksKillSlot\fR .IP Wipe the key-slot number from the LUKS device. Except running diff --git a/src/cryptsetup.c b/src/cryptsetup.c index 1277b629..aa8a7ae6 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -1443,6 +1443,40 @@ out: return r; } +static int action_luksConvertKey(void) +{ + struct crypt_device *cd = NULL; + char *password = NULL; + size_t password_size = 0; + int r; + + if ((r = crypt_init(&cd, uuid_or_device_header(NULL)))) + goto out; + + if ((r = crypt_load(cd, CRYPT_LUKS2, NULL))) + goto out; + + r = set_pbkdf_params(cd, crypt_get_type(cd)); + if (r) { + log_err(_("Failed to set pbkdf parameters.\n")); + goto out; + } + + r = tools_get_key(_("Enter passphrase for keylot to be converted: "), + &password, &password_size, + opt_keyfile_offset, opt_keyfile_size, opt_key_file, + opt_timeout, _verify_passphrase(0), 0, cd); + if (r < 0) + goto out; + + r = crypt_keyslot_change_by_passphrase(cd, opt_key_slot, opt_key_slot, + password, password_size, password, password_size); +out: + crypt_safe_free(password); + crypt_free(cd); + return r; +} + static int action_isLuks(void) { struct crypt_device *cd = NULL; @@ -1927,6 +1961,7 @@ static struct action_type { { "luksAddKey", action_luksAddKey, 1, 1, N_(" []"), N_("add key to LUKS device") }, { "luksRemoveKey",action_luksRemoveKey,1, 1, N_(" []"), N_("removes supplied key or key file from LUKS device") }, { "luksChangeKey",action_luksChangeKey,1, 1, N_(" []"), N_("changes supplied key or key file of LUKS device") }, + { "luksConvertKey",action_luksConvertKey,1, 1, N_(" []"), N_("converts a key to new pbkdf parameters") }, { "luksKillSlot", action_luksKillSlot, 2, 1, N_(" "), N_("wipes key with number from LUKS device") }, { "luksUUID", action_luksUUID, 1, 0, N_(""), N_("print UUID of LUKS device") }, { "isLuks", action_isLuks, 1, 0, N_(""), N_("tests for LUKS partition header") },