Support sector size option even for plain devices.

This commit is contained in:
Milan Broz
2017-09-24 17:49:31 +02:00
parent c6d4ebd80c
commit 19a1852e4b
7 changed files with 76 additions and 11 deletions

View File

@@ -46,6 +46,7 @@
#define SECTOR_SHIFT 9 #define SECTOR_SHIFT 9
#define SECTOR_SIZE (1 << SECTOR_SHIFT) #define SECTOR_SIZE (1 << SECTOR_SHIFT)
#define MAX_SECTOR_SIZE 4096 /* min page size among all platforms */
#define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */ #define DEFAULT_DISK_ALIGNMENT 1048576 /* 1MiB */
#define DEFAULT_MEM_ALIGNMENT 4096 #define DEFAULT_MEM_ALIGNMENT 4096
#define MAX_ERROR_LENGTH 512 #define MAX_ERROR_LENGTH 512

View File

@@ -356,6 +356,7 @@ struct crypt_params_plain {
uint64_t offset; /**< offset in sectors */ uint64_t offset; /**< offset in sectors */
uint64_t skip; /**< IV offset / initialization sector */ uint64_t skip; /**< IV offset / initialization sector */
uint64_t size; /**< size of mapped device or @e 0 for autodetection */ uint64_t size; /**< size of mapped device or @e 0 for autodetection */
uint32_t sector_size; /**< sector size in bytes (@e 0 means 512 for compatibility) */
}; };
/** /**
@@ -1214,7 +1215,7 @@ const char *crypt_get_uuid(struct crypt_device *cd);
const char *crypt_get_device_name(struct crypt_device *cd); const char *crypt_get_device_name(struct crypt_device *cd);
/** /**
* Get device offset in sectors where real data starts (on underlying device). * Get device offset in 512-bytes sectors where real data starts (on underlying device).
* *
* @param cd crypt device handle * @param cd crypt device handle
* *
@@ -1224,7 +1225,7 @@ const char *crypt_get_device_name(struct crypt_device *cd);
uint64_t crypt_get_data_offset(struct crypt_device *cd); uint64_t crypt_get_data_offset(struct crypt_device *cd);
/** /**
* Get IV offset in sectors (skip). * Get IV offset in 512-bytes sectors (skip).
* *
* @param cd crypt device handle * @param cd crypt device handle
* *

View File

@@ -587,7 +587,7 @@ static int crypt_check_data_device_size(struct crypt_device *cd)
int r; int r;
uint64_t size, size_min; uint64_t size, size_min;
/* Check data device size, require at least one sector */ /* Check data device size, require at least header or one sector */
size_min = crypt_get_data_offset(cd) << SECTOR_SHIFT ?: SECTOR_SIZE; size_min = crypt_get_data_offset(cd) << SECTOR_SHIFT ?: SECTOR_SIZE;
r = device_size(cd->device, &size); r = device_size(cd->device, &size);
@@ -1065,6 +1065,7 @@ static int _init_by_name_crypt(struct crypt_device *cd, const char *name)
cd->u.plain.hdr.hash = NULL; /* no way to get this */ cd->u.plain.hdr.hash = NULL; /* no way to get this */
cd->u.plain.hdr.offset = dmd.u.crypt.offset; cd->u.plain.hdr.offset = dmd.u.crypt.offset;
cd->u.plain.hdr.skip = dmd.u.crypt.iv_offset; cd->u.plain.hdr.skip = dmd.u.crypt.iv_offset;
cd->u.plain.hdr.sector_size = dmd.u.crypt.sector_size;
cd->u.plain.key_size = dmd.u.crypt.vk->keylength; cd->u.plain.key_size = dmd.u.crypt.vk->keylength;
cd->u.plain.cipher = strdup(cipher); cd->u.plain.cipher = strdup(cipher);
cd->u.plain.cipher_mode = strdup(cipher_mode); cd->u.plain.cipher_mode = strdup(cipher_mode);
@@ -1311,6 +1312,8 @@ static int _crypt_format_plain(struct crypt_device *cd,
size_t volume_key_size, size_t volume_key_size,
struct crypt_params_plain *params) struct crypt_params_plain *params)
{ {
unsigned int sector_size = params ? params->sector_size : SECTOR_SIZE;
if (!cipher || !cipher_mode) { if (!cipher || !cipher_mode) {
log_err(cd, _("Invalid plain crypt parameters.\n")); log_err(cd, _("Invalid plain crypt parameters.\n"));
return -EINVAL; return -EINVAL;
@@ -1326,6 +1329,16 @@ static int _crypt_format_plain(struct crypt_device *cd,
return -EINVAL; return -EINVAL;
} }
/* For compatibility with old params structure */
if (!sector_size)
sector_size = SECTOR_SIZE;
if (sector_size < SECTOR_SIZE || sector_size > MAX_SECTOR_SIZE ||
(sector_size & (sector_size - 1))) {
log_err(cd, _("Unsupported encryption sector size.\n"));
return -EINVAL;
}
if (!(cd->type = strdup(CRYPT_PLAIN))) if (!(cd->type = strdup(CRYPT_PLAIN)))
return -ENOMEM; return -ENOMEM;
@@ -1344,6 +1357,7 @@ static int _crypt_format_plain(struct crypt_device *cd,
cd->u.plain.hdr.offset = params ? params->offset : 0; cd->u.plain.hdr.offset = params ? params->offset : 0;
cd->u.plain.hdr.skip = params ? params->skip : 0; cd->u.plain.hdr.skip = params ? params->skip : 0;
cd->u.plain.hdr.size = params ? params->size : 0; cd->u.plain.hdr.size = params ? params->size : 0;
cd->u.plain.hdr.sector_size = sector_size;
if (!cd->u.plain.cipher || !cd->u.plain.cipher_mode) if (!cd->u.plain.cipher || !cd->u.plain.cipher_mode)
return -ENOMEM; return -ENOMEM;
@@ -1459,7 +1473,8 @@ static int _crypt_format_luks2(struct crypt_device *cd,
return -EINVAL; return -EINVAL;
} }
if (sector_size < 512 || sector_size > 4096 || (sector_size & (sector_size - 1))) { if (sector_size < SECTOR_SIZE || sector_size > MAX_SECTOR_SIZE ||
(sector_size & (sector_size - 1))) {
log_err(cd, _("Unsupported encryption sector size.\n")); log_err(cd, _("Unsupported encryption sector size.\n"));
return -EINVAL; return -EINVAL;
} }
@@ -3600,6 +3615,9 @@ int crypt_get_sector_size(struct crypt_device *cd)
if (!cd) if (!cd)
return SECTOR_SIZE; return SECTOR_SIZE;
if (isPLAIN(cd->type))
return cd->u.plain.hdr.sector_size;
if (isINTEGRITY(cd->type)) if (isINTEGRITY(cd->type))
return cd->u.integrity.params.sector_size; return cd->u.integrity.params.sector_size;

View File

@@ -110,7 +110,7 @@ Reports the status for the mapping <name>.
.IP .IP
Resizes an active mapping <name>. Resizes an active mapping <name>.
If \-\-size (in sectors) is not specified, the size is computed If \-\-size (in 512-bytes sectors) is not specified, the size is computed
from the underlying device. For LUKS it is the size of the from the underlying device. For LUKS it is the size of the
underlying device without the area reserved for LUKS header underlying device without the area reserved for LUKS header
(see data payload offset in \fBluksDump\fR command). (see data payload offset in \fBluksDump\fR command).
@@ -147,8 +147,8 @@ The following are valid plain device type actions:
Opens (creates a mapping with) <name> backed by device <device>. Opens (creates a mapping with) <name> backed by device <device>.
\fB<options>\fR can be [\-\-hash, \-\-cipher, \-\-verify-passphrase, \fB<options>\fR can be [\-\-hash, \-\-cipher, \-\-verify-passphrase,
\-\-key-file, \-\-keyfile-offset, \-\-key-size, \-\-offset, \-\-skip, \-\-size, \-\-sector\-size, \-\-key-file, \-\-keyfile-offset, \-\-key-size,
\-\-readonly, \-\-shared, \-\-allow\-discards] \-\-offset, \-\-skip, \-\-size, \-\-readonly, \-\-shared, \-\-allow\-discards]
Example: 'cryptsetup open \-\-type plain /dev/sda10 e1' maps the raw Example: 'cryptsetup open \-\-type plain /dev/sda10 e1' maps the raw
encrypted device /dev/sda10 to the mapped (decrypted) device encrypted device /dev/sda10 to the mapped (decrypted) device

View File

@@ -83,7 +83,7 @@ static const char *opt_integrity = NULL; /* none */
static int opt_integrity_nojournal = 0; static int opt_integrity_nojournal = 0;
static int opt_integrity_no_wipe = 0; static int opt_integrity_no_wipe = 0;
static const char *opt_key_description = NULL; static const char *opt_key_description = NULL;
static int opt_sector_size = 512; static int opt_sector_size = SECTOR_SIZE;
static int opt_persistent = 0; static int opt_persistent = 0;
static const char *opt_label = NULL; static const char *opt_label = NULL;
static const char *opt_subsystem = NULL; static const char *opt_subsystem = NULL;
@@ -166,6 +166,7 @@ static int action_open_plain(void)
.skip = opt_skip, .skip = opt_skip,
.offset = opt_offset, .offset = opt_offset,
.size = opt_size, .size = opt_size,
.sector_size = opt_sector_size,
}; };
char *password = NULL; char *password = NULL;
size_t passwordLen, key_size_max; size_t passwordLen, key_size_max;
@@ -954,7 +955,7 @@ static int action_luksFormat(void)
else else
luks_version = 1; luks_version = 1;
if (opt_sector_size > 512 && luks_version == 1) { if (opt_sector_size > SECTOR_SIZE && luks_version == 1) {
log_err(_("Unsupported encryption sector size.\n")); log_err(_("Unsupported encryption sector size.\n"));
return -EINVAL; return -EINVAL;
} }
@@ -2357,8 +2358,14 @@ int main(int argc, const char **argv)
_("PBKDF forced iterations cannot be combined with iteration time option.\n"), _("PBKDF forced iterations cannot be combined with iteration time option.\n"),
poptGetInvocationName(popt_context)); poptGetInvocationName(popt_context));
if ((opt_sector_size != 512 && strcmp(aname, "luksFormat")) || opt_sector_size < 512 if (opt_sector_size != SECTOR_SIZE && strcmp(aname, "luksFormat") &&
|| opt_sector_size > 4096 || (opt_sector_size & (opt_sector_size - 1))) (strcmp(aname, "open") || strcmp(opt_type, "plain")))
usage(popt_context, EXIT_FAILURE,
_("Sector size option is not supported for this command.\n"),
poptGetInvocationName(popt_context));
if (opt_sector_size < SECTOR_SIZE || opt_sector_size > MAX_SECTOR_SIZE ||
(opt_sector_size & (opt_sector_size - 1)))
usage(popt_context, EXIT_FAILURE, usage(popt_context, EXIT_FAILURE,
_("Unsupported encryption sector size.\n"), _("Unsupported encryption sector size.\n"),
poptGetInvocationName(popt_context)); poptGetInvocationName(popt_context));

