bitlk: Fix support for startup key with new metadata entry

Windows 11 now includes the BitLocker volume GUID in the BEK file
metadata entries. This was previously not included so cryptsetup
refused to open the file because there was an unknown metadata
entry in the startup key.

Fixes: #690
This commit is contained in:
Vojtech Trefny
2021-11-28 17:02:01 +01:00
parent 1c36ddfe73
commit 6eae9f6e91
3 changed files with 24 additions and 7 deletions

View File

@@ -869,13 +869,20 @@ static int get_recovery_key(struct crypt_device *cd,
return 0; return 0;
} }
static int parse_external_key_entry(struct crypt_device *cd, const char *data, int start, int end, struct volume_key **vk) static int parse_external_key_entry(struct crypt_device *cd,
const char *data,
int start,
int end,
struct volume_key **vk,
const struct bitlk_metadata *params)
{ {
uint16_t key_entry_size = 0; uint16_t key_entry_size = 0;
uint16_t key_entry_type = 0; uint16_t key_entry_type = 0;
uint16_t key_entry_value = 0; uint16_t key_entry_value = 0;
size_t key_size = 0; size_t key_size = 0;
const char *key = NULL; const char *key = NULL;
struct bitlk_guid guid;
char guid_buf[UUID_STR_LEN] = {0};
while (end - start > 2) { while (end - start > 2) {
/* size of this entry */ /* size of this entry */
@@ -892,8 +899,7 @@ static int parse_external_key_entry(struct crypt_device *cd, const char *data, i
key_entry_type = le16_to_cpu(key_entry_type); key_entry_type = le16_to_cpu(key_entry_type);
key_entry_value = le16_to_cpu(key_entry_value); key_entry_value = le16_to_cpu(key_entry_value);
/* only properties should be in this entry */ if (key_entry_type != BITLK_ENTRY_TYPE_PROPERTY && key_entry_type != BITLK_ENTRY_TYPE_VOLUME_GUID) {
if (key_entry_type != BITLK_ENTRY_TYPE_PROPERTY) {
log_err(cd, _("Unexpected metadata entry type '%u' found when parsing external key."), key_entry_type); log_err(cd, _("Unexpected metadata entry type '%u' found when parsing external key."), key_entry_type);
return -EINVAL; return -EINVAL;
} }
@@ -908,7 +914,15 @@ static int parse_external_key_entry(struct crypt_device *cd, const char *data, i
/* optional "ExternalKey" string, we can safely ignore it */ /* optional "ExternalKey" string, we can safely ignore it */
} else if (key_entry_value == BITLK_ENTRY_VALUE_STRING) } else if (key_entry_value == BITLK_ENTRY_VALUE_STRING)
; ;
else { /* GUID of the BitLocker device we are trying to open with this key */
else if (key_entry_value == BITLK_ENTRY_VALUE_GUID) {
memcpy(&guid, data + start + BITLK_ENTRY_HEADER_LEN, sizeof(struct bitlk_guid));
guid_to_string(&guid, guid_buf);
if (strcmp(guid_buf, params->guid) != 0) {
log_err(cd, _("BEK file GUID '%s' does not match GUID of the volume."), guid_buf);
return -EINVAL;
}
} else {
log_err(cd, _("Unexpected metadata entry value '%u' found when parsing external key."), key_entry_value); log_err(cd, _("Unexpected metadata entry value '%u' found when parsing external key."), key_entry_value);
return -EINVAL; return -EINVAL;
} }
@@ -925,7 +939,8 @@ static int get_startup_key(struct crypt_device *cd,
const char *password, const char *password,
size_t passwordLen, size_t passwordLen,
const struct bitlk_vmk *vmk, const struct bitlk_vmk *vmk,
struct volume_key **su_key) struct volume_key **su_key,
const struct bitlk_metadata *params)
{ {
struct bitlk_bek_header bek_header = {0}; struct bitlk_bek_header bek_header = {0};
char guid_buf[UUID_STR_LEN] = {0}; char guid_buf[UUID_STR_LEN] = {0};
@@ -975,7 +990,7 @@ static int get_startup_key(struct crypt_device *cd,
if (key_entry_type == BITLK_ENTRY_TYPE_STARTUP_KEY && key_entry_value == BITLK_ENTRY_VALUE_EXTERNAL_KEY) { if (key_entry_type == BITLK_ENTRY_TYPE_STARTUP_KEY && key_entry_value == BITLK_ENTRY_VALUE_EXTERNAL_KEY) {
return parse_external_key_entry(cd, password, return parse_external_key_entry(cd, password,
BITLK_BEK_FILE_HEADER_LEN + BITLK_ENTRY_HEADER_LEN + BITLK_STARTUP_KEY_HEADER_LEN, BITLK_BEK_FILE_HEADER_LEN + BITLK_ENTRY_HEADER_LEN + BITLK_STARTUP_KEY_HEADER_LEN,
passwordLen, su_key); passwordLen, su_key, params);
} else { } else {
log_err(cd, _("Unexpected metadata entry found when parsing startup key.")); log_err(cd, _("Unexpected metadata entry found when parsing startup key."));
log_dbg(cd, "Entry type: %u, entry value: %u", key_entry_type, key_entry_value); log_dbg(cd, "Entry type: %u, entry value: %u", key_entry_type, key_entry_value);
@@ -1142,7 +1157,7 @@ int BITLK_get_volume_key(struct crypt_device *cd,
if (r) if (r)
return r; return r;
} else if (next_vmk->protection == BITLK_PROTECTION_STARTUP_KEY) { } else if (next_vmk->protection == BITLK_PROTECTION_STARTUP_KEY) {
r = get_startup_key(cd, password, passwordLen, next_vmk, &vmk_dec_key); r = get_startup_key(cd, password, passwordLen, next_vmk, &vmk_dec_key, params);
if (r) { if (r) {
next_vmk = next_vmk->next; next_vmk = next_vmk->next;
continue; continue;

View File

@@ -61,6 +61,7 @@ typedef enum {
BITLK_ENTRY_TYPE_STARTUP_KEY = 0x0006, BITLK_ENTRY_TYPE_STARTUP_KEY = 0x0006,
BITLK_ENTRY_TYPE_DESCRIPTION = 0x0007, BITLK_ENTRY_TYPE_DESCRIPTION = 0x0007,
BITLK_ENTRY_TYPE_VOLUME_HEADER = 0x000f, BITLK_ENTRY_TYPE_VOLUME_HEADER = 0x000f,
BITLK_ENTRY_TYPE_VOLUME_GUID = 0x0019,
} BITLKFVEEntryType; } BITLKFVEEntryType;
typedef enum { typedef enum {
@@ -76,6 +77,7 @@ typedef enum {
BITLK_ENTRY_VALUE_EXTERNAL_KEY = 0x0009, BITLK_ENTRY_VALUE_EXTERNAL_KEY = 0x0009,
BITLK_ENTRY_VALUE_OFFSET_SIZE = 0x000f, BITLK_ENTRY_VALUE_OFFSET_SIZE = 0x000f,
BITLK_ENTRY_VALUE_RECOVERY_TIME = 0x015, BITLK_ENTRY_VALUE_RECOVERY_TIME = 0x015,
BITLK_ENTRY_VALUE_GUID = 0x0017,
} BITLKFVEEntryValue; } BITLKFVEEntryValue;
struct bitlk_vmk { struct bitlk_vmk {

Binary file not shown.