Technical Details: LibreCrypt Critical Data Block (CDB) Layout (CDB Format ID 1)

LibreCrypt logo LibreCrypt: Open-Source disk encryption for Windows

Technical Details: LibreCrypt Critical Data Block (CDB) Layout (CDB Format ID 1)

NOTE: This CDB layout is *_obsolete_; all new volumes should use the latest CDB format.*

Overview

OBSOLETE *This format is used by older versions of FreeOTFE, but not by LibreCrypt. LibreCrypt supports only (CDB Format ID 4)

The following table describes the high-level layout of all FreeOTFE (*not *Linux) volume files:

Critical data block:

Password salt Encrypted block:

Check hash Volume details block:
Critical data version Volume flags Encrypted partition image length Master key length Master key Requested drive letter Random padding #2
Random padding #1
Encrypted partition image

Color key:

Color Encryption used
Red items are not encrypted
Blue items are encrypted with the user's password, password salt, and user's chosen hash/cypher algorithms
Green items are encrypted with the master key and the user's chosen cypher, with IVs generated with the user's chosen sector IV method

Seem intimidating? Read on, and all will become clear... When broken down into its component parts, the volume structure is reasonably straightforward to understand.


Breakdown: Top level

Critical data block Encrypted partition image

At the highest level, volume files can be broken down into just two basic parts: A critical data area, and the encrypted partition itself.

Item name Size (in bits) Description
Critical data block 4096 This part of the volume file contains "critical data", including the master en/decryption key used for the encrypted partition image, the method used for generating sector IDs, and a check hash. See below for further breakdown.

Encrypted partition image User defined. (max 2^64 bytes; circa 16777216 TB) This is a literal partition image which represents the volume. This image is encrypted with:

    * The master key

    • The user's chosen cypher

    • The user's chosen method for generating different sector IVs

_Total size:_ 4096 + Encrypted partition image size


Breakdown: Critical data block layout

Password salt Encrypted blockRandom padding #1

Item name Size (in bits) Description
Password salt sl (User specified to a max 512) This data is appended onto the user's password, before it's hashed. The resulting hash may then be used to encrypt/decrypt the "Encrypted block".
Encrypted block If bs>0 then: ((4096 - salt length) div bs*)* * bs*_*_ If bs<=0 then: (4096 - salt length) This block contains the actual key which is used to encrypt/decrypt the encrypted partition image. See below for further breakdown.

Random padding #1 ((4096 - sl) % bs) Random "padding" data. Required to pad out any remaining, unused, bits in the "critical data block"**
_Total size:_ 4096


Breakdown: Encrypted block layout

Check hash Volume details block

As described above, this entire block is encrypted using the user's password, salt, and chosen hash and cypher algorithms.

As this block is encrypted, its length (in bits) must be a multiple of the cypher's blocksize.

Item name Size (in bits) Description
Check hash hk This is the hash of the plaintext version of the "Volume details block". If hk is zero, then this hash will be either truncated to 512 bits, or right-padded with 0 bits up to a maximum of 512 bits
Volume details Total size - hk This stores the details of how to encrypt/decrypt the encrypted partition.
_Total size:_ If bs>8 then: ((4096 - sl) / bs*)* * bs*_*_ If bs<=8 then: (4096 - sl) Note: "/" represents integer division


Breakdown: Volume details block layout

Critical data version Volume flags Encrypted partition image length Master key length Master key Requested drive letter Random padding #2

Finally, we reach the details that the critical data block was designed to protect:

Item name Size (in bits) Description
Critical data version 8 This is a version ID which identifies the layout of the remainder of the volume details block When this layout format is used, this will always be set to 1.

Volume flags 32 Bitmap flagging various items.

Currently, this only identifies which method is used in generating sector IVs, used in encrypting/decrypting the encrypted partition image.

Bit - Description

0 - Use different IVs for each sector 0 = Use NULL IV 1 = Use sector ID (possibly hashed) as IV 1 - Sector ID zero is at the start of the file 0 = Sector ID zero is at the start of the encrypted data 1 = Sector ID zero is at the start of the host volume file 2 - <unused> 3 - Hash sector ID before use 0 = Sector ID used as IV 1 = Hash sector ID before using is as an IV

