mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-17 05:40:13 +01:00
Add possibility to change key size (optionally by shrinking device).
This commit is contained in:
@@ -50,6 +50,18 @@ lines are always prefixed by '#'.
|
|||||||
.B "\-\-cipher, \-c" \fI<cipher-spec>\fR
|
.B "\-\-cipher, \-c" \fI<cipher-spec>\fR
|
||||||
Set the cipher specification string.
|
Set the cipher specification string.
|
||||||
.TP
|
.TP
|
||||||
|
.B "\-\-key-size, \-s \fI<bits>\fR"
|
||||||
|
Set key size in bits. The argument has to be a multiple of 8.
|
||||||
|
|
||||||
|
The possible key-sizes are limited by the cipher and mode used.
|
||||||
|
|
||||||
|
If you are increasing key size, there must be enough space in the LUKS header
|
||||||
|
for enlarged keyslots (data offset must be large enough) or reencryption
|
||||||
|
cannot be performed.
|
||||||
|
|
||||||
|
If there is not enough space for keyslots with new key size,
|
||||||
|
you can destructively shrink device with \-\-reduce-device-size option.
|
||||||
|
.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.
|
||||||
.TP
|
.TP
|
||||||
@@ -64,17 +76,17 @@ Define which kernel random number generator will be used to create the volume ke
|
|||||||
.TP
|
.TP
|
||||||
.B "\-\-key-file, \-d \fIname\fR"
|
.B "\-\-key-file, \-d \fIname\fR"
|
||||||
Read the passphrase from file.
|
Read the passphrase from file.
|
||||||
.br
|
|
||||||
WARNING: \-\-key-file option can be used only if there only one active keyslot,
|
WARNING: \-\-key-file option can be used only if there only one active keyslot,
|
||||||
or alternatively, also if \-\-key-slot option is specified (then all other keyslots
|
or alternatively, also if \-\-key-slot option is specified (then all other keyslots
|
||||||
will be disabled in new LUKS device).
|
will be disabled in new LUKS device).
|
||||||
|
|
||||||
If this option is not used, cryptswtup-reencrypt will ask for all active keyslot
|
If this option is not used, cryptsetup-reencrypt will ask for all active keyslot
|
||||||
passphrases.
|
passphrases.
|
||||||
.TP
|
.TP
|
||||||
.B "\-\-key-slot, \-S <0-7>"
|
.B "\-\-key-slot, \-S <0-7>"
|
||||||
Specify which key slot is used.
|
Specify which key slot is used.
|
||||||
.br
|
|
||||||
WARNING: All other keyslots will be disabled if this option is used.
|
WARNING: All other keyslots will be disabled if this option is used.
|
||||||
.TP
|
.TP
|
||||||
.B "\-\-keyfile-offset \fIvalue\fR"
|
.B "\-\-keyfile-offset \fIvalue\fR"
|
||||||
@@ -90,12 +102,28 @@ Number of retries for invalid passphrase entry.
|
|||||||
.TP
|
.TP
|
||||||
.B "\-\-block-size, \-B \fIvalue\fR"
|
.B "\-\-block-size, \-B \fIvalue\fR"
|
||||||
Use re-encryption block size of <value> in MiB.
|
Use re-encryption block size of <value> in MiB.
|
||||||
.br
|
|
||||||
Values can be between 1 and 64 MiB.
|
Values can be between 1 and 64 MiB.
|
||||||
.TP
|
.TP
|
||||||
|
.B "\-\-reduce-device-size \fInumber of 512 bytes sectors\fR"
|
||||||
|
Enlarge data offset for specified value of sectors by shrinking
|
||||||
|
device size.
|
||||||
|
|
||||||
|
This means that last sectors on the original device will be lost,
|
||||||
|
ciphertext data will be effectively shifted by specified
|
||||||
|
number of sectors.
|
||||||
|
|
||||||
|
It can be usefull if you e.g. added some space to underlying
|
||||||
|
partition (so last sectors contains no data).
|
||||||
|
|
||||||
|
WARNING: This is destructive operation and cannot be reverted.
|
||||||
|
Use with extreme care - shrinked filesystems are usually unrecoverable.
|
||||||
|
|
||||||
|
You cannot shrink device more than by 64 MiB (131072 sectors).
|
||||||
|
.TP
|
||||||
.B "\-\-use-directio"
|
.B "\-\-use-directio"
|
||||||
Use direct-io (O_DIRECT) for all read/write data operations.
|
Use direct-io (O_DIRECT) for all read/write data operations.
|
||||||
.br
|
|
||||||
Usefull if direct-io operations perform better than normal buffered
|
Usefull if direct-io operations perform better than normal buffered
|
||||||
operations (e.g. in virtual environments).
|
operations (e.g. in virtual environments).
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -55,11 +55,13 @@ static int opt_version_mode = 0;
|
|||||||
static int opt_random = 0;
|
static int opt_random = 0;
|
||||||
static int opt_urandom = 0;
|
static int opt_urandom = 0;
|
||||||
static int opt_bsize = 4;
|
static int opt_bsize = 4;
|
||||||
|
static int opt_reduce_device_size = 0;
|
||||||
static int opt_directio = 0;
|
static int opt_directio = 0;
|
||||||
static int opt_fsync = 0;
|
static int opt_fsync = 0;
|
||||||
static int opt_write_log = 0;
|
static int opt_write_log = 0;
|
||||||
static int opt_tries = 3;
|
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 const char **action_argv;
|
static const char **action_argv;
|
||||||
|
|
||||||
@@ -277,19 +279,36 @@ out:
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int create_empty_header(const char *new_file, const char *old_file)
|
static int create_empty_header(const char *new_file, const char *old_file,
|
||||||
|
uint64_t data_sector)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
int fd, r = 0;
|
int fd, r = 0;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
|
/* Never create header > 4MiB */
|
||||||
|
if (data_sector > 8192)
|
||||||
|
data_sector = 8192;
|
||||||
|
|
||||||
|
/* new header file of the same size as old backup */
|
||||||
if (stat(old_file, &st) == -1 ||
|
if (stat(old_file, &st) == -1 ||
|
||||||
(st.st_mode & S_IFMT) != S_IFREG ||
|
(st.st_mode & S_IFMT) != S_IFREG ||
|
||||||
(st.st_size > 16 * 1024 * 1024))
|
(st.st_size > 16 * 1024 * 1024))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
size = st.st_size;
|
size = st.st_size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if requesting key size change, try to use offset
|
||||||
|
* here can be enough space to fit new key.
|
||||||
|
*/
|
||||||
|
if (opt_key_size)
|
||||||
|
size = data_sector * SECTOR_SIZE;
|
||||||
|
|
||||||
|
/* if reducing size, be sure we have enough space */
|
||||||
|
if (opt_reduce_device_size)
|
||||||
|
size += (opt_reduce_device_size * SECTOR_SIZE);
|
||||||
|
|
||||||
log_dbg("Creating empty file %s of size %lu.", new_file, (unsigned long)size);
|
log_dbg("Creating empty file %s of size %lu.", new_file, (unsigned long)size);
|
||||||
|
|
||||||
if (!(buf = malloc(size)))
|
if (!(buf = malloc(size)))
|
||||||
@@ -499,13 +518,16 @@ static int backup_luks_headers(struct reenc_ctx *rc)
|
|||||||
goto out;
|
goto out;
|
||||||
log_verbose(_("LUKS header backup of device %s created.\n"), rc->device);
|
log_verbose(_("LUKS header backup of device %s created.\n"), rc->device);
|
||||||
|
|
||||||
if ((r = create_empty_header(rc->header_file_new, rc->header_file_org)))
|
if ((r = create_empty_header(rc->header_file_new, rc->header_file_org,
|
||||||
|
crypt_get_data_offset(cd))))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
params.hash = opt_hash ?: DEFAULT_LUKS1_HASH;
|
params.hash = opt_hash ?: DEFAULT_LUKS1_HASH;
|
||||||
params.data_alignment = crypt_get_data_offset(cd);
|
params.data_alignment = crypt_get_data_offset(cd);
|
||||||
|
params.data_alignment += opt_reduce_device_size;
|
||||||
params.data_device = rc->device;
|
params.data_device = rc->device;
|
||||||
|
|
||||||
|
|
||||||
if ((r = crypt_init(&cd_new, rc->header_file_new)))
|
if ((r = crypt_init(&cd_new, rc->header_file_new)))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@@ -529,7 +551,9 @@ static int backup_luks_headers(struct reenc_ctx *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),
|
||||||
NULL, crypt_get_volume_key_size(cd), ¶ms)))
|
NULL,
|
||||||
|
opt_key_size ? opt_key_size / 8 : crypt_get_volume_key_size(cd),
|
||||||
|
¶ms)))
|
||||||
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);
|
||||||
|
|
||||||
@@ -760,7 +784,7 @@ static int copy_data(struct reenc_ctx *rc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check size */
|
/* Check size */
|
||||||
if (ioctl(fd_old, BLKGETSIZE64, &rc->device_size) < 0) {
|
if (ioctl(fd_new, BLKGETSIZE64, &rc->device_size) < 0) {
|
||||||
log_err(_("Cannot get device size.\n"));
|
log_err(_("Cannot get device size.\n"));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -975,7 +999,7 @@ static int initialize_context(struct reenc_ctx *rc, const char *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!rc->in_progress) {
|
if (!rc->in_progress) {
|
||||||
if (1 /*opt_new */)
|
if (!opt_reduce_device_size)
|
||||||
rc->reencrypt_direction = FORWARD;
|
rc->reencrypt_direction = FORWARD;
|
||||||
else {
|
else {
|
||||||
rc->reencrypt_direction = BACKWARD;
|
rc->reencrypt_direction = BACKWARD;
|
||||||
@@ -998,7 +1022,7 @@ static void destroy_context(struct reenc_ctx *rc)
|
|||||||
if ((rc->reencrypt_direction == FORWARD &&
|
if ((rc->reencrypt_direction == FORWARD &&
|
||||||
rc->device_offset == rc->device_size) ||
|
rc->device_offset == rc->device_size) ||
|
||||||
(rc->reencrypt_direction == BACKWARD &&
|
(rc->reencrypt_direction == BACKWARD &&
|
||||||
rc->device_offset == 0)) {
|
(rc->device_offset == 0 || rc->device_offset == (uint64_t)~0))) {
|
||||||
unlink(rc->log_file);
|
unlink(rc->log_file);
|
||||||
unlink(rc->header_file_org);
|
unlink(rc->header_file_org);
|
||||||
unlink(rc->header_file_new);
|
unlink(rc->header_file_new);
|
||||||
@@ -1091,6 +1115,7 @@ int main(int argc, const char **argv)
|
|||||||
{ "debug", '\0', POPT_ARG_NONE, &opt_debug, 0, N_("Show debug messages"), NULL },
|
{ "debug", '\0', POPT_ARG_NONE, &opt_debug, 0, N_("Show debug messages"), NULL },
|
||||||
{ "block-size", 'B', POPT_ARG_INT, &opt_bsize, 0, N_("Reencryption block size"), N_("MiB") },
|
{ "block-size", 'B', POPT_ARG_INT, &opt_bsize, 0, N_("Reencryption block size"), N_("MiB") },
|
||||||
{ "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") },
|
||||||
{ "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 },
|
||||||
{ "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") },
|
||||||
@@ -1104,6 +1129,7 @@ int main(int argc, const char **argv)
|
|||||||
{ "key-slot", 'S', POPT_ARG_INT, &opt_key_slot, 0, N_("Use only this slot (others will be disabled)."), NULL },
|
{ "key-slot", 'S', POPT_ARG_INT, &opt_key_slot, 0, N_("Use only this slot (others will be disabled)."), NULL },
|
||||||
{ "keyfile-offset", '\0', POPT_ARG_LONG, &opt_keyfile_offset, 0, N_("Number of bytes to skip in keyfile"), N_("bytes") },
|
{ "keyfile-offset", '\0', POPT_ARG_LONG, &opt_keyfile_offset, 0, N_("Number of bytes to skip in keyfile"), N_("bytes") },
|
||||||
{ "keyfile-size", 'l', POPT_ARG_LONG, &opt_keyfile_size, 0, N_("Limits the read from keyfile"), N_("bytes") },
|
{ "keyfile-size", 'l', POPT_ARG_LONG, &opt_keyfile_size, 0, N_("Limits the read from keyfile"), N_("bytes") },
|
||||||
|
{ "reduce-device-size",'\0', POPT_ARG_INT, &opt_reduce_device_size, 0, N_("Reduce data device size (move data start). DANGEROUS!"), N_("SECTORS") },
|
||||||
POPT_TABLEEND
|
POPT_TABLEEND
|
||||||
};
|
};
|
||||||
poptContext popt_context;
|
poptContext popt_context;
|
||||||
@@ -1153,6 +1179,16 @@ int main(int argc, const char **argv)
|
|||||||
_("Only values between 1MiB and 64 MiB allowed for reencryption block size."),
|
_("Only values between 1MiB and 64 MiB allowed for reencryption block size."),
|
||||||
poptGetInvocationName(popt_context));
|
poptGetInvocationName(popt_context));
|
||||||
|
|
||||||
|
if (opt_reduce_device_size > 64 * 1024 * 1024 / SECTOR_SIZE)
|
||||||
|
usage(popt_context, EXIT_FAILURE,
|
||||||
|
_("Maximum device reduce size is 64 MiB."),
|
||||||
|
poptGetInvocationName(popt_context));
|
||||||
|
|
||||||
|
if (opt_key_size % 8)
|
||||||
|
usage(popt_context, EXIT_FAILURE,
|
||||||
|
_("Key size must be a multiple of 8 bits"),
|
||||||
|
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user