mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-15 12:50:06 +01:00
Move change key into library (add crypt_keyslot_change_by_passphrase).
This change is useful mainly in FIPS mode, where we cannot extract volume key directly from libcryptsetup.
This commit is contained in:
3
TODO
3
TODO
@@ -1,7 +1,4 @@
|
|||||||
Version 1.6.0:
|
Version 1.6.0:
|
||||||
- Export wipe device functions
|
- Export wipe device functions
|
||||||
- Support K/M suffixes for align payload (new switch?).
|
- Support K/M suffixes for align payload (new switch?).
|
||||||
- FIPS: move changekey to library
|
|
||||||
- online reencryption api?
|
|
||||||
- integrate more metadata formats
|
|
||||||
- TRIM for keyslots
|
- TRIM for keyslots
|
||||||
|
|||||||
@@ -598,6 +598,33 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
|
|||||||
const char *new_passphrase,
|
const char *new_passphrase,
|
||||||
size_t new_passphrase_size);
|
size_t new_passphrase_size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change defined key slot using provided passphrase
|
||||||
|
*
|
||||||
|
* @pre @e cd contains initialized and formatted LUKS device context
|
||||||
|
*
|
||||||
|
* @param cd crypt device handle
|
||||||
|
* @param keyslot_old old keyslot or @e CRYPT_ANY_SLOT
|
||||||
|
* @param keyslot_new new keyslot (can be the same as old)
|
||||||
|
* @param passphrase passphrase used to unlock volume key, @e NULL for query
|
||||||
|
* @param passphrase_size size of passphrase (binary data)
|
||||||
|
* @param new_passphrase passphrase for new keyslot, @e NULL for query
|
||||||
|
* @param new_passphrase_size size of @e new_passphrase (binary data)
|
||||||
|
*
|
||||||
|
* @return allocated key slot number or negative errno otherwise.
|
||||||
|
*
|
||||||
|
* @note This function is just internal implementation of luksChange
|
||||||
|
* command to avoid reading of volume key outside libcryptsetup boundary
|
||||||
|
* in FIPS mode.
|
||||||
|
*/
|
||||||
|
int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
|
||||||
|
int keyslot_old,
|
||||||
|
int keyslot_new,
|
||||||
|
const char *passphrase,
|
||||||
|
size_t passphrase_size,
|
||||||
|
const char *new_passphrase,
|
||||||
|
size_t new_passphrase_size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add key slot using provided key file path
|
* Add key slot using provided key file path
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ CRYPTSETUP_1.0 {
|
|||||||
crypt_free;
|
crypt_free;
|
||||||
|
|
||||||
crypt_keyslot_add_by_passphrase;
|
crypt_keyslot_add_by_passphrase;
|
||||||
|
crypt_keyslot_change_by_passphrase;
|
||||||
crypt_keyslot_add_by_keyfile;
|
crypt_keyslot_add_by_keyfile;
|
||||||
crypt_keyslot_add_by_keyfile_offset;
|
crypt_keyslot_add_by_keyfile_offset;
|
||||||
crypt_keyslot_add_by_volume_key;
|
crypt_keyslot_add_by_volume_key;
|
||||||
|
|||||||
61
lib/setup.c
61
lib/setup.c
@@ -1649,6 +1649,67 @@ out:
|
|||||||
return r ?: keyslot;
|
return r ?: keyslot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int crypt_keyslot_change_by_passphrase(struct crypt_device *cd,
|
||||||
|
int keyslot_old,
|
||||||
|
int keyslot_new,
|
||||||
|
const char *passphrase,
|
||||||
|
size_t passphrase_size,
|
||||||
|
const char *new_passphrase,
|
||||||
|
size_t new_passphrase_size)
|
||||||
|
{
|
||||||
|
struct volume_key *vk = NULL;
|
||||||
|
int r = -EINVAL;
|
||||||
|
|
||||||
|
log_dbg("Changing passphrase from old keyslot %d to new %d.",
|
||||||
|
keyslot_old, keyslot_new);
|
||||||
|
|
||||||
|
if (!isLUKS(cd->type)) {
|
||||||
|
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = LUKS_open_key_with_hdr(keyslot_old, passphrase, passphrase_size,
|
||||||
|
&cd->u.luks1.hdr, &vk, cd);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
if (keyslot_old != CRYPT_ANY_SLOT && keyslot_old != r) {
|
||||||
|
log_dbg("Keyslot mismatch.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
keyslot_old = r;
|
||||||
|
|
||||||
|
if (keyslot_new == CRYPT_ANY_SLOT) {
|
||||||
|
keyslot_new = LUKS_keyslot_find_empty(&cd->u.luks1.hdr);
|
||||||
|
if (keyslot_new < 0)
|
||||||
|
keyslot_new = keyslot_old;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyslot_old == keyslot_new) {
|
||||||
|
log_dbg("Key slot %d is going to be overwritten.", keyslot_old);
|
||||||
|
(void)crypt_keyslot_destroy(cd, keyslot_old);
|
||||||
|
}
|
||||||
|
|
||||||
|
r = LUKS_set_key(keyslot_new, new_passphrase, new_passphrase_size,
|
||||||
|
&cd->u.luks1.hdr, vk, cd->iteration_time,
|
||||||
|
&cd->u.luks1.PBKDF2_per_sec, cd);
|
||||||
|
|
||||||
|
if (keyslot_old == keyslot_new) {
|
||||||
|
if (r >= 0)
|
||||||
|
log_verbose(cd, _("Key slot %d changed.\n"), r);
|
||||||
|
} else {
|
||||||
|
if (r >= 0) {
|
||||||
|
log_verbose(cd, _("Replaced with key slot %d.\n"), r);
|
||||||
|
r = crypt_keyslot_destroy(cd, keyslot_old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (r < 0)
|
||||||
|
log_err(cd, _("Failed to swap new key slot.\n"));
|
||||||
|
out:
|
||||||
|
crypt_free_volume_key(vk);
|
||||||
|
return r ?: keyslot_new;
|
||||||
|
}
|
||||||
|
|
||||||
int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd,
|
int crypt_keyslot_add_by_keyfile_offset(struct crypt_device *cd,
|
||||||
int keyslot,
|
int keyslot,
|
||||||
const char *keyfile,
|
const char *keyfile,
|
||||||
|
|||||||
@@ -909,24 +909,13 @@ 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(void)
|
static int action_luksChangeKey(void)
|
||||||
{
|
{
|
||||||
const char *opt_new_key_file = (action_argc > 1 ? action_argv[1] : NULL);
|
const char *opt_new_key_file = (action_argc > 1 ? action_argv[1] : NULL);
|
||||||
struct crypt_device *cd = NULL;
|
struct crypt_device *cd = NULL;
|
||||||
char *vk = NULL, *password = NULL;
|
char *password = NULL, *password_new = NULL;
|
||||||
size_t passwordLen = 0;
|
size_t password_size = 0, password_new_size = 0;
|
||||||
size_t vk_size;
|
int r;
|
||||||
int new_key_slot, old_key_slot, r;
|
|
||||||
|
|
||||||
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
if ((r = crypt_init(&cd, uuid_or_device(action_argv[0]))))
|
||||||
goto out;
|
goto out;
|
||||||
@@ -938,71 +927,31 @@ static int action_luksChangeKey(void)
|
|||||||
crypt_set_iteration_time(cd, opt_iteration_time);
|
crypt_set_iteration_time(cd, opt_iteration_time);
|
||||||
|
|
||||||
r = crypt_get_key(_("Enter LUKS passphrase to be changed: "),
|
r = crypt_get_key(_("Enter LUKS passphrase to be changed: "),
|
||||||
&password, &passwordLen,
|
&password, &password_size,
|
||||||
opt_keyfile_offset, opt_keyfile_size, opt_key_file,
|
opt_keyfile_offset, opt_keyfile_size, opt_key_file,
|
||||||
opt_timeout, _verify_passphrase(0), cd);
|
opt_timeout, _verify_passphrase(0), cd);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
vk_size = crypt_get_volume_key_size(cd);
|
/* Check password before asking for new one */
|
||||||
vk = crypt_safe_alloc(vk_size);
|
r = crypt_activate_by_passphrase(cd, NULL, opt_key_slot,
|
||||||
if (!vk) {
|
password, password_size, 0);
|
||||||
r = -ENOMEM;
|
if (r < 0)
|
||||||
goto out;
|
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: "),
|
r = crypt_get_key(_("Enter new LUKS passphrase: "),
|
||||||
&password, &passwordLen,
|
&password_new, &password_new_size,
|
||||||
opt_new_keyfile_offset, opt_new_keyfile_size,
|
opt_new_keyfile_offset, opt_new_keyfile_size,
|
||||||
opt_new_key_file,
|
opt_new_key_file,
|
||||||
opt_timeout, _verify_passphrase(0), cd);
|
opt_timeout, _verify_passphrase(0), cd);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if (new_key_slot == old_key_slot) {
|
r = crypt_keyslot_change_by_passphrase(cd, opt_key_slot, opt_key_slot,
|
||||||
(void)crypt_keyslot_destroy(cd, old_key_slot);
|
password, password_size, password_new, password_new_size);
|
||||||
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:
|
out:
|
||||||
crypt_safe_free(vk);
|
|
||||||
crypt_safe_free(password);
|
crypt_safe_free(password);
|
||||||
|
crypt_safe_free(password_new);
|
||||||
crypt_free(cd);
|
crypt_free(cd);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user