mirror of
https://github.com/Aorimn/dislocker
synced 2026-06-08 10:24:29 +00:00
370 lines
8.5 KiB
C
370 lines
8.5 KiB
C
/* -*- coding: utf-8 -*- */
|
|
/* -*- mode: c -*- */
|
|
/*
|
|
* Dislocker -- enables to read/write on BitLocker encrypted partitions under
|
|
* Linux
|
|
* Copyright (C) 2012-2013 Romain Coltel, Hervé Schauer Consultants
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
|
* USA.
|
|
*/
|
|
#ifndef DATUM_HEADER_H
|
|
#define DATUM_HEADER_H
|
|
|
|
|
|
#include "dislocker/common.h"
|
|
#include "dislocker/metadata/metadata.h"
|
|
#include "dislocker/metadata/extended_info.h"
|
|
#include "dislocker/metadata/guid.h"
|
|
#include "dislocker/ntfs/clock.h"
|
|
#include "dislocker/ntfs/encoding.h"
|
|
#include "dislocker/encryption/encommon.h"
|
|
|
|
#include <assert.h>
|
|
|
|
#ifndef static_assert
|
|
#define static_assert(x, s) extern int static_assertion[2*!!(x)-1]
|
|
#endif
|
|
|
|
|
|
/**
|
|
* Here stand datums' value types stuff
|
|
*/
|
|
#define NB_DATUMS_VALUE_TYPES 20
|
|
|
|
enum value_types
|
|
{
|
|
/* 0 */ DATUMS_VALUE_ERASED = 0x0000,
|
|
/* 1 */ DATUMS_VALUE_KEY,
|
|
/* 2 */ DATUMS_VALUE_UNICODE,
|
|
/* 3 */ DATUMS_VALUE_STRETCH_KEY,
|
|
/* 4 */ DATUMS_VALUE_USE_KEY,
|
|
/* 5 */ DATUMS_VALUE_AES_CCM,
|
|
/* 6 */ DATUMS_VALUE_TPM_ENCODED,
|
|
/* 7 */ DATUMS_VALUE_VALIDATION,
|
|
/* 8 */ DATUMS_VALUE_VMK,
|
|
/* 9 */ DATUMS_VALUE_EXTERNAL_KEY,
|
|
/* 10 */ DATUMS_VALUE_UPDATE,
|
|
/* 11 */ DATUMS_VALUE_ERROR,
|
|
|
|
/* Below is only available on Windows Seven */
|
|
/* 12 */ DATUMS_VALUE_ASYM_ENC,
|
|
/* 13 */ DATUMS_VALUE_EXPORTED_KEY,
|
|
/* 14 */ DATUMS_VALUE_PUBLIC_KEY,
|
|
/* 15 */ DATUMS_VALUE_VIRTUALIZATION_INFO,
|
|
/* 16 */ DATUMS_VALUE_SIMPLE_1,
|
|
/* 17 */ DATUMS_VALUE_SIMPLE_2,
|
|
/* 18 */ DATUMS_VALUE_CONCAT_HASH_KEY,
|
|
/* 19 */ DATUMS_VALUE_SIMPLE_3
|
|
};
|
|
typedef uint16_t dis_datums_value_type_t;
|
|
|
|
|
|
/* Here are some specifics entry types (second field of the safe header) */
|
|
#define NB_DATUMS_ENTRY_TYPES 12
|
|
|
|
enum entry_types
|
|
{
|
|
DATUMS_ENTRY_UNKNOWN1 = 0x0000,
|
|
DATUMS_ENTRY_UNKNOWN2,
|
|
DATUMS_ENTRY_VMK,
|
|
DATUMS_ENTRY_FVEK,
|
|
DATUMS_ENTRY_UNKNOWN3,
|
|
DATUMS_ENTRY_UNKNOWN4,
|
|
DATUMS_ENTRY_STARTUP_KEY,
|
|
DATUMS_ENTRY_ENCTIME_INFORMATION,
|
|
DATUMS_ENTRY_UNKNOWN7,
|
|
DATUMS_ENTRY_UNKNOWN8,
|
|
DATUMS_ENTRY_UNKNOWN9,
|
|
DATUMS_ENTRY_UNKNOWN10,
|
|
DATUMS_ENTRY_FVEK_2
|
|
};
|
|
typedef uint16_t dis_datums_entry_type_t;
|
|
|
|
|
|
|
|
/**
|
|
* This is the minimal header a datum has
|
|
*/
|
|
#pragma pack (1)
|
|
typedef struct _header_safe
|
|
{
|
|
uint16_t datum_size;
|
|
dis_datums_entry_type_t entry_type;
|
|
dis_datums_value_type_t value_type;
|
|
uint16_t error_status;
|
|
} datum_header_safe_t;
|
|
|
|
static_assert(
|
|
sizeof(struct _header_safe) == 8,
|
|
"Datum header structure's size isn't equal to 8"
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Used if the datum header is not implemented yet, according to the datum type
|
|
*/
|
|
typedef struct _datum_generic
|
|
{
|
|
datum_header_safe_t header;
|
|
// uint8_t* payload;
|
|
} datum_generic_type_t;
|
|
|
|
|
|
|
|
/**
|
|
* Here are datum headers, according to their datum type
|
|
*/
|
|
|
|
/* Datum type = 0 */
|
|
typedef struct _datum_erased
|
|
{
|
|
datum_header_safe_t header;
|
|
} datum_erased_t;
|
|
|
|
|
|
/* Datum type = 1 */
|
|
typedef struct _datum_key
|
|
{
|
|
datum_header_safe_t header;
|
|
cipher_t algo;
|
|
uint16_t padd;
|
|
} datum_key_t;
|
|
|
|
|
|
/* Datum type = 2 */
|
|
typedef struct _datum_unicode
|
|
{
|
|
datum_header_safe_t header;
|
|
} datum_unicode_t;
|
|
|
|
|
|
/* Datum type = 3 */
|
|
typedef struct _datum_stretch_key
|
|
{
|
|
datum_header_safe_t header;
|
|
cipher_t algo;
|
|
uint16_t padd;
|
|
uint8_t salt[16];
|
|
} datum_stretch_key_t;
|
|
|
|
|
|
/* Datum type = 4 */
|
|
typedef struct _datum_use_key
|
|
{
|
|
datum_header_safe_t header;
|
|
cipher_t algo;
|
|
uint16_t padd;
|
|
} datum_use_key_t;
|
|
|
|
|
|
/* Datum type = 5 */
|
|
typedef struct _datum_aes_ccm
|
|
{
|
|
datum_header_safe_t header;
|
|
uint8_t nonce[12];
|
|
uint8_t mac[16];
|
|
} datum_aes_ccm_t;
|
|
|
|
|
|
/* Datum type = 6 */
|
|
typedef struct _datum_tpm_enc
|
|
{
|
|
datum_header_safe_t header;
|
|
uint32_t unknown; // See properties below, the header size of this datum is 0xc => header + int32 (int32 possibly divided into more members)
|
|
} datum_tpm_enc_t;
|
|
|
|
|
|
/* Datum type = 8 */
|
|
typedef struct _datum_vmk
|
|
{
|
|
datum_header_safe_t header;
|
|
guid_t guid;
|
|
uint8_t nonce[12];
|
|
} datum_vmk_t;
|
|
|
|
|
|
/* Datum type = 9 */
|
|
typedef struct _datum_external
|
|
{
|
|
datum_header_safe_t header;
|
|
guid_t guid;
|
|
ntfs_time_t timestamp;
|
|
} datum_external_t;
|
|
|
|
|
|
/* Datum type = 15 */
|
|
typedef struct _datum_virtualization
|
|
{
|
|
datum_header_safe_t header;
|
|
uint64_t ntfs_boot_sectors;
|
|
uint64_t nb_bytes;
|
|
|
|
/*
|
|
* Below is a structure added to this virtualization structure in Windows 8
|
|
* The header is still 0x18 in size, which means xinfo is a payload
|
|
*/
|
|
extended_info_t xinfo;
|
|
} datum_virtualization_t;
|
|
#pragma pack ()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
* A hardcoded table defining some properties for each datum
|
|
*/
|
|
typedef struct _datum_value_types_properties
|
|
{
|
|
/*
|
|
* The header size of the datum, this is including the datum_header_safe_t
|
|
* structure which is beginning each one of them
|
|
*/
|
|
uint16_t size_header;
|
|
|
|
/*
|
|
* A flag which tells us if the datum has one or more nested datum
|
|
* 0 = No nested datum
|
|
* 1 = One or more nested datum
|
|
*/
|
|
uint8_t has_nested_datum;
|
|
|
|
/* Always equal to 0, maybe for padding */
|
|
uint8_t zero;
|
|
} value_types_properties_t;
|
|
|
|
static const value_types_properties_t datum_value_types_prop[] =
|
|
{
|
|
{ 8, 0, 0 }, // ERASED
|
|
{ 0xc, 0, 0 }, // KEY
|
|
{ 8, 0, 0 }, // UNICODE
|
|
{ 0x1c, 1, 0 }, // STRETCH
|
|
{ 0xc, 1, 0 }, // USE KEY
|
|
{ 0x24, 0, 0 }, // AES CCM
|
|
{ 0xc, 0, 0 }, // TPM ENCODED
|
|
{ 8, 0, 0 }, // VALIDATION
|
|
{ 0x24, 1, 0 }, // VMK
|
|
{ 0x20, 1, 0 }, // EXTERNAL KEY
|
|
{ 0x2c, 1, 0 }, // UPDATE
|
|
{ 0x34, 0, 0 }, // ERROR
|
|
|
|
/* These ones below were added for Seven */
|
|
{ 8, 0, 0 }, // ASYM ENC
|
|
{ 8, 0, 0 }, // EXPORTED KEY
|
|
{ 8, 0, 0 }, // PUBLIC KEY
|
|
{ 0x18, 0, 0 }, // VIRTUALIZATION INFO
|
|
{ 0xc, 0, 0 }, // SIMPLE
|
|
{ 0xc, 0, 0 }, // SIMPLE
|
|
{ 0x1c, 0, 0 }, // CONCAT HASH KEY
|
|
{ 0xc, 0, 0 } // SIMPLE
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
* Here are prototypes of functions dealing with data
|
|
*/
|
|
char* cipherstr(cipher_t enc);
|
|
char* datumvaluetypestr(dis_datums_value_type_t value_type);
|
|
|
|
int get_header_safe(void* data, datum_header_safe_t* header);
|
|
|
|
int get_payload_safe(void* data, void** payload, size_t* size_payload);
|
|
|
|
void print_one_datum(DIS_LOGS level, void* datum);
|
|
|
|
void print_header(DIS_LOGS level, datum_header_safe_t* header);
|
|
|
|
void print_datum_generic(DIS_LOGS level, void* vdatum);
|
|
void print_datum_erased(DIS_LOGS level, void* vdatum);
|
|
void print_datum_key(DIS_LOGS level, void* vdatum);
|
|
void print_datum_unicode(DIS_LOGS level, void* vdatum);
|
|
void print_datum_stretch_key(DIS_LOGS level, void* vdatum);
|
|
void print_datum_use_key(DIS_LOGS level, void* vdatum);
|
|
void print_datum_aes_ccm(DIS_LOGS level, void* vdatum);
|
|
void print_datum_tpmenc(DIS_LOGS level, void* vdatum);
|
|
void print_datum_vmk(DIS_LOGS level, void* vdatum);
|
|
void print_datum_external(DIS_LOGS level, void* vdatum);
|
|
void print_datum_virtualization(DIS_LOGS level, void* vdatum);
|
|
|
|
void print_nonce(DIS_LOGS level, uint8_t* nonce);
|
|
void print_mac(DIS_LOGS level, uint8_t* mac);
|
|
|
|
int get_next_datum(
|
|
dis_metadata_t dis_metadata,
|
|
dis_datums_entry_type_t entry_type,
|
|
dis_datums_value_type_t value_type,
|
|
void* datum_begin,
|
|
void** datum_result
|
|
);
|
|
|
|
int get_nested_datum(void* datum, void** datum_nested);
|
|
int get_nested_datumvaluetype(void* datum, dis_datums_value_type_t value_type, void** datum_nested);
|
|
|
|
int datum_value_type_must_be(void* datum, dis_datums_value_type_t value_type);
|
|
|
|
int dis_metadata_has_clear_key(dis_metadata_t dis_meta, void** vmk_datum);
|
|
|
|
|
|
typedef void(*print_datum_f)(DIS_LOGS, void*);
|
|
static const print_datum_f print_datum_tab[NB_DATUMS_VALUE_TYPES] =
|
|
{
|
|
print_datum_erased,
|
|
print_datum_key,
|
|
print_datum_unicode,
|
|
print_datum_stretch_key,
|
|
print_datum_use_key,
|
|
print_datum_aes_ccm,
|
|
print_datum_tpmenc,
|
|
print_datum_generic,
|
|
print_datum_vmk,
|
|
print_datum_external,
|
|
print_datum_generic,
|
|
print_datum_generic,
|
|
print_datum_generic,
|
|
print_datum_generic,
|
|
print_datum_generic,
|
|
print_datum_virtualization,
|
|
print_datum_generic,
|
|
print_datum_generic,
|
|
print_datum_generic,
|
|
print_datum_generic,
|
|
};
|
|
|
|
|
|
#ifdef _HAVE_RUBY
|
|
#include "dislocker/ruby.h"
|
|
|
|
void Init_datum(VALUE rb_cDislockerMetadata);
|
|
|
|
VALUE rb_cDislockerMetadataDatum_new(VALUE klass, VALUE datum);
|
|
#endif
|
|
|
|
|
|
|
|
#endif // DATUM_HEADER_H
|