Encrypted partition image length 64 This stores the length (in bytes) of the encrypted partition image
Master key length 32 This will be set to the length of the master key in bits. Not strictly needed, but used as a sanity check.
Master key _ks (max 1536) _ This is set to the random data generated when the volume was created; it represents the en/decryption key used to encrypt the encrypted partition image
Requested drive letter 8 The drive letter the volume should be typically be mounted as. Set to 0x00 if there is no particular drive letter the volume should be mounted as; mount using the first available drive letter.
Random padding #2 All remaining bits to pad out to Total size Random "padding" data. Required to pad out the encrypted block to a multiple of bs, and to increase the size of this block to the maximum length that can fit within the "critical data block".
_Total size:_ (((4096 - sl) / bs*)* * bs*_*)** - _hk Note: "/" represents integer division


Miscellaneous Comments Regarding the LibreCrypt File Layout

The design of the critical data layout eliminates the need for the cypher/hash used to be stored anywhere, denying an attacker this information and increasing the amount of work required to attack a volume file.

The "critical data block" is encrypted.

The "password salt" appears before the "encrypted block", and no indication of the length of salt used is stored anywhere in order to prevent an attacker from even knowing where the "encrypted block" starts within the "critical data block".

The "Check hash" appears before the volume details block. This may seem a little strange since the size of "Check hash" is variable (its actual length is dependent on the hash algorithm chosen), but appears first in order to reduce the amount of "known" (or predictable) data early on in the volume. Theoretically this is desirable as (for example) cyphers operating in CBC (or similar) modes which "whiten" data will do so with data that is less predictable than would occur if the hash appeared towards the end of the block it appears in.

The "Check hash" is limited to 512 bits. This is limited as, in practical terms, some kind of limit is required if the critical data block is to be of a predetermined size. See section on mounting volume files for how multiple matching check hashes is handled.

The "Password salt" is (fairly arbitrarily) limited to 512 bits. Again, this is primarily done for practical reasons.

Although at time of writing (2004) this limit to the length of salt used should be sufficient, the format of the critical data block (with included layout version ID) does allow future scope for modification in order to allow the critical data block to be extended (e.g. from 4096 to 8192 bits), should this limit be determined as insufficient.

