From 7d8003da460660f081e27f539d656eea533dd3b1 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Tue, 13 Nov 2018 14:16:27 +0100 Subject: [PATCH] cryptsetup: add support for --offset option to luksFormat. This option can replace --align-payload with absolute alignment value. --- man/cryptsetup.8 | 6 +++++- src/cryptsetup.c | 17 ++++++++++++++--- src/cryptsetup_reencrypt.c | 15 ++++++++++----- tests/compat-test | 3 +++ tests/compat-test2 | 11 +++++++++++ 5 files changed, 43 insertions(+), 9 deletions(-) diff --git a/man/cryptsetup.8 b/man/cryptsetup.8 index e8b28170..3fd66afe 100644 --- a/man/cryptsetup.8 +++ b/man/cryptsetup.8 @@ -892,7 +892,11 @@ actions. .B "\-\-offset, \-o " Start offset in the backend device in 512-byte sectors. This option is only relevant for the \fIopen\fR action with plain -or loopaes device types. +or loopaes device types or for LUKS devices in \fIluksFormat\fR. + +For LUKS, the \-\-offset option sets the data offset (payload) of data +device and must be be aligned to 4096-byte sectors (must be multiple of 8). +This option cannot be combined with \-\-align\-payload option. .TP .B "\-\-skip, \-p " Start offset used in IV calculation in 512-byte sectors diff --git a/src/cryptsetup.c b/src/cryptsetup.c index 59411fc9..9d6198af 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -1043,6 +1043,12 @@ static int action_luksFormat(void) return r; } + if (opt_offset) { + r = crypt_set_data_offset(cd, opt_offset); + if (r < 0) + goto out; + } + /* Print all present signatures in read-only mode */ r = tools_detect_signatures(header_device, 0, &signatures); if (r < 0) @@ -2638,16 +2644,21 @@ int main(int argc, const char **argv) usage(popt_context, EXIT_FAILURE, _("Option --align-payload is allowed only for luksFormat."), poptGetInvocationName(popt_context)); + if (opt_align_payload && opt_offset) + usage(popt_context, EXIT_FAILURE, _("Option --align-payload and --offset cannot be combined."), + poptGetInvocationName(popt_context)); + if (opt_skip && (strcmp(aname, "open") || (strcmp(opt_type, "plain") && strcmp(opt_type, "loopaes")))) usage(popt_context, EXIT_FAILURE, _("Option --skip is supported only for open of plain and loopaes devices.\n"), poptGetInvocationName(popt_context)); - if (opt_offset && (strcmp(aname, "open") || - (strcmp(opt_type, "plain") && strcmp(opt_type, "loopaes")))) + if (opt_offset && ((strcmp(aname, "open") && strcmp(aname, "luksFormat")) || + (!strcmp(aname, "open") && strcmp(opt_type, "plain") && strcmp(opt_type, "loopaes")) || + (!strcmp(aname, "luksFormat") && strncmp(opt_type, "luks", 4)))) usage(popt_context, EXIT_FAILURE, - _("Option --offset is supported only for open of plain and loopaes devices.\n"), + _("Option --offset is supported only for open of plain and loopaes devices and for luksFormat.\n"), poptGetInvocationName(popt_context)); if ((opt_tcrypt_hidden || opt_tcrypt_system || opt_tcrypt_backup) && strcmp(aname, "tcryptDump") && diff --git a/src/cryptsetup_reencrypt.c b/src/cryptsetup_reencrypt.c index 96725042..c34ff810 100644 --- a/src/cryptsetup_reencrypt.c +++ b/src/cryptsetup_reencrypt.c @@ -78,6 +78,7 @@ struct reenc_ctx { uint64_t device_size_org_real; uint64_t device_offset; uint64_t device_shift; + uint64_t data_offset; unsigned int stained:1; unsigned int in_progress:1; @@ -590,6 +591,12 @@ static int create_new_header(struct reenc_ctx *rc, struct crypt_device *cd_old, goto out; } + r = crypt_set_data_offset(cd_new, rc->data_offset); + if (r) { + log_err(_("Failed to set data offset.")); + goto out; + } + r = crypt_format(cd_new, type, cipher, cipher_mode, uuid, key, key_size, params); check_signal(&r); if (r < 0) @@ -731,14 +738,12 @@ static int backup_luks_headers(struct reenc_ctx *rc) if (rc->reencrypt_mode == DECRYPT) goto out; - if ((r = create_empty_header(rc->header_file_new, rc->header_file_org, - crypt_get_data_offset(cd)))) + rc->data_offset = crypt_get_data_offset(cd) + ROUND_SECTOR(opt_reduce_size); + + if ((r = create_empty_header(rc->header_file_new, rc->header_file_org, rc->data_offset))) goto out; params.hash = opt_hash ?: DEFAULT_LUKS1_HASH; - params.data_alignment = crypt_get_data_offset(cd); - params.data_alignment += ROUND_SECTOR(opt_reduce_size); - params2.data_alignment = params.data_alignment; params2.data_device = params.data_device = rc->device; params2.sector_size = crypt_get_sector_size(cd); diff --git a/tests/compat-test b/tests/compat-test index 55801137..ba64bc93 100755 --- a/tests/compat-test +++ b/tests/compat-test @@ -678,6 +678,9 @@ echo $PWD1 | $CRYPTSETUP luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --head echo $PWD1 | $CRYPTSETUP luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --align-payload 1 >/dev/null 2>&1 && fail echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --align-payload 8192 || fail echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --align-payload 0 || fail +echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --align-payload 8192 --offset 8192 >/dev/null 2>&1 && fail +echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --offset 8192 || fail +echo $PWD1 | $CRYPTSETUP -q luksFormat --type luks1 $FAST_PBKDF_OPT $LOOPDEV --header $HEADER_IMG --offset 0 || fail echo $PWD1 | $CRYPTSETUP luksOpen $LOOPDEV --header $HEADER_IMG $DEV_NAME || fail $CRYPTSETUP -q resize $DEV_NAME --size 100 --header $HEADER_IMG || fail $CRYPTSETUP -q status $DEV_NAME --header $HEADER_IMG | grep "size:" | grep -q "100 sectors" || fail diff --git a/tests/compat-test2 b/tests/compat-test2 index 58d7620c..69b74b76 100755 --- a/tests/compat-test2 +++ b/tests/compat-test2 @@ -209,6 +209,17 @@ export LANG=C [ -z "$LOOPDEV" ] && skip "WARNING: Cannot find free loop device, test skipped." [ -d "$LOCK_DIR" ] || skip "WARNING: LUKS2 locking directory ($LOCK_DIR) is missing, test skipped." +prepare "[1] Data offset" wipe +echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --offset 1 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --offset 16385 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --offset 32 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --align-payload 16384 --offset 16384 2>/dev/null && fail +echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --offset 16384 || fail +$CRYPTSETUP -q luksDump $LOOPDEV | grep -q "offset: $((512 * 16384)) \[bytes\]" || fail +echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 1024 --offset 16384 || fail +$CRYPTSETUP -q luksDump $LOOPDEV | grep -q "offset: $((512 * 16384)) \[bytes\]" || fail +echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --offset 80000 2>/dev/null && fail + prepare "[2] Sector size and old payload alignment" wipe echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 511 2>/dev/null && fail echo $PWD1 | $CRYPTSETUP luksFormat $FAST_PBKDF_OPT --type luks2 $LOOPDEV -q --sector-size 256 2>/dev/null && fail