Commit c2bce3e9 authored by Milan Broz's avatar Milan Broz

Wipe full header areas (including unused) during LUKS format.

All previous version of cryptsetup wiped only first 4k for LUKS1
and both JSON areas for LUKS2 (first 32k) and the allocated
keyslot area (as it contained the generated key).

Remaining areas (unused keyslots, padding, and alignment) were
not wiped and could contain some previous data.

Since this commit, the whole area up to the data offset is zeroed,
and subsequently, all keyslots areas are wiped with random data.

Only exceptions are
 - padding/alignment areas for detached header
   if the data offset is set to 0
 - bogus LUKS1 keyslot areas (upstream code never
   created such keyslots but someone could use that).

This operation could slow down luksFormat on some devices, but
it guarantees that after this operation LUKS header does not
contain any foreign data.
parent a46733e7
...@@ -1210,3 +1210,56 @@ int LUKS1_activate(struct crypt_device *cd, ...@@ -1210,3 +1210,56 @@ int LUKS1_activate(struct crypt_device *cd,
free(dm_cipher); free(dm_cipher);
return r; return r;
} }
int LUKS_wipe_header_areas(struct luks_phdr *hdr,
struct crypt_device *ctx)
{
int i, r;
uint64_t offset, length;
size_t wipe_block;
/* Wipe complete header, keyslots and padding aread with zeroes. */
offset = 0;
length = hdr->payloadOffset * SECTOR_SIZE;
wipe_block = 1024 * 1024;
/* On detached header or bogus header, wipe at least the first 4k */
if (length == 0 || length > (LUKS_MAX_KEYSLOT_SIZE * LUKS_NUMKEYS)) {
length = 4096;
wipe_block = 4096;
}
log_dbg("Wiping LUKS areas (0x%06" PRIx64 " - 0x%06" PRIx64") with zeroes.",
offset, length + offset);
r = crypt_wipe_device(ctx, crypt_metadata_device(ctx), CRYPT_WIPE_ZERO,
offset, length, wipe_block, NULL, NULL);
if (r < 0)
return r;
/* Wipe keyslots areas */
wipe_block = 1024 * 1024;
for (i = 0; i < LUKS_NUMKEYS; i++) {
r = LUKS_keyslot_area(hdr, i, &offset, &length);
if (r < 0)
return r;
/* Ignore too big LUKS1 keyslots here */
if (length > LUKS_MAX_KEYSLOT_SIZE ||
offset > (LUKS_MAX_KEYSLOT_SIZE - length))
continue;
if (length == 0 || offset < 4096)
return -EINVAL;
log_dbg("Wiping keyslot %i area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.",
i, offset, length + offset);
r = crypt_wipe_device(ctx, crypt_metadata_device(ctx), CRYPT_WIPE_RANDOM,
offset, length, wipe_block, NULL, NULL);
if (r < 0)
return r;
}
return r;
}
...@@ -61,6 +61,9 @@ ...@@ -61,6 +61,9 @@
/* Offset to keyslot area [in bytes] */ /* Offset to keyslot area [in bytes] */
#define LUKS_ALIGN_KEYSLOTS 4096 #define LUKS_ALIGN_KEYSLOTS 4096
/* Maximal LUKS header size, for wipe [in bytes] */
#define LUKS_MAX_KEYSLOT_SIZE 0x1000000 /* 16 MB, up to 32768 bits key */
/* Any integer values are stored in network byte order on disk and must be /* Any integer values are stored in network byte order on disk and must be
converted */ converted */
...@@ -168,6 +171,9 @@ int LUKS_del_key( ...@@ -168,6 +171,9 @@ int LUKS_del_key(
struct luks_phdr *hdr, struct luks_phdr *hdr,
struct crypt_device *ctx); struct crypt_device *ctx);
int LUKS_wipe_header_areas(struct luks_phdr *hdr,
struct crypt_device *ctx);
crypt_keyslot_info LUKS_keyslot_info(struct luks_phdr *hdr, int keyslot); crypt_keyslot_info LUKS_keyslot_info(struct luks_phdr *hdr, int keyslot);
int LUKS_keyslot_find_empty(struct luks_phdr *hdr); int LUKS_keyslot_find_empty(struct luks_phdr *hdr);
int LUKS_keyslot_active_count(struct luks_phdr *hdr); int LUKS_keyslot_active_count(struct luks_phdr *hdr);
......
...@@ -331,6 +331,9 @@ int LUKS2_generate_hdr( ...@@ -331,6 +331,9 @@ int LUKS2_generate_hdr(
unsigned int alignOffset, unsigned int alignOffset,
int detached_metadata_device); int detached_metadata_device);
int LUKS2_wipe_header_areas(struct crypt_device *cd,
struct luks2_hdr *hdr);
uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr); uint64_t LUKS2_get_data_offset(struct luks2_hdr *hdr);
int LUKS2_get_sector_size(struct luks2_hdr *hdr); int LUKS2_get_sector_size(struct luks2_hdr *hdr);
const char *LUKS2_get_cipher(struct luks2_hdr *hdr, int segment); const char *LUKS2_get_cipher(struct luks2_hdr *hdr, int segment);
......
...@@ -229,3 +229,45 @@ int LUKS2_generate_hdr( ...@@ -229,3 +229,45 @@ int LUKS2_generate_hdr(
JSON_DBG(hdr->jobj, "Header JSON"); JSON_DBG(hdr->jobj, "Header JSON");
return 0; return 0;
} }
int LUKS2_wipe_header_areas(struct crypt_device *cd,
struct luks2_hdr *hdr)
{
int r;
uint64_t offset, length;
size_t wipe_block;
/* Wipe complete header, keyslots and padding aread with zeroes. */
offset = 0;
length = LUKS2_get_data_offset(hdr) * SECTOR_SIZE;
wipe_block = 1024 * 1024;
/* On detached header or bogus header wipe at least the first 4k */
if (length == 0 || length > LUKS2_MAX_KEYSLOTS_SIZE) {
length = 4096;
wipe_block = 4096;
}
log_dbg("Wiping LUKS areas (0x%06" PRIx64 " - 0x%06" PRIx64") with zeroes.",
offset, length + offset);
r = crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_ZERO,
offset, length, wipe_block, NULL, NULL);
if (r < 0)
return r;
/* Wipe keyslot area */
wipe_block = 1024 * 1024;
offset = get_min_offset(hdr);
length = LUKS2_keyslots_size(hdr->jobj);
if (length == 0 || length > LUKS2_MAX_KEYSLOTS_SIZE ||
offset < 4096 || offset > (LUKS2_MAX_KEYSLOTS_SIZE - length))
return -EINVAL;
log_dbg("Wiping keyslots area (0x%06" PRIx64 " - 0x%06" PRIx64") with random data.",
offset, length + offset);
return crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_RANDOM,
offset, length, wipe_block, NULL, NULL);
}
...@@ -1474,9 +1474,7 @@ static int _crypt_format_luks1(struct crypt_device *cd, ...@@ -1474,9 +1474,7 @@ static int _crypt_format_luks1(struct crypt_device *cd,
if (r < 0) if (r < 0)
return r; return r;
/* Wipe first 8 sectors - fs magic numbers etc. */ r = LUKS_wipe_header_areas(&cd->u.luks1.hdr, cd);
r = crypt_wipe_device(cd, crypt_metadata_device(cd), CRYPT_WIPE_ZERO, 0,
8 * SECTOR_SIZE, 8 * SECTOR_SIZE, NULL, NULL);
if (r < 0) { if (r < 0) {
log_err(cd, _("Cannot wipe header on device %s."), log_err(cd, _("Cannot wipe header on device %s."),
mdata_device_path(cd)); mdata_device_path(cd));
...@@ -1613,6 +1611,13 @@ static int _crypt_format_luks2(struct crypt_device *cd, ...@@ -1613,6 +1611,13 @@ static int _crypt_format_luks2(struct crypt_device *cd,
goto out; goto out;
} }
r = LUKS2_wipe_header_areas(cd, &cd->u.luks2.hdr);
if (r < 0) {
log_err(cd, _("Cannot wipe header on device %s."),
mdata_device_path(cd));
goto out;
}
/* Wipe integrity superblock and create integrity superblock */ /* Wipe integrity superblock and create integrity superblock */
if (crypt_get_integrity_tag_size(cd)) { if (crypt_get_integrity_tag_size(cd)) {
r = crypt_wipe_device(cd, crypt_data_device(cd), CRYPT_WIPE_ZERO, r = crypt_wipe_device(cd, crypt_data_device(cd), CRYPT_WIPE_ZERO,
......
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