mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-11 10:50:01 +01:00
Fix parsing BitLocker metadata on Big Endian architectures
This commit is contained in:
committed by
Milan Broz
parent
97e39f0744
commit
b43429e684
@@ -202,7 +202,7 @@ static int convert_to_utf8(struct crypt_device *cd, uint8_t *input, size_t inlen
|
|||||||
memset(outbuf, 0, inlen);
|
memset(outbuf, 0, inlen);
|
||||||
ic_outbuf = outbuf;
|
ic_outbuf = outbuf;
|
||||||
|
|
||||||
ic = iconv_open("UTF-8", "UTF-16");
|
ic = iconv_open("UTF-8", "UTF-16LE");
|
||||||
r = iconv(ic, (char **) &input, &ic_inlen, &ic_outbuf, &ic_outlen);
|
r = iconv(ic, (char **) &input, &ic_inlen, &ic_outbuf, &ic_outlen);
|
||||||
iconv_close(ic);
|
iconv_close(ic);
|
||||||
|
|
||||||
@@ -262,6 +262,7 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
|
|||||||
while (end - start > 2) {
|
while (end - start > 2) {
|
||||||
/* size of this entry */
|
/* size of this entry */
|
||||||
memcpy(&key_entry_size, data + start, sizeof(key_entry_size));
|
memcpy(&key_entry_size, data + start, sizeof(key_entry_size));
|
||||||
|
key_entry_size = le16_to_cpu(key_entry_size);
|
||||||
if (key_entry_size == 0)
|
if (key_entry_size == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -270,6 +271,8 @@ static int parse_vmk_entry(struct crypt_device *cd, uint8_t *data, int start, in
|
|||||||
memcpy(&key_entry_value,
|
memcpy(&key_entry_value,
|
||||||
data + start + sizeof(key_entry_size) + sizeof(key_entry_type),
|
data + start + sizeof(key_entry_size) + sizeof(key_entry_type),
|
||||||
sizeof(key_entry_value));
|
sizeof(key_entry_value));
|
||||||
|
key_entry_type = le16_to_cpu(key_entry_type);
|
||||||
|
key_entry_value = le16_to_cpu(key_entry_value);
|
||||||
|
|
||||||
if (key_entry_type != BITLK_ENTRY_TYPE_PROPERTY) {
|
if (key_entry_type != BITLK_ENTRY_TYPE_PROPERTY) {
|
||||||
log_err(cd, _("Unexpected metadata entry found when parsing VMK."));
|
log_err(cd, _("Unexpected metadata entry found when parsing VMK."));
|
||||||
@@ -365,6 +368,8 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||||||
struct bitlk_fve_metadata fve = {};
|
struct bitlk_fve_metadata fve = {};
|
||||||
struct bitlk_entry_vmk entry_vmk = {};
|
struct bitlk_entry_vmk entry_vmk = {};
|
||||||
uint8_t *fve_entries = NULL;
|
uint8_t *fve_entries = NULL;
|
||||||
|
uint16_t fve_size = 0;
|
||||||
|
uint32_t fve_metadata_size = 0;
|
||||||
int fve_offset = 0;
|
int fve_offset = 0;
|
||||||
char guid_buf[UUID_STR_LEN] = {0};
|
char guid_buf[UUID_STR_LEN] = {0};
|
||||||
uint16_t entry_size = 0;
|
uint16_t entry_size = 0;
|
||||||
@@ -425,24 +430,27 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
params->metadata_offset[i] = le64_to_cpu(sb.fve_offset[i]);
|
||||||
|
|
||||||
log_dbg(cd, "Reading BitLocker FVE metadata of size %zu on device %s, offset %" PRIu64 ".",
|
log_dbg(cd, "Reading BitLocker FVE metadata of size %zu on device %s, offset %" PRIu64 ".",
|
||||||
sizeof(fve), device_path(device), sb.fve_offset[0]);
|
sizeof(fve), device_path(device), params->metadata_offset[0]);
|
||||||
|
|
||||||
/* read FVE metadata from the first metadata area */
|
/* read FVE metadata from the first metadata area */
|
||||||
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
|
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
|
||||||
device_alignment(device), &fve, sizeof(fve), sb.fve_offset[0]) != sizeof(fve) ||
|
device_alignment(device), &fve, sizeof(fve), params->metadata_offset[0]) != sizeof(fve) ||
|
||||||
memcmp(fve.signature, BITLK_SIGNATURE, sizeof(fve.signature)) ||
|
memcmp(fve.signature, BITLK_SIGNATURE, sizeof(fve.signature)) ||
|
||||||
fve.fve_version != 2) {
|
le16_to_cpu(fve.fve_version) != 2) {
|
||||||
log_err(cd, _("Failed to read BitLocker FVE metadata from %s."), device_path(device));
|
log_err(cd, _("Failed to read BitLocker FVE metadata from %s."), device_path(device));
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
params->metadata_version = le32_to_cpu(fve.fve_version);
|
params->metadata_version = le16_to_cpu(fve.fve_version);
|
||||||
for (i = 0; i < 3; i++)
|
fve_size = le16_to_cpu(fve.fve_size);
|
||||||
params->metadata_offset[i] = le64_to_cpu(sb.fve_offset[i]);
|
fve_metadata_size = le32_to_cpu(fve.metadata_size);
|
||||||
|
|
||||||
switch (fve.encryption) {
|
switch (le16_to_cpu(fve.encryption)) {
|
||||||
/* AES-CBC with Elephant difuser */
|
/* AES-CBC with Elephant difuser */
|
||||||
case 0x8000:
|
case 0x8000:
|
||||||
params->key_size = 128;
|
params->key_size = 128;
|
||||||
@@ -496,34 +504,36 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||||||
params->creation_time = filetime_to_unixtime(le64_to_cpu(fve.creation_time));
|
params->creation_time = filetime_to_unixtime(le64_to_cpu(fve.creation_time));
|
||||||
|
|
||||||
/* read and parse all FVE metadata entries */
|
/* read and parse all FVE metadata entries */
|
||||||
fve_entries = malloc(fve.metadata_size - fve.fve_size);
|
fve_entries = malloc(fve_metadata_size - fve_size);
|
||||||
if (!fve_entries) {
|
if (!fve_entries) {
|
||||||
r = -ENOMEM;
|
r = -ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
memset(fve_entries, 0, (fve.metadata_size - fve.fve_size));
|
memset(fve_entries, 0, (fve_metadata_size - fve_size));
|
||||||
|
|
||||||
log_dbg(cd, "Reading BitLocker FVE metadata entries of size %" PRIu32 " on device %s, offset %" PRIu64 ".",
|
log_dbg(cd, "Reading BitLocker FVE metadata entries of size %" PRIu32 " on device %s, offset %" PRIu64 ".",
|
||||||
fve.metadata_size - fve.fve_size, device_path(device),
|
fve_metadata_size - fve_size, device_path(device),
|
||||||
sb.fve_offset[0] + BITLK_FVE_METADATA_HEADER_LEN);
|
params->metadata_offset[0] + BITLK_FVE_METADATA_HEADER_LEN);
|
||||||
|
|
||||||
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
|
if (read_lseek_blockwise(devfd, device_block_size(cd, device),
|
||||||
device_alignment(device), fve_entries, fve.metadata_size - fve.fve_size,
|
device_alignment(device), fve_entries, fve_metadata_size - fve_size,
|
||||||
sb.fve_offset[0] + BITLK_FVE_METADATA_HEADER_LEN) != fve.metadata_size - fve.fve_size) {
|
params->metadata_offset[0] + BITLK_FVE_METADATA_HEADER_LEN) != fve_metadata_size - fve_size) {
|
||||||
log_err(cd, _("Failed to read BitLocker metadata entries from %s."), device_path(device));
|
log_err(cd, _("Failed to read BitLocker metadata entries from %s."), device_path(device));
|
||||||
r = -EINVAL;
|
r = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
end = fve.metadata_size - fve.fve_size;
|
end = fve_metadata_size - fve_size;
|
||||||
while (end - start > 2) {
|
while (end - start > 2) {
|
||||||
/* size of this entry */
|
/* size of this entry */
|
||||||
memcpy(&entry_size, fve_entries + start, sizeof(entry_size));
|
memcpy(&entry_size, fve_entries + start, sizeof(entry_size));
|
||||||
|
entry_size = le16_to_cpu(entry_size);
|
||||||
if (entry_size == 0)
|
if (entry_size == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* type of this entry */
|
/* type of this entry */
|
||||||
memcpy(&entry_type, fve_entries + start + sizeof(entry_size), sizeof(entry_type));
|
memcpy(&entry_type, fve_entries + start + sizeof(entry_size), sizeof(entry_type));
|
||||||
|
entry_type = le16_to_cpu(entry_type);
|
||||||
|
|
||||||
/* VMK */
|
/* VMK */
|
||||||
if (entry_type == BITLK_ENTRY_TYPE_VMK) {
|
if (entry_type == BITLK_ENTRY_TYPE_VMK) {
|
||||||
@@ -538,7 +548,7 @@ int BITLK_read_sb(struct crypt_device *cd, struct bitlk_metadata *params)
|
|||||||
guid_to_string(&entry_vmk.guid, guid_buf);
|
guid_to_string(&entry_vmk.guid, guid_buf);
|
||||||
vmk->guid = strdup (guid_buf);
|
vmk->guid = strdup (guid_buf);
|
||||||
|
|
||||||
vmk->protection = get_vmk_protection(entry_vmk.protection);
|
vmk->protection = get_vmk_protection(le16_to_cpu(entry_vmk.protection));
|
||||||
|
|
||||||
/* more data in another entry list */
|
/* more data in another entry list */
|
||||||
r = parse_vmk_entry(cd, fve_entries,
|
r = parse_vmk_entry(cd, fve_entries,
|
||||||
@@ -758,7 +768,7 @@ static int bitlk_kdf(struct crypt_device *cd,
|
|||||||
r = crypt_hash_final(hd, kdf.last_sha256, len);
|
r = crypt_hash_final(hd, kdf.last_sha256, len);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto out;
|
goto out;
|
||||||
kdf.count++;
|
kdf.count = cpu_to_le64(le64_to_cpu(kdf.count) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
*vk = crypt_alloc_volume_key(len, kdf.last_sha256);
|
*vk = crypt_alloc_volume_key(len, kdf.last_sha256);
|
||||||
@@ -779,6 +789,7 @@ static int decrypt_key(struct crypt_device *cd,
|
|||||||
{
|
{
|
||||||
char *outbuf;
|
char *outbuf;
|
||||||
int r;
|
int r;
|
||||||
|
uint32_t key_size = 0;
|
||||||
|
|
||||||
outbuf = crypt_safe_alloc(enc_key->keylength);
|
outbuf = crypt_safe_alloc(enc_key->keylength);
|
||||||
if (!outbuf)
|
if (!outbuf)
|
||||||
@@ -794,7 +805,8 @@ static int decrypt_key(struct crypt_device *cd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* key_data has it's size as part of the metadata */
|
/* key_data has it's size as part of the metadata */
|
||||||
if (enc_key->keylength == le32_to_cpu((uint32_t)*outbuf)) {
|
memcpy(&key_size, outbuf, 4);
|
||||||
|
if (enc_key->keylength == le32_to_cpu(key_size)) {
|
||||||
*vk = crypt_alloc_volume_key(enc_key->keylength - BITLK_OPEN_KEY_METADATA_LEN,
|
*vk = crypt_alloc_volume_key(enc_key->keylength - BITLK_OPEN_KEY_METADATA_LEN,
|
||||||
(const char *)(outbuf + BITLK_OPEN_KEY_METADATA_LEN));
|
(const char *)(outbuf + BITLK_OPEN_KEY_METADATA_LEN));
|
||||||
r = *vk ? 0 : -ENOMEM;
|
r = *vk ? 0 : -ENOMEM;
|
||||||
|
|||||||
Reference in New Issue
Block a user