mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-16 05:10:03 +01:00
Add snapshot of LUKS2 docs.
This commit is contained in:
@@ -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 | <padding> | (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"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
docs/on-disk-format-luks2.pdf
Normal file
BIN
docs/on-disk-format-luks2.pdf
Normal file
Binary file not shown.
Reference in New Issue
Block a user