mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-16 21:29:59 +01:00
Add --keep-key to cryptsetup-reencrypt.
This allows change of LUKS header hash (and iteration count) without the need to reencrypt the whole data area.
This commit is contained in:
@@ -67,6 +67,9 @@ you can destructively shrink device with \-\-reduce-device-size option.
|
|||||||
.TP
|
.TP
|
||||||
.B "\-\-hash, \-h \fI<hash-spec>\fR"
|
.B "\-\-hash, \-h \fI<hash-spec>\fR"
|
||||||
Specifies the hash used in the LUKS key setup scheme and volume key digest.
|
Specifies the hash used in the LUKS key setup scheme and volume key digest.
|
||||||
|
|
||||||
|
NOTE: if this parameter is not specified, default hash algorithm is always used
|
||||||
|
for new device header.
|
||||||
.TP
|
.TP
|
||||||
.B "\-\-iter-time, \-i \fI<milliseconds>\fR"
|
.B "\-\-iter-time, \-i \fI<milliseconds>\fR"
|
||||||
The number of milliseconds to spend with PBKDF2 passphrase processing for the
|
The number of milliseconds to spend with PBKDF2 passphrase processing for the
|
||||||
@@ -100,6 +103,12 @@ Read a maximum of \fIvalue\fR bytes from the key file.
|
|||||||
Default is to read the whole file up to the compiled-in
|
Default is to read the whole file up to the compiled-in
|
||||||
maximum.
|
maximum.
|
||||||
.TP
|
.TP
|
||||||
|
.B "\-\-keep-key"
|
||||||
|
Do not change encryption key, just reencrypt the LUKS header and keyslots.
|
||||||
|
|
||||||
|
This option can be combined only with \fI\-\-hash\fR or \fI\-\-iter-time\fR
|
||||||
|
options.
|
||||||
|
.TP
|
||||||
.B "\-\-tries, \-T"
|
.B "\-\-tries, \-T"
|
||||||
Number of retries for invalid passphrase entry.
|
Number of retries for invalid passphrase entry.
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ static int opt_tries = 3;
|
|||||||
static int opt_key_slot = CRYPT_ANY_SLOT;
|
static int opt_key_slot = CRYPT_ANY_SLOT;
|
||||||
static int opt_key_size = 0;
|
static int opt_key_size = 0;
|
||||||
static int opt_new = 0;
|
static int opt_new = 0;
|
||||||
|
static int opt_keep_key = 0;
|
||||||
|
|
||||||
static const char *opt_reduce_size_str = NULL;
|
static const char *opt_reduce_size_str = NULL;
|
||||||
static uint64_t opt_reduce_size = 0;
|
static uint64_t opt_reduce_size = 0;
|
||||||
@@ -424,7 +425,8 @@ out:
|
|||||||
|
|
||||||
static int create_new_header(struct reenc_ctx *rc, const char *cipher,
|
static int create_new_header(struct reenc_ctx *rc, const char *cipher,
|
||||||
const char *cipher_mode, const char *uuid,
|
const char *cipher_mode, const char *uuid,
|
||||||
int key_size, struct crypt_params_luks1 *params)
|
const char *key, int key_size,
|
||||||
|
struct crypt_params_luks1 *params)
|
||||||
{
|
{
|
||||||
struct crypt_device *cd_new = NULL;
|
struct crypt_device *cd_new = NULL;
|
||||||
int i, r;
|
int i, r;
|
||||||
@@ -441,7 +443,7 @@ static int create_new_header(struct reenc_ctx *rc, const char *cipher,
|
|||||||
crypt_set_iteration_time(cd_new, opt_iteration_time);
|
crypt_set_iteration_time(cd_new, opt_iteration_time);
|
||||||
|
|
||||||
if ((r = crypt_format(cd_new, CRYPT_LUKS1, cipher, cipher_mode,
|
if ((r = crypt_format(cd_new, CRYPT_LUKS1, cipher, cipher_mode,
|
||||||
uuid, NULL, key_size, params)))
|
uuid, key, key_size, params)))
|
||||||
goto out;
|
goto out;
|
||||||
log_verbose(_("New LUKS header for device %s created.\n"), rc->device);
|
log_verbose(_("New LUKS header for device %s created.\n"), rc->device);
|
||||||
|
|
||||||
@@ -464,6 +466,8 @@ static int backup_luks_headers(struct reenc_ctx *rc)
|
|||||||
struct crypt_device *cd = NULL;
|
struct crypt_device *cd = NULL;
|
||||||
struct crypt_params_luks1 params = {0};
|
struct crypt_params_luks1 params = {0};
|
||||||
char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
|
char cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
|
||||||
|
char *old_key = NULL;
|
||||||
|
size_t old_key_size;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
log_dbg("Creating LUKS header backup for device %s.", rc->device);
|
log_dbg("Creating LUKS header backup for device %s.", rc->device);
|
||||||
@@ -494,14 +498,30 @@ static int backup_luks_headers(struct reenc_ctx *rc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opt_keep_key) {
|
||||||
|
log_dbg("Keeping key from old header.");
|
||||||
|
old_key_size = crypt_get_volume_key_size(cd);
|
||||||
|
old_key = crypt_safe_alloc(old_key_size);
|
||||||
|
if (!old_key) {
|
||||||
|
r = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, old_key, &old_key_size,
|
||||||
|
rc->p[rc->keyslot].password, rc->p[rc->keyslot].passwordLen);
|
||||||
|
if (r < 0)
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
r = create_new_header(rc,
|
r = create_new_header(rc,
|
||||||
opt_cipher ? cipher : crypt_get_cipher(cd),
|
opt_cipher ? cipher : crypt_get_cipher(cd),
|
||||||
opt_cipher ? cipher_mode : crypt_get_cipher_mode(cd),
|
opt_cipher ? cipher_mode : crypt_get_cipher_mode(cd),
|
||||||
crypt_get_uuid(cd),
|
crypt_get_uuid(cd),
|
||||||
|
old_key,
|
||||||
opt_key_size ? opt_key_size / 8 : crypt_get_volume_key_size(cd),
|
opt_key_size ? opt_key_size / 8 : crypt_get_volume_key_size(cd),
|
||||||
¶ms);
|
¶ms);
|
||||||
out:
|
out:
|
||||||
crypt_free(cd);
|
crypt_free(cd);
|
||||||
|
crypt_safe_free(old_key);
|
||||||
if (r)
|
if (r)
|
||||||
log_err(_("Creation of LUKS backup headers failed.\n"));
|
log_err(_("Creation of LUKS backup headers failed.\n"));
|
||||||
return r;
|
return r;
|
||||||
@@ -559,7 +579,7 @@ static int backup_fake_header(struct reenc_ctx *rc)
|
|||||||
r = create_new_header(rc,
|
r = create_new_header(rc,
|
||||||
opt_cipher ? cipher : DEFAULT_LUKS1_CIPHER,
|
opt_cipher ? cipher : DEFAULT_LUKS1_CIPHER,
|
||||||
opt_cipher ? cipher_mode : DEFAULT_LUKS1_MODE,
|
opt_cipher ? cipher_mode : DEFAULT_LUKS1_MODE,
|
||||||
NULL,
|
NULL, NULL,
|
||||||
(opt_key_size ? opt_key_size : DEFAULT_LUKS1_KEYBITS) / 8,
|
(opt_key_size ? opt_key_size : DEFAULT_LUKS1_KEYBITS) / 8,
|
||||||
¶ms);
|
¶ms);
|
||||||
out:
|
out:
|
||||||
@@ -1087,11 +1107,15 @@ static int run_reencrypt(const char *device)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!opt_keep_key) {
|
||||||
|
log_dbg("Running data area reencryption.");
|
||||||
if ((r = activate_luks_headers(&rc)))
|
if ((r = activate_luks_headers(&rc)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if ((r = copy_data(&rc)))
|
if ((r = copy_data(&rc)))
|
||||||
goto out;
|
goto out;
|
||||||
|
} else
|
||||||
|
log_dbg("Keeping existing key, skipping data area reencryption.");
|
||||||
|
|
||||||
r = restore_luks_header(&rc);
|
r = restore_luks_header(&rc);
|
||||||
out:
|
out:
|
||||||
@@ -1130,6 +1154,7 @@ int main(int argc, const char **argv)
|
|||||||
{ "cipher", 'c', POPT_ARG_STRING, &opt_cipher, 0, N_("The cipher used to encrypt the disk (see /proc/crypto)"), NULL },
|
{ "cipher", 'c', POPT_ARG_STRING, &opt_cipher, 0, N_("The cipher used to encrypt the disk (see /proc/crypto)"), NULL },
|
||||||
{ "key-size", 's', POPT_ARG_INT, &opt_key_size, 0, N_("The size of the encryption key"), N_("BITS") },
|
{ "key-size", 's', POPT_ARG_INT, &opt_key_size, 0, N_("The size of the encryption key"), N_("BITS") },
|
||||||
{ "hash", 'h', POPT_ARG_STRING, &opt_hash, 0, N_("The hash used to create the encryption key from the passphrase"), NULL },
|
{ "hash", 'h', POPT_ARG_STRING, &opt_hash, 0, N_("The hash used to create the encryption key from the passphrase"), NULL },
|
||||||
|
{ "keep-key", '\0', POPT_ARG_NONE, &opt_keep_key, 0, N_("Do not change key, no data area reencryption."), NULL },
|
||||||
{ "key-file", 'd', POPT_ARG_STRING, &opt_key_file, 0, N_("Read the key from a file."), NULL },
|
{ "key-file", 'd', POPT_ARG_STRING, &opt_key_file, 0, N_("Read the key from a file."), NULL },
|
||||||
{ "iter-time", 'i', POPT_ARG_INT, &opt_iteration_time, 0, N_("PBKDF2 iteration time for LUKS (in ms)"), N_("msecs") },
|
{ "iter-time", 'i', POPT_ARG_INT, &opt_iteration_time, 0, N_("PBKDF2 iteration time for LUKS (in ms)"), N_("msecs") },
|
||||||
{ "batch-mode", 'q', POPT_ARG_NONE, &opt_batch_mode, 0, N_("Do not ask for confirmation"), NULL },
|
{ "batch-mode", 'q', POPT_ARG_NONE, &opt_batch_mode, 0, N_("Do not ask for confirmation"), NULL },
|
||||||
@@ -1235,6 +1260,10 @@ int main(int argc, const char **argv)
|
|||||||
usage(popt_context, EXIT_FAILURE, _("Option --new must be used together with --reduce-device-size."),
|
usage(popt_context, EXIT_FAILURE, _("Option --new must be used together with --reduce-device-size."),
|
||||||
poptGetInvocationName(popt_context));
|
poptGetInvocationName(popt_context));
|
||||||
|
|
||||||
|
if (opt_keep_key && ((!opt_hash && !opt_iteration_time) || opt_cipher || opt_new))
|
||||||
|
usage(popt_context, EXIT_FAILURE, _("Option --keep-key can be used only with --hash or --iter-time."),
|
||||||
|
poptGetInvocationName(popt_context));
|
||||||
|
|
||||||
if (opt_debug) {
|
if (opt_debug) {
|
||||||
opt_verbose = 1;
|
opt_verbose = 1;
|
||||||
crypt_set_debug_level(-1);
|
crypt_set_debug_level(-1);
|
||||||
|
|||||||
@@ -255,5 +255,16 @@ add_scsi_device sector_size=512 physblk_exp=3 dev_size_mb=8
|
|||||||
simple_scsi_reenc "[4096/512 sector]"
|
simple_scsi_reenc "[4096/512 sector]"
|
||||||
echo "[OK]"
|
echo "[OK]"
|
||||||
|
|
||||||
|
echo "[8] Header only reencryption (hash and iteration time)"
|
||||||
|
echo $PWD1 | $CRYPTSETUP -q luksFormat --hash sha1 $LOOPDEV1 || fail
|
||||||
|
wipe $PWD1
|
||||||
|
check_hash $PWD1 $HASH1
|
||||||
|
echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key --hash sha256 --iter-time 1
|
||||||
|
check_hash $PWD1 $HASH1
|
||||||
|
echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key --hash sha512
|
||||||
|
check_hash $PWD1 $HASH1
|
||||||
|
echo $PWD1 | $REENC $LOOPDEV1 -q --keep-key --iter-time 1
|
||||||
|
check_hash $PWD1 $HASH1
|
||||||
|
|
||||||
remove_mapping
|
remove_mapping
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
Reference in New Issue
Block a user