Commit 5c7954a0 authored by Milan Broz's avatar Milan Broz

Require only up to last keyslot area for header device (ignore data offset).

Fix header backup and restore to work on files with large data offset.
parent 62f334cf
2012-06-10 Milan Broz <gmazyland@gmail.com>
* Both data and header device can now be a file.
* Loop is automatically allocated in crypt_set_data_device().
* Require only up to last keyslot area for header device (ignore data offset).
* Fix header backup and restore to work on files with large data offset.
2012-05-27 Milan Broz <gmazyland@gmail.com>
* Fix readonly activation if underlying device is readonly (1.4.0).
......
......@@ -47,12 +47,12 @@ static inline int round_up_modulo(int x, int m) {
}
/* Get size of struct luks_phrd with all keyslots material space */
static uint64_t LUKS_device_sectors(size_t keyLen, unsigned int stripes)
static uint64_t LUKS_device_sectors(size_t keyLen)
{
uint64_t keyslot_sectors, sector;
int i;
keyslot_sectors = div_round_up(keyLen * stripes, SECTOR_SIZE);
keyslot_sectors = div_round_up(keyLen * LUKS_STRIPES, SECTOR_SIZE);
sector = round_up_modulo(LUKS_PHDR_SIZE, LUKS_ALIGN_KEYSLOTS / SECTOR_SIZE);
for (i = 0; i < LUKS_NUMKEYS; i++) {
......@@ -63,22 +63,22 @@ static uint64_t LUKS_device_sectors(size_t keyLen, unsigned int stripes)
return sector;
}
static int LUKS_check_device_size(const char *device,
uint64_t min_sectors,
static int LUKS_check_device_size(struct crypt_device *ctx, const char *device,
size_t keyLength)
{
uint64_t dev_size, req_sectors;
req_sectors = LUKS_device_sectors(keyLength, LUKS_STRIPES);
if (min_sectors > req_sectors)
req_sectors = min_sectors;
uint64_t dev_size;
if(device_size(device, &dev_size)) {
log_dbg("Cannot get device size for device %s.", device);
return -EIO;
}
return (req_sectors > (dev_size >> SECTOR_SHIFT));
if (LUKS_device_sectors(keyLength) > (dev_size >> SECTOR_SHIFT)) {
log_err(ctx, _("Device %s is too small.\n"), device);
return -EINVAL;
}
return 0;
}
/* Check keyslot to prevent access outside of header and keyslot area */
......@@ -154,7 +154,7 @@ int LUKS_hdr_backup(
if (r)
return r;
buffer_size = hdr->payloadOffset << SECTOR_SHIFT;
buffer_size = LUKS_device_sectors(hdr->keyBytes) << SECTOR_SHIFT;
buffer = crypt_safe_alloc(buffer_size);
if (!buffer || buffer_size < LUKS_ALIGN_KEYSLOTS) {
r = -ENOMEM;
......@@ -219,7 +219,7 @@ int LUKS_hdr_restore(
r = LUKS_read_phdr_backup(backup_file, device, &hdr_file, 0, ctx);
if (!r)
buffer_size = hdr_file.payloadOffset << SECTOR_SHIFT;
buffer_size = LUKS_device_sectors(hdr_file.keyBytes) << SECTOR_SHIFT;
if (r || buffer_size < LUKS_ALIGN_KEYSLOTS) {
log_err(ctx, _("Backup file doesn't contain valid LUKS header.\n"));
......@@ -512,6 +512,9 @@ int LUKS_read_phdr(const char *device,
r = _check_and_convert_hdr(device, hdr, require_luks_device,
repair, ctx);
if (!r)
r = LUKS_check_device_size(ctx, device, hdr->keyBytes);
close(devfd);
return r;
}
......@@ -529,10 +532,9 @@ int LUKS_write_phdr(const char *device,
log_dbg("Updating LUKS header of size %d on device %s",
sizeof(struct luks_phdr), device);
if (LUKS_check_device_size(device, hdr->payloadOffset, hdr->keyBytes)) {
log_err(ctx, _("Device %s is too small.\n"), device);
return -EINVAL;
}
r = LUKS_check_device_size(ctx, device, hdr->keyBytes);
if (r)
return r;
devfd = open(device,O_RDWR | O_DIRECT | O_SYNC);
if(-1 == devfd) {
......
......@@ -598,7 +598,7 @@ static int crypt_check_data_device_size(struct crypt_device *cd)
return r;
if (size < size_min) {
log_err(cd, _("LUKS header detected but device %s is too small.\n"),
log_err(cd, _("Header detected but device %s is too small.\n"),
crypt_get_device_name(cd));
return -EINVAL;
}
......@@ -1224,16 +1224,6 @@ int crypt_load(struct crypt_device *cd,
} else
return -EINVAL;
if (r < 0)
return r;
/* cd->type and header must be set in context */
r = crypt_check_data_device_size(cd);
if (r < 0) {
free(cd->type);
cd->type = NULL;
}
return r;
}
......
......@@ -986,7 +986,8 @@ static void AddDeviceLuks(void)
OK_(get_luks_offsets(0, key_size, params.data_alignment, 0, NULL, &r_payload_offset));
OK_(create_dmdevice_over_loop(L_DEVICE_0S, r_payload_offset));
OK_(create_dmdevice_over_loop(L_DEVICE_1S, r_payload_offset + 1));
OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_payload_offset - 1));
//OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, r_payload_offset - 1));
OK_(create_dmdevice_over_loop(L_DEVICE_WRONG, 2050 - 1)); //FIXME last keyslot - 1 sector
// 1 sector less than required
OK_(crypt_init(&cd, DMDIR L_DEVICE_WRONG));
......@@ -1298,8 +1299,10 @@ static void LuksHeaderLoad(void)
// external header device
OK_(create_dmdevice_over_loop(H_DEVICE, r_header_size));
// prepared header on a device too small to contain header and payload
OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_payload_offset - 1));
snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%" PRIu64, r_payload_offset - 1);
//OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, r_payload_offset - 1));
OK_(create_dmdevice_over_loop(H_DEVICE_WRONG, 2050 - 1)); //FIXME
//snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%" PRIu64, r_payload_offset - 1);
snprintf(cmd, sizeof(cmd), "dd if=" EVL_HEADER_4 " of=" DMDIR H_DEVICE_WRONG " bs=512 count=%" PRIu64, 2050ULL - 1);
OK_(_system(cmd, 1));
// some device
OK_(create_dmdevice_over_loop(L_DEVICE_OK, r_payload_offset + 1000));
......@@ -1342,7 +1345,7 @@ static void LuksHeaderLoad(void)
crypt_free(cd);
// damaged header
OK_(_system("dd if=/dev/zero of=" DMDIR L_DEVICE_0S "bs=512 count=8", 1));
OK_(_system("dd if=/dev/zero of=" DMDIR L_DEVICE_OK " bs=512 count=8", 1));
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
FAIL_(crypt_load(cd, CRYPT_LUKS1, NULL), "Header not found");
crypt_free(cd);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment