Each Virtual Encrypted Disk contains the encrypted data as well as the envelope that holds the encryption keys and other information necessary for successful decryption and re-encryption of the data. The encrypted data can be stored as one large file or be split in several files. The envelope can also be stored in the same file as encrypted data, or in a separate file.
The encrypted data
This is the actual user or application data that the Driver encrypts and decrypts as necessary. The data is split in 512-byte sectors, and each sector is encrypted with a single run of the cipher in the encryption mode selected by the user.
The envelope
The envelope contains the following information:
Offset (in bytes) | Size (bytes) | Description |
0 | 512 | Volume descriptor key |
512 | 512 | Reserved (random bytes) |
1024 | 1024 | Volume descriptor |
Volume descriptor key
The Volume descriptor key area contains a CIPHER_CONTEXT_RAW structure (described below) that contains the encryption key and other information necessary to decrypt Volume descriptor. The Volume descriptor key area itself is encrypted with the key derived from the user password.
Volume descriptor
The Volume descriptor area contains a VOLUME_DESCRIPTOR_RAW structure that contains the encryption key and other information necessary to decrypt the encrypted data.
The VOLUME_DESCRIPTOR_RAW structure
struct VOLUME_DESCRIPTOR_RAW
{
VOLUME_DESCRIPTOR volume_descriptor;
BYTE random[ 1024 - sizeof(VOLUME_DESCRIPTOR) - sizeof( MAC_VALUE ) ];
MAC_VALUE mac;
};
The volume_descriptor member is described below. The random member is filled with random bytes when the Virtual Encrypted Disk is first created.
The mac value contains the result of the calculation with the OMAC algorithm of the volume_descriptor and random members. The entire VOLUME_DESCRIPTOR_RAW structure is encrypted with the Volume descriptor key. The mac value is calculated before the encryption. When the VOLUME_DESCRIPTOR_RAW is decrypted, the mac value is checked to verify the integrity of the remaining data of the structure.
The VOLUME_DESCRIPTOR structure
The VOLUME_DESCRIPTOR structure contains the encryption key and other information required by the driver to successfully "start" (a.k.a. "mount") the encrypted data that contains a file system volume. This structure contains the following members:
struct VOLUME_DESCRIPTOR
{
UINT16 wSize; // = sizeof(VOLUME_DESCRIPTOR)
UINT16 nDriverBuildMin;
UINT16 nVolumeVersion;
UINT16 wVolumeFlags;
UINT128 volume_id;
CIPHER_CONTEXT volume_key;
UINT64 uxSegmentSize; // 0 if all in one file, or size of each segment in Bytes!
UINT64 uxReserved0; // 0
};
The nDriverBuildMin member contains the minimum build number of the driver that is required to start this volume. The nVolumeVersion member is the version number of the VOLUME_DESCRIPTOR structure and currently has the value 1.
The wVolumeFlags member can be 0 if encrypted data follows the envelope in the same physical file, or 1 if encrypted data is stored in one or more physical files, separate from the envelope.
The volume_id member is a randomly generated 128-bit value that may be used to identify the volume that this specific instance of the structure describes.
The volume_key member contains the encryption key and other information required for the encryption and decryption of the encrypted data.
The uxSegmentSize member is 0 if all encrypted data is stored within one file, or the size of the largest segment, if the encrypted data is stored in several file segments.
The CIPHER_CONTEXT_RAW structure
The CIPHER_CONTEXT_RAW structure is used in several places of Virtual Encrypted Disk and is used to store the encryption key, as well as other information necessary for an encryption algorithm to successfully encrypt and decrypt data. The CIPHER_CONTEXT_RAW structure contains the following members:
struct CIPHER_CONTEXT_RAW
{
CONTAINER_ID id;
PASSWORD_SALT salt;
CIPHER_CONTEXT_EX cipher_context_ex;
};
The id member a randomly generated 128-bit number that may be used as a unique identifier of the data associated with a specific instance of this structure. The salt member a randomly generated 128-bit number that is used as the "salt" value during the key derivation procedure, if this structure is used to describe a key generated from the user's password.
The CIPHER_CONTEXT_EX structure
The CIPHER_CONTEXT_EX structure contains the following members:
struct CIPHER_CONTEXT_EX
{
CIPHER_CONTEXT cipher_context;
BYTE random[ 512 -
sizeof( CONTAINER_ID ) -
sizeof( PASSWORD_SALT ) -
sizeof( CIPHER_CONTEXT ) -
sizeof( MAC_VALUE ) ];
MAC_VALUE mac;
};
The mac value contains the result of the calculation with the OMAC algorithm of the cipher_context and random areas, to be able to check the integrity of the structure.
The CIPHER_CONTEXT structure
The CIPHER_CONTEXT structure contains the following members:
struct CIPHER_CONTEXT
{
CIPHER_DESCRIPTOR cipher_descriptor;
BYTE key[ BITS(2048) ];
};
The CIPHER_DESCRIPTOR structure
The CIPHER_DESCRIPTOR structure contains the following members:
struct CIPHER_DESCRIPTOR
{
UINT16 wSize; // = sizeof( CIPHER_DESCRIPTOR )
UINT16 wReserved0; // 0
UINT32 dwFlags; // 0 for now
UINT32 idCipher;
UINT32 dwReserved1; // 0
UINT32 idMode;
UINT32 dwReserved2; // 0
UINT64 uxDataOffset;
UINT64 uxDataSize;
};
The idCipher member specifies the encryption algorithm; it can currently take one of the following values:
Encryption algorithm | Value (decimal) |
AES-128 | 65793 |
AES-192 | 131329 |
AES-256 | 196865 |
TWOFISH-128 | 66305 |
TWOFISH-192 | 131841 |
TWOFISH-256 | 197377 |
The idMode member specifies the encryption mode; it can currently take one of the following values:
Encryption mode | Value (decimal) |
CBC | 516 |
XTS | 1284 |
The uxDataOffset and uxDataSize are optional and may specify the location of the data encrypted with the cipher described by this instance of the CIPHER_DESCRIPTOR structure; they could both be 0 if that location can be determined from other information.
The key member of the CIPHER_CONTEXT structure contains the key material that is necessary for the cipher to perform the encryption and decryption of the data. For example, if the cipher is AES-128 and the encryption mode is CBC, then the first 128 bits of the key member are used as the encryption key, and the next 128 bits are used as the initial initialization vector. The remaining (unused) bits of the key member are set to random values when the CIPHER_CONTEXT structure is first created.