Add luksChangeKey command.

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@450 36d66b0a-2a48-0410-832c-cd162a569da5
This commit is contained in:
Milan Broz
2011-03-13 18:06:15 +00:00
parent b7498adc1c
commit e1cc40df7e
5 changed files with 155 additions and 2 deletions

View File

@@ -1,6 +1,7 @@
2011-04-11 Milan Broz <mbroz@redhat.com> 2011-04-11 Milan Broz <mbroz@redhat.com>
* Add loop manipulation code and support mapping of images in file. * Add loop manipulation code and support mapping of images in file.
* Add backing device loop info into status message. * Add backing device loop info into status message.
* Add luksChangeKey command.
2011-04-05 Milan Broz <mbroz@redhat.com> 2011-04-05 Milan Broz <mbroz@redhat.com>
* Add exception to COPYING for binary distribution linked with OpenSSL library. * Add exception to COPYING for binary distribution linked with OpenSSL library.

View File

@@ -46,6 +46,21 @@ static inline int round_up_modulo(int x, int m) {
return div_round_up(x, m) * m; return div_round_up(x, m) * m;
} }
const char *dbg_slot_state(crypt_keyslot_info ki)
{
switch(ki) {
case CRYPT_SLOT_INACTIVE:
return "INACTIVE";
case CRYPT_SLOT_ACTIVE:
return "ACTIVE";
case CRYPT_SLOT_ACTIVE_LAST:
return "ACTIVE_LAST";
case CRYPT_SLOT_INVALID:
default:
return "INVALID";
}
}
int LUKS_hdr_backup( int LUKS_hdr_backup(
const char *backup_file, const char *backup_file,
const char *device, const char *device,
@@ -629,7 +644,8 @@ static int LUKS_open_key(const char *device,
size_t AFEKSize; size_t AFEKSize;
int r; int r;
log_dbg("Trying to open key slot %d [%d].", keyIndex, (int)ki); log_dbg("Trying to open key slot %d [%s].", keyIndex,
dbg_slot_state(ki));
if (ki < CRYPT_SLOT_ACTIVE) if (ki < CRYPT_SLOT_ACTIVE)
return -ENOENT; return -ENOENT;

View File

@@ -82,6 +82,20 @@ The key file with the new material is supplied as a positional argument.
.IP .IP
remove supplied key or key file from LUKS device remove supplied key or key file from LUKS device
.PP .PP
\fIluksChangeKey\fR <device> [<new key file>]
.IP
change existing key file or passphrase. An existing passphrase or key file (via \-\-key-file) must be supplied.
The key file with the new material is supplied as a positional argument.
If no key slot is specified (and there is still free key slot on device) new slot is allocated before the old is purged.
If \fB\-\-key\-slot\fR option is specified (or there is no free slot) command will overwrite existing slot.
\fBWARNING:\fR Be sure you have another slot active or header backup when using explicit key slot (so you can
unlock the device even after possible media failure during slot swap).
\fB<options>\fR can be [\-\-key-file, \-\-keyfile-size, \-\-new-keyfile-size, \-\-key-slot].
.PP
\fIluksKillSlot\fR <device> <key slot number> \fIluksKillSlot\fR <device> <key slot number>
.IP .IP
wipe key with number <key slot> from LUKS device. A remaining passphrase or wipe key with number <key slot> from LUKS device. A remaining passphrase or
@@ -258,6 +272,7 @@ set up a read-only mapping.
.TP .TP
.B "\-\-iter-time, \-i" .B "\-\-iter-time, \-i"
The number of milliseconds to spend with PBKDF2 password processing. This option is only relevant to the LUKS operations as \fIluksFormat\fR or \fIluksAddKey\fR. The number of milliseconds to spend with PBKDF2 password processing. This option is only relevant to the LUKS operations as \fIluksFormat\fR or \fIluksAddKey\fR.
Note that 0 means default.
.TP .TP
.B "\-\-batch-mode, \-q" .B "\-\-batch-mode, \-q"
Do not ask for confirmation. Use with care! This option is only relevant for \fIluksFormat\fR, \fIluksAddKey\fR, \fIluksRemoveKey\fR or \fIluksKillSlot\fR. Do not ask for confirmation. Use with care! This option is only relevant for \fIluksFormat\fR, \fIluksAddKey\fR, \fIluksRemoveKey\fR or \fIluksKillSlot\fR.
@@ -341,7 +356,7 @@ Copyright \(co 2004 Christophe Saout
.br .br
Copyright \(co 2004-2006 Clemens Fruhwirth Copyright \(co 2004-2006 Clemens Fruhwirth
.br .br
Copyright \(co 2009-2010 Red Hat, Inc. Copyright \(co 2009-2011 Red Hat, Inc.
This is free software; see the source for copying conditions. There is NO This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

View File

@@ -55,6 +55,7 @@ static int action_luksOpen(int arg);
static int action_luksAddKey(int arg); static int action_luksAddKey(int arg);
static int action_luksKillSlot(int arg); static int action_luksKillSlot(int arg);
static int action_luksRemoveKey(int arg); static int action_luksRemoveKey(int arg);
static int action_luksChangeKey(int arg);
static int action_isLuks(int arg); static int action_isLuks(int arg);
static int action_luksUUID(int arg); static int action_luksUUID(int arg);
static int action_luksDump(int arg); static int action_luksDump(int arg);
@@ -81,6 +82,7 @@ static struct action_type {
{ "luksOpen", action_luksOpen, 0, 2, 1, N_("<device> <name> "), N_("open LUKS device as mapping <name>") }, { "luksOpen", action_luksOpen, 0, 2, 1, N_("<device> <name> "), N_("open LUKS device as mapping <name>") },
{ "luksAddKey", action_luksAddKey, 0, 1, 1, N_("<device> [<new key file>]"), N_("add key to LUKS device") }, { "luksAddKey", action_luksAddKey, 0, 1, 1, N_("<device> [<new key file>]"), N_("add key to LUKS device") },
{ "luksRemoveKey",action_luksRemoveKey, 0, 1, 1, N_("<device> [<key file>]"), N_("removes supplied key or key file from LUKS device") }, { "luksRemoveKey",action_luksRemoveKey, 0, 1, 1, N_("<device> [<key file>]"), N_("removes supplied key or key file from LUKS device") },
{ "luksChangeKey",action_luksChangeKey, 0, 1, 1, N_("<device> [<key file>]"), N_("changes supplied key or key file of LUKS device") },
{ "luksKillSlot", action_luksKillSlot, 0, 2, 1, N_("<device> <key slot>"), N_("wipes key with number <key slot> from LUKS device") }, { "luksKillSlot", action_luksKillSlot, 0, 2, 1, N_("<device> <key slot>"), N_("wipes key with number <key slot> from LUKS device") },
{ "luksUUID", action_luksUUID, 0, 1, 0, N_("<device>"), N_("print UUID of LUKS device") }, { "luksUUID", action_luksUUID, 0, 1, 0, N_("<device>"), N_("print UUID of LUKS device") },
{ "isLuks", action_isLuks, 0, 1, 0, N_("<device>"), N_("tests <device> for LUKS partition header") }, { "isLuks", action_isLuks, 0, 1, 0, N_("<device>"), N_("tests <device> for LUKS partition header") },
@@ -671,6 +673,100 @@ out:
return r; return r;
} }
static int _slots_full(struct crypt_device *cd)
{
int i;
for (i = 0; i < crypt_keyslot_max(crypt_get_type(cd)); i++)
if (crypt_keyslot_status(cd, i) == CRYPT_SLOT_INACTIVE)
return 0;
return 1;
}
static int action_luksChangeKey(int arg)
{
const char *opt_new_key_file = (action_argc > 1 ? action_argv[1] : NULL);
struct crypt_device *cd = NULL;
char *vk = NULL, *password = NULL;
unsigned int passwordLen = 0;
size_t vk_size;
int new_key_slot, old_key_slot, r;
if ((r = crypt_init(&cd, action_argv[0])))
goto out;
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
goto out;
r = crypt_get_key(_("Enter LUKS passphrase to be changed: "),
&password, &passwordLen,
opt_keyfile_size, opt_key_file, opt_timeout,
opt_batch_mode ? 0 : opt_verify_passphrase, cd);
if (r < 0)
goto out;
vk_size = crypt_get_volume_key_size(cd);
vk = crypt_safe_alloc(vk_size);
if (!vk) {
r = -ENOMEM;
goto out;
}
r = crypt_volume_key_get(cd, opt_key_slot, vk, &vk_size,
password, passwordLen);
if (r < 0) {
if (opt_key_slot != CRYPT_ANY_SLOT)
log_err(_("No key available with this passphrase.\n"));
goto out;
}
if (opt_key_slot != CRYPT_ANY_SLOT || _slots_full(cd)) {
log_dbg("Key slot %d is going to be overwritten (%s).",
r, opt_key_slot != CRYPT_ANY_SLOT ?
"explicit key slot specified" : "no free key slot");
old_key_slot = r;
new_key_slot = r;
} else {
log_dbg("Allocating new key slot.");
old_key_slot = r;
new_key_slot = CRYPT_ANY_SLOT;
}
crypt_safe_free(password);
password = NULL;
passwordLen = 0;
r = crypt_get_key(_("Enter new LUKS passphrase: "),
&password, &passwordLen,
opt_new_keyfile_size, opt_new_key_file,
opt_timeout, opt_batch_mode ? 0 : 1, cd);
if (r < 0)
goto out;
if (new_key_slot == old_key_slot) {
(void)crypt_keyslot_destroy(cd, old_key_slot);
r = crypt_keyslot_add_by_volume_key(cd, new_key_slot,
vk, vk_size,
password, passwordLen);
if (r >= 0)
log_verbose(_("Key slot %d changed.\n"), r);
} else {
r = crypt_keyslot_add_by_volume_key(cd, CRYPT_ANY_SLOT,
vk, vk_size,
password, passwordLen);
if (r >= 0) {
log_verbose(_("Replaced with key slot %d.\n"), r);
r = crypt_keyslot_destroy(cd, old_key_slot);
}
}
if (r < 0)
log_err(_("Failed to swap new key slot.\n"));
out:
crypt_safe_free(vk);
crypt_safe_free(password);
crypt_free(cd);
return r;
}
static int action_isLuks(int arg) static int action_isLuks(int arg)
{ {
struct crypt_device *cd = NULL; struct crypt_device *cd = NULL;

View File

@@ -300,5 +300,30 @@ dmsetup resume $DEV_NAME || fail
$CRYPTSETUP -q luksClose $DEV_NAME2 || fail $CRYPTSETUP -q luksClose $DEV_NAME2 || fail
dmsetup remove $DEV_NAME || fail dmsetup remove $DEV_NAME || fail
prepare "[23] ChangeKey passphrase and keyfile" wipe
# [0]$KEY1 [1]key0
$CRYPTSETUP -q luksFormat $LOOPDEV $KEY1 --key-slot 0 || fail
echo "key0" | $CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 --key-slot 1 || fail
# keyfile [0] / keyfile [0]
$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY1 $KEY2 --key-slot 0 || fail
# passphrase [1] / passphrase [1]
echo -e "key0\nkey1\n" | $CRYPTSETUP luksChangeKey $LOOPDEV --key-slot 1 || fail
# keyfile [0] / keyfile [new]
$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY2 $KEY1 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 0: DISABLED" || fail
# passphrase [1] / passphrase [new]
echo -e "key1\nkey0\n" | $CRYPTSETUP luksChangeKey $LOOPDEV || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: DISABLED" || fail
# use all slots
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 -i 1 || fail
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 -i 1 || fail
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 -i 1 || fail
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 -i 1 || fail
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 -i 1 || fail
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 -i 1 || fail
# still allows replace
$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY1 $KEY2 || fail
$CRYPTSETUP luksChangeKey $LOOPDEV -d $KEY1 $KEY2 2>/dev/null && fail
remove_mapping remove_mapping
exit 0 exit 0