diff --git a/docs/LUKS2-format.txt b/docs/LUKS2-format.txt deleted file mode 100644 index 5718f1f0..00000000 --- a/docs/LUKS2-format.txt +++ /dev/null @@ -1,279 +0,0 @@ -LUKS2 on-disk format -==================== - -Note: these are temporary documentation notes only. -The more formal definition will be published later. - -Design goals -~~~~~~~~~~~~ -The LUKS2 is an on-disk storage format designed to -provide simple key management, primarily intended for Full Disk -Encryption based on dm-crypt. - -The LUKS2 is highly inspired by LUKS1 format and in some -specific situations (most of the default installations) can be converted -in-place (in both ways - to and from LUKS1). - -The LUKS2 format is designed to allow future updates of various -parts without the need to modify binary structures. - -On-disk format provides redundancy of metadata, detection -of metadata corruption and automatic repair from metadata copy. - -NOTE: For security reasons, there is no redundancy in keyslots -binary data (encrypted keys) but format allows updating to redundant -keyslot encryption in future (add forward error correction codes -is one possibility). - -On-disk structure -~~~~~~~~~~~~~~~~~ - -The LUKS2 header contains three parts: - - binary header (one 4096 bytes sector) - - area for metadata stored in JSON format - - keyslot area (per-context binary data). - - The binary header and JSON area are stored twice to increase - redundancy. Keyslot area is allocated per-demand, and it is stored only once. - -The basic on-disk structure is then - -0 4096 -| bin hdr1 | JSON ... | bin hdr2 | JSON ... | Keyslot data | | (data payload) - -Binary header -~~~~~~~~~~~~~ - -The binary header is intended for quick scanning (by blkid and udev) and contains -magic string to detect the device, basic information (labels), header size information -and metadata checksum. -Checksum covers both binary data and following JSON area and is calculated -with checksum fields zeroed. By default plain SHA256 checksum is used. - -The primary binary header is always stored in sector 0 of the device. - -The C structure of binary header (see luks2.h) is - -#define LUKS2_MAGIC_1ST "LUKS\xba\xbe" -#define LUKS2_MAGIC_2ND "SKUL\xba\xbe" -#define LUKS2_MAGIC_L 6 -#define LUKS2_UUID_L 40 -#define LUKS2_LABEL_L 48 -#define LUKS2_SALT_L 64 -#define LUKS2_CHECKSUM_ALG_L 32 -#define LUKS2_CHECKSUM_L 64 - -struct luks2_hdr_disk { - char magic[LUKS2_MAGIC_L]; /* "LUKS\xba\xbe" (1st) or "SKUL\xba\be" (2nd) */ - uint16_t version; /* Version 2 */ - uint64_t hdr_size; /* in bytes, including JSON area */ - uint64_t seqid; /* sequence ID, increased on every update */ - char label[LUKS2_LABEL_L]; /* ASCII label or empty */ - char checksum_alg[LUKS2_CHECKSUM_ALG_L]; /* checksum algorithm, "sha256" */ - uint8_t salt[LUKS2_SALT_L]; /* random salt, unique for every header */ - char uuid[LUKS2_UUID_L]; /* UUID of device */ - char subsystem[LUKS2_LABEL_L]; /* owner subsystem label or empty */ - uint64_t hdr_offset; /* header offset from device start in bytes */ - char _padding[184]; /* must be zeroed */ - uint8_t csum[LUKS2_CHECKSUM_L]; /* header checksum */ - char _padding4096[7*512]; /* must be zeroed */ -} __attribute__ ((packed)); - -The LUKS1 compatible field (magic, UUID) are placed intentionally on the same offsets. -The header version must be set to 2. -The UUID is the same format as in LUKS1. - -Magic string differs between the first and second header. - -The hdr_offset must match physical header offset on the device. -If hdr_offset does not match, the header is misplaced and must not be used. -(It is a prevention to partition resize or manipulation with device start offset.) - -The hdr_size contains the size of the binary header and JSON data area. -The offset and size of the second (backup) header must match to these data. -(Prevention to rewrite of a header with different JSON area size.) - -There are two labels - label and subsystem. Content of these fields will be visible -in UDEV/blkid scan and can be used for similar purposes as a filesystem label. -These fields are by default empty. - -The salt field in binary header is generated by an RNG and is different for -every header, even the backup header must contain a different salt. -The salt in binary header is not used after the header is read, the main intention -is to avoid deduplication of the header sector. -The salt must be regenerated on every header repair (but not on regular update). - -The sequential number (seqid) is a counter that is always increased when a new -update of the header is written. The header with higher seqid is more recent and -is used for recovery (if there are two headers with different seqid, the -more recent one is automatically used). - -The rest of binary header must be zeroed. - -JSON area -~~~~~~~~~ -The JSON area starts immediately after the binary header. Its size is set -by binary header hdr_size field (JSON area size = hdr_size - 4096). - -The area contains metadata in JSON format and is fixed. Unused remainder -of the area must be empty. - -The header cannot store larger metadata that this fixed buffer and header -size must be set properly during format. For now, only areas with 14 kB -header (4kB binary header + 14kB JSON area) is created during format. - -The JSON is structured to be able to describe system in very generic way, -but LUKS2 intentionally limits options to values that are supportable -in implemented version. - -JSON structure is as follows: - -Mandatory sections (must be present but some can be empty): - - config - - keyslots - - digests - - segments - - tokens - -Except for config section, all section contains array of objects that must be named -as number (unsigned integer) - for example keyslot "0", "1" etc. -Every object is typed (must contain attribute "type"). -According to type, library decides how to handle (or ignore) such an object. - -Binary data inside JSON (for example salt) is stored in Base64 encoding. - -If a value is needed to be stored as a 64bit integer (usually offset or size), -it is stored in text format and later converted to the 64bit integer. -(JSON cannot store 64bit integers directly.) - -Config section -~~~~~~~~~~~~~~ -Config contains information about JSON buffer size (cross-checked with binary header), -keyslot area size and optional object with activation flags. - -The "flags" section is array of activation flags that are automatically used -when LUKS device is activated (for example it can unconditionally allow TRIM/discard -functionality on the encrypted device). - -Segments sections -~~~~~~~~~~~~~~~~~ -The segment is an encrypted area on the disk containing data (in LUKS1 often -mentioned as a data payload). -For now, only one data area is available for the user. -(More segments will be later used for on-line re-encryption functionality.) - -Segments contain definition about encryption parameters, sector size and -start and length of the segments. By default, the segment starts directly -after the LUKS2 header and is marked as "dynamic" (it automatically detects -the size of the available device). - -Optionally it can contain information about data integrity protection, -then the data segments is formatted as dm-integrity device and dm-crypt -encryption is stacked above. - -To activate a segment, there must be at least one digest linked to it. - -Keyslots section -~~~~~~~~~~~~~~~~ -Keyslot object contains information stored key - area, where it is stored -(keyslot data), encryption, anti-forensic function, and Key Derivation Function -and its parameters (PBKDF type, costs, salt). - -For now, only internal "luks2" keyslot type is available, it uses the same logic -as LUKS1 keyslot, but allows to define per-keyslot algorithms -(for example different PBKDF). - -Digests section -~~~~~~~~~~~~~~~ -The digest is used to verify that volume key decrypted from a keyslot is correct. -A digest is linked to keyslots and segment. - -For now, only "pbkdf2" digest (LUKS1 compatible digest that uses PBKDF2) -is supported. - -Tokens section -~~~~~~~~~~~~~~ -A token is an object that can describe "how to get passphrase or key" to unlock -particular keyslot or it can be used t store any additional data (even unrelated -to a keyslot). -This area can be user configurable, and libcryptsetup provides interface to -store used data directly in JSON format. -Some token types are implemented internally, for now, there is only "luks2-keyring". -type. This token type tries to load unlocking passphrase from kernel keyring -with stored identification. - -There can be external application that uses token objects to store metadata and -implements bindings to specific hardware (TPM etc.). - -LUKS2 JSON Format Example -~~~~~~~~~~~~~~~~~~~~~~~~~ -For illustration this is example of a LUKS2 device JSON: - -{ - "keyslots":{ - "0":{ - "type":"luks2", - "key_size":32, - "kdf":{ - "type":"argon2i", - "time":181, - "memory":1024, - "cpus":4, - "salt":"Xfc5ScS8tCLrdbt6jtyWsBjCwAn3Msn\/enOYaAq8PEo=" - }, - "af":{ - "type":"luks1", - "hash":"sha256", - "stripes":4000 - }, - "area":{ - "type":"raw", - "encryption":"aes-xts-plain64", - "key_size":32, - "offset":"32768", - "size":"131072" - } - } - }, - "tokens":{ - "0":{ - "type":"luks2-keyring", - "keyslots":[ - "0" - ], - "key_description":"my-token" - } - }, - "segments":{ - "0":{ - "type":"crypt", - "offset":"4194304", - "iv_tweak":"0", - "size":"dynamic", - "encryption":"aes-xts-plain64", - "sector_size":512 - } - }, - "digests":{ - "0":{ - "type":"pbkdf2", - "keyslots":[ - "0" - ], - "segments":[ - "0" - ], - "hash":"sha256", - "iterations":155298, - "salt":"WgMOideLECc5hfnmFVu3bwttJpkfnpf2RayE2WhP8zU=", - "digest":"olobPk9pc0GItqofH78aMPmRaOZIbRevlvSlTZ91NLI=" - } - }, - "config":{ - "json_size":"12288", - "keyslots_size":"4161536", - "flags":[ - "allow-discards" - ] - } -} diff --git a/docs/on-disk-format-luks2.pdf b/docs/on-disk-format-luks2.pdf new file mode 100644 index 00000000..803f8be2 Binary files /dev/null and b/docs/on-disk-format-luks2.pdf differ