View File

@@ -49,6 +49,7 @@
#define CONST_CAST(x) (x)(uintptr_t) #define CONST_CAST(x) (x)(uintptr_t)
#define DEFAULT_CIPHER(type) (DEFAULT_##type##_CIPHER "-" DEFAULT_##type##_MODE) #define DEFAULT_CIPHER(type) (DEFAULT_##type##_CIPHER "-" DEFAULT_##type##_MODE)
#define SECTOR_SIZE 512 #define SECTOR_SIZE 512
#define MAX_SECTOR_SIZE 4096
#define ROUND_SECTOR(x) (((x) + SECTOR_SIZE - 1) / SECTOR_SIZE) #define ROUND_SECTOR(x) (((x) + SECTOR_SIZE - 1) / SECTOR_SIZE)
#define DEFAULT_WIPE_BLOCK 1048576 /* 1 MiB */ #define DEFAULT_WIPE_BLOCK 1048576 /* 1 MiB */

View File

@@ -46,6 +46,14 @@ format() # format
[ $? -ne 0 ] && fail "Keyslot removal failed." [ $? -ne 0 ] && fail "Keyslot removal failed."
} }
check_sector_size() # $1 expected sector size
{
$CRYPTSETUP status $DEV_NAME | grep "sector size" | grep -q $1 || fail
if [ $S -gt 512 ]; then
dmsetup table $DEV_NAME | grep -q "sector_size:$1" || fail
fi
}
if [ $(id -u) != 0 ]; then if [ $(id -u) != 0 ]; then
echo "WARNING: You must be root to run this test, test skipped." echo "WARNING: You must be root to run this test, test skipped."
exit 0 exit 0
@@ -103,4 +111,33 @@ else
$CRYPTSETUP close $DEV_NAME || fail $CRYPTSETUP close $DEV_NAME || fail
fi fi
echo "[3] Kernel dmcrypt sector size options"
echo -e "$PWD1" | $CRYPTSETUP open --type plain $DEV $DEV_NAME --sector-size 4096 >/dev/null 2>&1
if [ $? -ne 0 ] ; then
echo "TEST SKIPPED: dmcrypt sector-size option not available"
else
$CRYPTSETUP close $DEV_NAME || fail
echo -n "PLAIN sector size:"
echo -e "$PWD1" | $CRYPTSETUP open --type plain $DEV $DEV_NAME --sector-size 1234 >/dev/null 2>&1 && fail
for S in 512 1024 2048 4096; do
echo -n "[$S]"
echo -e "$PWD1" | $CRYPTSETUP open --type plain $DEV $DEV_NAME --sector-size $S || fail
check_sector_size $S
$CRYPTSETUP close $DEV_NAME || fail
done
echo
echo -n "LUKS2 sector size:"
echo -e "$PWD1" | $CRYPTSETUP luksFormat --type luks2 -$DEV --sector-size 1234 >/dev/null 2>&1 && fail
for S in 512 1024 2048 4096; do
echo -n "[$S]"
echo -e "$PWD1" | $CRYPTSETUP luksFormat --type luks2 --pbkdf pbkdf2 --pbkdf-force-iterations 1000 $DEV --sector-size $S || fail
echo -e "$PWD1" | $CRYPTSETUP open $DEV $DEV_NAME || fail
check_sector_size $S
$CRYPTSETUP close $DEV_NAME || fail
done
echo
fi
cleanup cleanup