The "Encrypted block" does contain a certain amount of data that may be reasonably guessed by an attacker (e.g. the critical data version), however this would be of very limited use to an attacker launching a "known plaintext" attack as the amount of this data is minimal, and as with pretty much any transparant encryption system, the "Encrypted partition image" can reasonably expected to contain significantly more known plaintext anyway (e.g. the partition's boot sector)


Creating LibreCrypt Volumes

To create a container file, a fairly significant amount of information is required due to freedom that LibreCrypt gives you in creating volume files.

Broadly speaking, creating a container consists of three distinct stages:

  1. Creating a file large enough on the local filesystem, and overwriting it with 'chaff'
  2. Writing the critical data block to the volume file
  3. Mounting the volume, formatting it

Stage 1 is straightforward; write data to the file until is has gained the required size. This stage is skipped when creating a hidden volume.

Stage 2 is more complex; and will be described below.

Stage 3 is required to set the volume up for use

Writing the critical data block.

The following procedure is used to build up a container's critical volume block:

    (((4096 - **sl**) / **bs****)** * **bs**_****_**)** - _hk_
    (See the layout breakdown diagrams of the "Critical data area" to understand where this algorithm comes from.) * With the user's selection of hash algorithm, hash the "Volume details block" to generate the "Check hash". * If the "Check hash" generated has less than "**hk**" bits, it should be right-padded with zero bits until it is "**hk**" bits long. * If the "Check hash" generated has more than "**hk**" bits, it should be truncated to the first "**hk**" bits. * Prepend the "Check hash" onto the "Volume details block" to build the plaintext version of the "Encrypted block" * Append the salt onto the user's password * Hash the salted password with the user's chosen hash algorithm * If the hash generated has less than "**ks**" bits, it should be right-padded with zero bits until it is "**ks**" bits long. * If the hash generated has more than "**ks**" bits, it should be truncated to the first "**ks**" bits. **The truncated/padded hash will be used as the "critical data key"** * Encrypt the plaintext "Encrypted block" with the user's selection of cypher, an IV of "**bs"** zeroed bits, and the "critical data key" * Prepend the salt onto the cyphertext version of the "Encrypted block" * Append "Random padding #1" to the "Encrypted block" in order to pad it out to 4096 bits (512 bytes) and form the complete "Critical data block" * Write the "Critical data block" to the volume file, beginning from the start of the file for normal LibreCrypt volumes, or from the user's offset in the case of a hidden volume.

#### Mounting LibreCrypt Volumes IMPORTANT: Versions of FreeOTFE (v00.00.0x) that used this CDB format had an implementation fault that caused the Volume Details Block to be incorrectly parsed when it was read in. It incorrectly used the 32 bits starting from offset byte 10 within the Volume Details Block (i.e. data storing the part of the encrypted partition image length) as the VolumeFlags. This has been compensated for in later versions of FreeOTFE, which use a later CDB layout in any case. To mount a container, the following information must be determined:

    * The location of the critical data block within the volume file* The user's password * The length of salt used, in bits (**sl**)* The algorithm used to hash the user's password and salt * The cypher used for all en/decryption operations * The master key to be used to en/decrypt the encrypted partition image * The method used to generate the different IVs for each sector of the encrypted partition image * The length of the encrypted partition image
Items 1-3 are obtained by asking the user. Items 3 and 4 are determined by brute force; by hashing the user's password with the first **sl** bits of the critical data block with each of the hash algorithms installed, then using that information to decrypt the remainder of the critical data block using each of the installed cyphers in turn. After each decryption, the decrypted critical data block is hashed, and this hash value is compared to the decrypted version of the check hash. Items 6-8 are then taken from the successfully decrypted critical data block, and the volume is mounted. In detail, the following procedure is used:
    * The user is prompted for the following information: * The first 512 bytes (4096 bits) of the file are read in, beginning from the user specified offset. * The first "**sl**" bits of which are assumed to be the salt, and are appended to the user's password. * For each hash algorithm installed on the user's computer: _Note: We will use "_hk_" to describe the length of hash values generated by each hash algorithm as it is used in turn. This value is as reported by the hash driver. If the hash driver reports that the hash length "-1", we will use the smaller of 512 bits, and the length of the data that the hash algorithm actually returns, as "_hk_"._
      * The combined user's password and salt previously generated is hashed, giving an **hk** bit "critical key". * For each cypher installed on the user's computer: _Note: We will use "_ks_" to describe the keysize of each cypher as it is used in turn, the keysize being as reported by the cypher driver. If the cypher driver reports that the cypher's keysize is "-1" (no specific keysize), we will use "_hk_" as "_ks_"._ _Note: We will use "_bs_" to describe the blocksize of the cypher, as reported by the cypher driver. If the cypher driver reports that the cypher's keysize is "-1" (no blocksize), we will use 8 bits (1 byte) as "_bs_"._
        * The "Encrypted block" is extracted from the critical data block. The length of the "Encrypted block" is calculated as:
        ((4096 - **sl**) / **bs**) * _bs _
        Alternatively, the length of "Random padding #1" can be viewed as being:
        ((4096 - **sl**) % **bs**)

        Where % represents the modulus, and / integer division* The "Encrypted block" is decrypted using:

              <OL>
        
                *
        

        The first "ks" bits of the hash value previously generated as the decryption key; if "hk" is less than "ks", then the hash will have extra zero bits appended to it in order to pad it out to "ks"

                *
        

        An IV consisting of a block of "bs" bits, all set to 0.

              </OL>
        
        • Next, the "Check hash" and "Volume details block" are extracted from the decrypted data. In order to do this, the length of the check hash must be known; if the hash algorithm used on the salted user's password is reported to generate hashes "-1" bits long, then the check hash is assumed to be 512 bits long. Otherwise, the actual hash length is used.
        • The "Volume details block" is hashed and right padded with zero bits to make it the same length as the "Check hash", which it is then compared with. If the hash generated matches the "Check hash", then the "Encrypted block" is deemed to have been successfully decrypted; a note will be made of the cypher and hash used, together with the contents of the decrypted "Volume details block".

        In either case, all remaining hash/cypher combinations will be processed in the same manner.

As a result of the volume's layout, it is not necessary to store the cypher or hash algorithm used for en/decryption anywhere. Nor is it necessary to prompt the user for this information since during mounting a container formatted volume, this information can be determined dynamically by attempting the mount using all possible combinations of installed hash/cypher in conjunction with the check hash.