mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-16 05:10:03 +01:00
Do not hardcode number of DM segments for BitLocker devices
Sometimes there is no gap between the metadata so we don't want to create a dm-crypt segment there.
This commit is contained in:
committed by
Milan Broz
parent
5ec2fbcd38
commit
834059ddfa
@@ -52,6 +52,8 @@
|
|||||||
#define BITLK_KDF_HASH "sha256"
|
#define BITLK_KDF_HASH "sha256"
|
||||||
#define BITLK_KDF_ITERATION_COUNT 0x100000
|
#define BITLK_KDF_ITERATION_COUNT 0x100000
|
||||||
|
|
||||||
|
/* maximum number of segments for the DM device */
|
||||||
|
#define MAX_BITLK_SEGMENTS 10
|
||||||
|
|
||||||
/* January 1, 1970 as MS file time */
|
/* January 1, 1970 as MS file time */
|
||||||
#define EPOCH_AS_FILETIME 116444736000000000
|
#define EPOCH_AS_FILETIME 116444736000000000
|
||||||
@@ -83,6 +85,18 @@ static void guid_to_string(struct bitlk_guid *guid, char *out) {
|
|||||||
uuid_unparse((unsigned char *) guid, out);
|
uuid_unparse((unsigned char *) guid, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BITLK_SEGTYPE_CRYPT,
|
||||||
|
BITLK_SEGTYPE_ZERO,
|
||||||
|
} BitlkSegmentType;
|
||||||
|
|
||||||
|
struct segment {
|
||||||
|
uint64_t offset;
|
||||||
|
uint64_t length;
|
||||||
|
uint64_t iv_offset;
|
||||||
|
BitlkSegmentType type;
|
||||||
|
};
|
||||||
|
|
||||||
struct bitlk_signature {
|
struct bitlk_signature {
|
||||||
uint8_t boot_code[3];
|
uint8_t boot_code[3];
|
||||||
uint8_t signature[8];
|
uint8_t signature[8];
|
||||||
@@ -830,8 +844,10 @@ int BITLK_activate(struct crypt_device *cd,
|
|||||||
uint32_t flags)
|
uint32_t flags)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
uint64_t start = 0;
|
int i = 0;
|
||||||
uint64_t size = 0;
|
int j = 0;
|
||||||
|
int min = 0;
|
||||||
|
int num_segments = 0;
|
||||||
struct crypt_dm_active_device dmd = {
|
struct crypt_dm_active_device dmd = {
|
||||||
.flags = flags,
|
.flags = flags,
|
||||||
};
|
};
|
||||||
@@ -841,6 +857,11 @@ int BITLK_activate(struct crypt_device *cd,
|
|||||||
struct volume_key *vmk_dec_key = NULL;
|
struct volume_key *vmk_dec_key = NULL;
|
||||||
struct volume_key *recovery_key = NULL;
|
struct volume_key *recovery_key = NULL;
|
||||||
const struct bitlk_vmk *next_vmk = NULL;
|
const struct bitlk_vmk *next_vmk = NULL;
|
||||||
|
struct segment segments[MAX_BITLK_SEGMENTS] = {};
|
||||||
|
struct segment temp;
|
||||||
|
uint64_t next_start = 0;
|
||||||
|
uint64_t next_end = 0;
|
||||||
|
uint64_t last_segment = 0;
|
||||||
|
|
||||||
next_vmk = params->vmks;
|
next_vmk = params->vmks;
|
||||||
while (next_vmk) {
|
while (next_vmk) {
|
||||||
@@ -939,130 +960,118 @@ int BITLK_activate(struct crypt_device *cd,
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = dm_targets_allocate(&dmd.segment, 9);
|
/* there will be always 4 dm-zero segments: 3x metadata, 1x FS header */
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
segments[num_segments].offset = params->metadata_offset[i] / SECTOR_SIZE;
|
||||||
|
segments[num_segments].length = BITLK_FVE_METADATA_SIZE / SECTOR_SIZE;
|
||||||
|
segments[num_segments].iv_offset = 0;
|
||||||
|
segments[num_segments].type = BITLK_SEGTYPE_ZERO;
|
||||||
|
num_segments++;
|
||||||
|
}
|
||||||
|
segments[num_segments].offset = params->volume_header_offset / SECTOR_SIZE;
|
||||||
|
segments[num_segments].length = params->volume_header_size / SECTOR_SIZE;
|
||||||
|
segments[num_segments].iv_offset = 0;
|
||||||
|
segments[num_segments].type = BITLK_SEGTYPE_ZERO;
|
||||||
|
num_segments++;
|
||||||
|
|
||||||
|
/* filesystem header (moved from the special location) */
|
||||||
|
segments[num_segments].offset = 0;
|
||||||
|
segments[num_segments].length = params->volume_header_size / SECTOR_SIZE;
|
||||||
|
segments[num_segments].iv_offset = params->volume_header_offset / SECTOR_SIZE;
|
||||||
|
segments[num_segments].type = BITLK_SEGTYPE_CRYPT;
|
||||||
|
num_segments++;
|
||||||
|
|
||||||
|
/* now fill gaps between the dm-zero segments with dm-crypt */
|
||||||
|
last_segment = params->volume_header_size / SECTOR_SIZE;
|
||||||
|
while (true) {
|
||||||
|
next_start = dmd.size;
|
||||||
|
next_end = dmd.size;
|
||||||
|
|
||||||
|
/* start of the next segment: end of the first existing segment after the last added */
|
||||||
|
for (i = 0; i < num_segments; i++)
|
||||||
|
if (segments[i].offset + segments[i].length < next_start && segments[i].offset + segments[i].length >= last_segment)
|
||||||
|
next_start = segments[i].offset + segments[i].length;
|
||||||
|
|
||||||
|
/* end of the next segment: start of the next segment after start we found above */
|
||||||
|
for (i = 0; i < num_segments; i++)
|
||||||
|
if (segments[i].offset < next_end && segments[i].offset >= next_start)
|
||||||
|
next_end = segments[i].offset;
|
||||||
|
|
||||||
|
/* two zero segments next to each other, just bump the last_segment
|
||||||
|
so the algorithm moves */
|
||||||
|
if (next_end - next_start == 0) {
|
||||||
|
last_segment = next_end + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
segments[num_segments].offset = next_start;
|
||||||
|
segments[num_segments].length = next_end - next_start;
|
||||||
|
segments[num_segments].iv_offset = next_start;
|
||||||
|
segments[num_segments].type = BITLK_SEGTYPE_CRYPT;
|
||||||
|
last_segment = next_end;
|
||||||
|
num_segments++;
|
||||||
|
|
||||||
|
if (next_end == dmd.size)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (num_segments == 10) {
|
||||||
|
log_err(cd, "Failed to calculate number of dm-crypt segments for open.");
|
||||||
|
r = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* device mapper needs the segment sorted */
|
||||||
|
for (i = 0; i < num_segments - 1; i++) {
|
||||||
|
min = i;
|
||||||
|
for (j = i + 1; j < num_segments; j++)
|
||||||
|
if (segments[j].offset < segments[min].offset)
|
||||||
|
min = j;
|
||||||
|
|
||||||
|
if (min != i) {
|
||||||
|
temp.offset = segments[min].offset;
|
||||||
|
temp.length = segments[min].length;
|
||||||
|
temp.iv_offset = segments[min].iv_offset;
|
||||||
|
temp.type = segments[min].type;
|
||||||
|
|
||||||
|
segments[min].offset = segments[i].offset;
|
||||||
|
segments[min].length = segments[i].length;
|
||||||
|
segments[min].iv_offset = segments[i].iv_offset;
|
||||||
|
segments[min].type = segments[i].type;
|
||||||
|
|
||||||
|
segments[i].offset = temp.offset;
|
||||||
|
segments[i].length = temp.length;
|
||||||
|
segments[i].iv_offset = temp.iv_offset;
|
||||||
|
segments[i].type = temp.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r = dm_targets_allocate(&dmd.segment, num_segments);
|
||||||
if (r)
|
if (r)
|
||||||
goto out;
|
goto out;
|
||||||
next_segment = &dmd.segment;
|
next_segment = &dmd.segment;
|
||||||
|
|
||||||
/* filesystem header (moved from the special location) */
|
for (i = 0; i < num_segments; i++) {
|
||||||
start = 0;
|
if (segments[i].type == BITLK_SEGTYPE_ZERO)
|
||||||
size = params->volume_header_size / SECTOR_SIZE;
|
r = dm_zero_target_set(next_segment,
|
||||||
r = dm_crypt_target_set(next_segment,
|
segments[i].offset,
|
||||||
start, size,
|
segments[i].length);
|
||||||
crypt_data_device(cd),
|
else if (segments[i].type == BITLK_SEGTYPE_CRYPT)
|
||||||
open_fvek_key,
|
r = dm_crypt_target_set(next_segment,
|
||||||
crypt_get_cipher_spec(cd),
|
segments[i].offset,
|
||||||
params->volume_header_offset / SECTOR_SIZE,
|
segments[i].length,
|
||||||
params->volume_header_offset / SECTOR_SIZE,
|
crypt_data_device(cd),
|
||||||
NULL, 0,
|
open_fvek_key,
|
||||||
SECTOR_SIZE);
|
crypt_get_cipher_spec(cd),
|
||||||
if (r)
|
segments[i].iv_offset,
|
||||||
goto out;
|
segments[i].iv_offset,
|
||||||
start += size;
|
NULL, 0,
|
||||||
next_segment = next_segment->next;
|
SECTOR_SIZE);
|
||||||
|
if (r)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
next_segment = next_segment->next;
|
||||||
/* first data part up to the first fve header */
|
}
|
||||||
size = (params->metadata_offset[0] / SECTOR_SIZE) - start;
|
|
||||||
r = dm_crypt_target_set(next_segment,
|
|
||||||
start, size,
|
|
||||||
crypt_data_device(cd),
|
|
||||||
open_fvek_key,
|
|
||||||
crypt_get_cipher_spec(cd),
|
|
||||||
start,
|
|
||||||
start,
|
|
||||||
NULL, 0,
|
|
||||||
SECTOR_SIZE);
|
|
||||||
if (r)
|
|
||||||
goto out;
|
|
||||||
start += size;
|
|
||||||
next_segment = next_segment->next;
|
|
||||||
|
|
||||||
/* zeroes instead of the first fve header */
|
|
||||||
size = BITLK_FVE_METADATA_SIZE / SECTOR_SIZE;
|
|
||||||
r = dm_zero_target_set(next_segment,
|
|
||||||
start,
|
|
||||||
size);
|
|
||||||
if (r)
|
|
||||||
goto out;
|
|
||||||
start += size;
|
|
||||||
next_segment = next_segment->next;
|
|
||||||
|
|
||||||
/* zeroes instead of the the encrypted filesystem header */
|
|
||||||
size = params->volume_header_size / SECTOR_SIZE;
|
|
||||||
r = dm_zero_target_set(next_segment,
|
|
||||||
start,
|
|
||||||
size);
|
|
||||||
if (r)
|
|
||||||
goto out;
|
|
||||||
start += size;
|
|
||||||
next_segment = next_segment->next;
|
|
||||||
|
|
||||||
/* second data part up to the second fve header */
|
|
||||||
size = (params->metadata_offset[1] / SECTOR_SIZE) - start;
|
|
||||||
r = dm_crypt_target_set(next_segment,
|
|
||||||
start, size,
|
|
||||||
crypt_data_device(cd),
|
|
||||||
open_fvek_key,
|
|
||||||
crypt_get_cipher_spec(cd),
|
|
||||||
start,
|
|
||||||
start,
|
|
||||||
NULL, 0,
|
|
||||||
SECTOR_SIZE);
|
|
||||||
if (r)
|
|
||||||
goto out;
|
|
||||||
start += size;
|
|
||||||
next_segment = next_segment->next;
|
|
||||||
|
|
||||||
/* zeroes instead of the second fve header */
|
|
||||||
size = BITLK_FVE_METADATA_SIZE / SECTOR_SIZE;
|
|
||||||
r = dm_zero_target_set(next_segment,
|
|
||||||
start,
|
|
||||||
size);
|
|
||||||
if (r)
|
|
||||||
goto out;
|
|
||||||
start += size;
|
|
||||||
next_segment = next_segment->next;
|
|
||||||
|
|
||||||
/* third data part up to the third fve header */
|
|
||||||
size = (params->metadata_offset[2] / SECTOR_SIZE) - start;
|
|
||||||
r = dm_crypt_target_set(next_segment,
|
|
||||||
start, size,
|
|
||||||
crypt_data_device(cd),
|
|
||||||
open_fvek_key,
|
|
||||||
crypt_get_cipher_spec(cd),
|
|
||||||
start,
|
|
||||||
start,
|
|
||||||
NULL, 0,
|
|
||||||
SECTOR_SIZE);
|
|
||||||
if (r)
|
|
||||||
goto out;
|
|
||||||
start += size;
|
|
||||||
next_segment = next_segment->next;
|
|
||||||
|
|
||||||
/* zeroes instead of the third fve header */
|
|
||||||
size = BITLK_FVE_METADATA_SIZE / SECTOR_SIZE;
|
|
||||||
r = dm_zero_target_set(next_segment,
|
|
||||||
start,
|
|
||||||
size);
|
|
||||||
if (r)
|
|
||||||
goto out;
|
|
||||||
start += size;
|
|
||||||
next_segment = next_segment->next;
|
|
||||||
|
|
||||||
/* fourth (and last) part of the data */
|
|
||||||
size = dmd.size - start;
|
|
||||||
r = dm_crypt_target_set(next_segment,
|
|
||||||
start, size,
|
|
||||||
crypt_data_device(cd),
|
|
||||||
open_fvek_key,
|
|
||||||
crypt_get_cipher_spec(cd),
|
|
||||||
start,
|
|
||||||
start,
|
|
||||||
NULL, 0,
|
|
||||||
SECTOR_SIZE);
|
|
||||||
if (r)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
log_dbg(cd, "Trying to activate BITLK on device %s%s%s.\n",
|
log_dbg(cd, "Trying to activate BITLK on device %s%s%s.\n",
|
||||||
device_path(crypt_data_device(cd)), name ? " with name " :"", name ?: "");
|
device_path(crypt_data_device(cd)), name ? " with name " :"", name ?: "");
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user