LUKS1 On-Disk Format Specification
Version 1.2.3
Clemens Fruhwirth <clemens@endorphin.org>
January 20, 2018

Document History
Version

Date
Changes

1.0

22.01.2005 Clemens Fruhwirth <clemens@endorphin.org>
More clear distinction between raw data and string data by adding
a byte[] data type for LUKS magic, salt and checksum data.
15.01.2006 Clemens Fruhwirth <clemens@endorphin.org>
Corrected the hash-spec length in Figure 1 from 64 to 32 bytes
as implied by offset calculation and all other assumptions in this
document.
18.02.2006 Clemens Fruhwirth <clemens@endorphin.org>
Added precise AFsplit specification. Removed lrw-plain mode
spec as the LRW standardization process is not about to be finished any time soon; will be reintroduced when a normative documentation is released by SISWG. Extended introduction text.
Thanks to Sarah Dean for providing valuable feedback with respect to the AFsplit specification.
08.12.2008 Clemens Fruhwirth <clemens@endorphin.org>
Clarify IV reference point for decrypt/encrypt. Thanks to Michael
Gorven for this suggestion.
11.04.2011 Milan Broz <mbroz@redhat.com>
Fix hash block size/digest size AF comment. Clarify master key
digest iteration count. Add XTS mode reference. Some minor
typo fixes. Add reference to NIST SP 800-132.
16.10.2011 Milan Broz <mbroz@redhat.com>
Mention detached header. Typo correction and some editing
for punctuation, grammar and clarity. Thanks to Karl O. Pinc
<kop@meme.com>.
4.5.2016
Milan Broz <mbroz@redhat.com>
Clarification of fixed sector size and keyslots alignment.
20.1.2018
Milan Broz <gmazyland@gmail.com>
Fixed links to inline document sources.

1.0.1

1.1

1.1.1

1.2

1.2.1

1.2.2
1.2.3

Author

1

1. OVERVIEW

2

Introduction
LUKS1 is short for ”Linux Unified Key Setup”. It has initially been developed
to remedy the unpleasantness a user experienced that arise from deriving the
encryption setup from changing user space, and forgotten command line arguments. The result of this changes are an unaccessible encryption storage. The
reason for this to happen was, a unstandardised way to read, process and set up
encryption keys, and if the user was unlucky, he upgraded to an incompatible
version of user space tools that needed a good deal of knowledge to use with
old encryption volumes.
LUKS has been invented to standardise key setup. But the project became
bigger as anticipated, because standards creation involves decision making,
which in turn demands for a justification of these decision. An overspring of this
effort can be found as TKS1 [Fru04], a design model for secure key processing
from entropy-weak sources2 . LUKS is also treaded extensivly in Chapters 5 and
6 in “New Methods in Hard Disk Encryption”, which provides a theoretic base
for the security of PBKDF2 passwords and anti-forensic information splitting.
See [Fru05b].
LUKS is the proof-of-concept implementation for TKS1. In LUKS 1.0, the
implementation switched to TKS2, a varient of TKS1, introduced in [Fru05b].
Additionally to the security provided by the TKS1 model, LUKS gives the user
the ability to associate more than one password with an encrypted partition.
Any of these passwords can be changed or revoked in a secure manner.
This document specifies the structure, syntax and semantic of the partition
header and the key material. The LUKS design can be used with any cipher
or cipher mode, but for compatibility reasons, LUKS standarises cipher names
and cipher modes.
While the reference implementation is using dm-crypt, Linux’ kernel facility
for bulk data encryption, it is not tied to it in any particular way.
Next to the reference implementation which works on Linux, there is a Windows implementation named LibreCrypt (based on original FreeOTFE project
by Sarah Dean).

1 Overview
A rough overall disk layout follows:
LUKS phdr

KM1 KM2 …

KM8

bulk data

A LUKS partition starts with the LUKS partition header (phdr) and is
followed by key material (labelled KM1, KM2 …KM8 in figure). After the key
material, the bulk data is located, which is encrypted by the master key. The
phdr contains information about the used cipher, cipher mode, the key length,
a uuid and a master key checksum.
Also, the phdr contains information about the key slots. Every key slot
is associated with a key material section after the phdr. When a key slot
is active, the key slot stores an encrypted copy of the master key in its key
1 This document describes version 1 of the LUKS on-disk format.
2 such as a user password

2. PREREQUISITES

3

material section. This encrypted copy is locked by a user password. Supplying
this user password unlocks the decryption for the key material, which stores
the master key. The master key in turn unlocks the bulk data. For a key slot,
all parameters how to decrypt its key material with a given user password are
stored in the phdr (f.e. salt, iteration depth).
A partition can have as many user passwords as there are key slots. To
access a partition, the user has to supply only one of these passwords. If a
password is changed, the old copy of the master key encrypted by the old
password must be destroyed. Peter Gutmann has shown in [Gut96], how data
destruction shall be done to maximise the chance, that no traces are left on
the disk. Usually the master key comprises only 16 or 32 bytes. This small
amount of data can easily be remapped as a whole to a reserved area. This
action is taken by modern hard disk firmware, when a sector is likely to become
unreadable due to mechanical wear. The original sectors become unaccessible
and any traces of key data can’t be purged if necessary.
To counter this problem, LUKS uses the anti-forensic information splitter
to artificially inflate the volume of the key, as with a bigger data set the probability that the whole data set is remapped drops exponentially. The inflated
encrypted master key is stored in the key material section. These sections are
labelled as ”KMx” in the figure above.

2 Prerequisites
2.1 Block encryption system
Instead of using cipher implementations like AES or Twofish internally, LUKS
reuses the block encryption facility used for the bulk data. The following syntax
is used in the pseudocode:
enc−d a t a = e n c r y p t ( c i p h e r −name , c i p h e r −mode , key , o r i g i n a l ,
o r i g i n a l −l e n g t h )
o r i g i n a l = d e c r y p t ( c i p h e r −name , c i p h e r −mode , key , enc−data ,
o r i g i n a l −l e n g t h )

If the encryption primitive requires a certain block size, incomplete blocks
are padded with zero. The zeros are stripped upon decryptions.3

2.2 Cryptographic hash
A cryptographic hash is necessary for the following two prerequisites. In
PBKDF2 a pseudo-random function is needed, and for AFsplitting a diffusion
function is needed. The pseudo-random function needs to be parameterisable,
therefore the hash function is used in a HMAC setup [BCK97].
The following syntaxes may omit the hash-spec parameter, because the
following pseudo code does not need a great variation of this parameter. The
parameter can be obtained from the partition header and will not change, once
initialised.
3 These primitives are also used for key material en/decryption. The key material is
always aligned to sector boundaries. If the block size of the underlaying encryption primitive
is larger than one sector, the pseudocode of section 4.1 has to be changed respectively.

2. PREREQUISITES

4

2.3 PBKDF2
LUKS needs to process password from entropy-weak sources like keyboard input. PKCS #5’s password based key derive function 2 (PBKDF2) has been
defined for the purpose to enhance the security properties of entropy-weak password, see [Kal97]. Therefore, LUKS depends on a working implementation of
PBKDF2. LUKS uses SHA1 per default as the pseudorandom function (PRF)
but any other hash function can be put in place by setting the hash-spec field.
In the pseudo code, the following syntax is used:
r e s u l t = PBKDF2( password ,
salt ,
i t e r a t i o n −count ,
d e r i v e d −key−l e n g t h )

Notice that the result of this function depends on the current setting of hashspec but the parameter has been omitted. Think of hash-spec as sort of an
environment variable.

2.4 AF-Splitter
LUKS uses anti-forensic information splitting as specified in [Fru05b]. The
underlaying diffusion function shall be SHA1 for the reference implementation,
but can be changed exactly as described in the remarks above. A C reference
implementation using SHA1 is available from [Fru05a].
s p l i t −m a t e r i a l = A F s p l i t ( u n s p l i t −m a t e r i a l , l e n g t h , s t r i p e s )
u n s p l i t −m a t e r i a l = AFmerge ( s p l i t −m a t e r i a l , l e n g t h , s t r i p e s )

Notice that the result of AFsplit, split-material, is stripes-times as large as
the original, that is length ∗ stripes bytes. Notice that the length parameter is
the length of the original content and not the length of the split-material array.
When D is the unsplit material, H is a diffusion function, and n is the stripe
number, AFsplit returns s1 , s2 . . . sn where s1 . . . sn−1 are randomly chosen
while sn is computed according to:
d0 = 0

(1)

dk = H(dk−1 ⊕ sk )

(2)

sn = dn−1 ⊕ D

(3)

To reverse the process, AFmerge computes dn−1 and recovers D from:
D = dn−1 ⊕ sn

(4)

2.4.1 H1
H1 is a hash function with an underlaying hash function P .4 H1 can operate
on a variable amount of data, hence it is constructed for hash extension. The
underlaying hash function is SHA1, we use it solely in LUKS. We use |P | to
denote the digest size of P , for SHA1 it is 160 bit.
4 H ’s function definition stems from an implementation error that I’m responsible for.
1
Do not try to analyse it, the structure given here is specified according to this implementation
error and hence is a mistake itself. H2 is the correct hash extension as originally envisioned.

3. THE PARTITION HEADER

5

The input to H1 (d), namely d, is partitioned into individual data hunks.
The partitioning repeatedly takes a data vector with the size |P | as di with
the final block (possibly shorter than |P |) dn . The transformation happens as
follows:
pi = P (i || di )

(5)

The end of the last block pn is cropped, so that its length is |dn |. The integer
i has to be delivered to the hash as an unsigned 32-bit integer in big-endien
format.

2.4.2 H2
All remarks for H1 apply, except
pi = P (i || d)

(6)

Notice the missing subscript of d in contrast to (5). This version will be used
in future LUKS revisions.5

3 The partition header
3.1 Version 1
The LUKS partition header has the layout as described in Figure 1. It starts
at sector 0 of the partition6 . LUKS uses 3 primitive data types in its header,
• unsigned integer, 16 bit, stored in big endian
• unsigned integer, 32 bit, stored in big endian
• char[], a string stored as null terminated sequence of 8-bit characters7
• byte[], a sequence of bytes, treated as binary.
Further, there is an aggregated data type key slot, which elements are described
in Figure 2.
A reference definition as C struct for phdr is available in the appendix.

3.2 Forward compatibility
LUKS’ forward compatibility centers around the on-disk format. Future versions are required to be able to correctly interpret older phdr versions. Future
versions are not required to be able to generate old versions of the phdr.
5 The transition has not happend yet. It is likely that the transition will occour in
conjunction with a version number bump to Version 2. Do not use H2 until then.
6 Since cryptsetup 1.4 the LUKS partition header can be detached and stored on another
device. In this specific case the payload offset can be zero.
7 Also known as C string.

3. THE PARTITION HEADER

start offset

field name

6

length

data type

description
magic for LUKS partition header,
see
LUKS_MAGIC
LUKS version
cipher name specification
cipher mode specification
hash specification
start offset of the bulk
data (in 512 bytes sectors)
number of key bytes
master key checksum
from PBKDF2
salt parameter for master key PBKDF2
iterations
parameter for master key
PBKDF2
UUID of the partition
key slot 1
key slot 2
…
key slot 8

0

magic

6

byte[]

6
8

version
cipher-name

2
32

uint16_t
char[]

40

cipher-mode

32

char[]

72
104

hash-spec
payload-offset

32
4

char[]
uint32_t

108
112

key-bytes
mk-digest

4
20

uint32_t
byte[]

132

mk-digest-salt

32

byte[]

164

mk-digest-iter

4

uint32_t

168
208
256
…
544
592

uuid
key-slot-1
key-slot-2
…
key-slot-8
total phdr size

40
48
48
…
48

char[]
key slot
key slot
…
key slot

Figure 1: PHDR layout

offset

field name

length

data type

description
state of keyslot, enabled/disabled
iteration parameter for
PBKDF2
salt
parameter
for
PBKDF2
start sector of key material
number of anti-forensic
stripes

0

active

4

unit32_t

4

iterations

4

uint32_t

8

salt

32

byte[]

40

key-material-offset

4

uint32_t

44

stripes

4

uint32_t

Figure 2: key slot layout

4. LUKS OPERATIONS

7

A LUKS implementation encountering a newer phdr version should not try
to interpret it, and return an error. Of course, an error should be returned, if
the phdr’s magic is not present.

4 LUKS operations
4.1 Initialisation
The initialisation process takes a couple of parameters. First and most important, the master key. This key is used for the bulk data. This key must be
created from an entropy strong (random) source, as the overcoming of entropy
weak keys is one of LUKS’ main objectives. For the following remarks, the
pseudo code is available as Figure 3.
Further, the user specifices the cipher setup details that are stored in the
cipher-name and cipher-mode fields. Although no LUKS operation manipulates
these two strings, it is likely that the LUKS implementation will have to convert
it into something suitable for the underlaying cipher system, as the interface is
not likely to be as ideal as described in Section 2.1.
The overall disk layout depends on the length of the key material sections
following the phdr. While the phdr is always constant in size, the key material
section size depends on the length of the master key and the number of stripes
used by the anti-forensic information splitter. The exact disk layout is generated by computing the size for the phdr and a key material section in sectors
rounded up. Then the disk is filled sector-wise by phdr first, and following
key material section 1 till key material section 8. After the eight key material
section, the bulk data starts.
After determining the exact key layout and boundaries between phdr, key
material and bulk data, the key material locations are written into the key
slot entries in the phdr. The information about the bulk data start is written
into the payload-offset field of the phdr. These values will not change during
the lifetime of a LUKS partition and are simply cached for safety reasons as a
miscalculation of these values can cause data corruption.8
The master key is checksummed, so a correct master key can be detected.
To future-proof the checksumming, a hash is not only applied once but multiple
times. In fact, the PBKDF2 primitive is reused. The master key is feed into
the PBKDF2 process as if it were a user password. After the iterative hashing,
the random chosen salt, the iteration count9 and result are stored in the phdr.
Although everything is correctly initialised up to this point, the initialisation process should not stop here. Without an active key slot the partition is
useless. At least one key slot should be activated from the master key still in
memory.
8 E.g. an incorrect bulk data offset can lead to overwritten key material and an incorrect
key offset can result in overwritten encrypted data.
9 Master key iteration count was set to 10 in previous revisions of LUKS. For new devices
the iteration count should be determined by benchmarking with suggested minimum of 1000
iterations.

4. LUKS OPERATIONS

masterKeyLength = d e f i n e d by u s e r
masterKey = g e n e r a t e random v e c t o r , l e n g t h : masterKeyLength
phdr . magic
= LUKS_MAGIC
phdr . v e r s i o n
= 1
phdr . c i p h e r −name
= a s s u p p l i e d by u s e r
phdr . c i p h e r −mode
= a s s u p p l i e d by u s e r
phdr . key−b y t e s
= masterKey
phdr . mk−d i g e s t −s a l t = g e n e r a t e random v e c t o r ,
l e n g t h : LUKS_SALTSIZE
// benchmarked a c c o r d i n g t o u s e r i n p u t
// ( i n o l d e r v e r s i o n s f i x e d t o 10)
phdr . mk−d i g e s t −i t e r a t i o n −count = a s above
phdr . mk−d i g e s t = PBKDF2( masterKey ,
phdr . mk−d i g e s t −s a l t ,
phdr . mk−d i g e s t −i t e r a t i o n −count ,
LUKS_DIGESTSIZE )
s t r i p e s = LUKS_STRIPES o r u s e r d e f i n e d
// i n t e g e r d i v i s i o n s , r e s u l t rounded down
b a s e O f f s e t = ( s i z e o f phdr ) / LUKS_SECTOR_SIZE + 1
k e y M a t e r i a l S e c t o r s = ( s t r i p e s ∗ masterKeyLength ) /
LUKS_SECTOR_SIZE + 1
f o r each k e y s l o t i n phdr a s k s {
// A l i g n k e y s l o t up t o m u l t i p l e o f LUKS_ALIGN_KEYSLOTS
b a s e O f f s e t = round_up ( b a s e O f f s e t , LUKS_ALIGN_KEYSLOTS)
k s . a c t i v e = LUKS_KEY_DISABLED
ks . s t r i p e s = s t r i p e s
k s . key−m a t e r i a l −o f f s e t = b a s e O f f s e t
baseOffset = baseOffset + keyMaterialSectors
}
phdr . p a y l o a d −o f f s e t = b a s e O f f s e t
phdr . u u i d = g e n e r a t e u u i d
w r i t e phdr t o d i s k

Figure 3: Pseudo code for partition initialisation

8

4. LUKS OPERATIONS

9

4.2 Adding new passwords
To add a password to a LUKS partition one has to possess an unencrypted
copy of the master key; either initialization must still be in progress or the
master key must be recovered using a valid password to an existing key slot.
The latter operation is sketched in Figure 4.
Assuming we have a good copy of the master key in memory the next steps
are to fetch a salt from a random source and to choose a password iteration
count10 . This information is written into a free – that is disabled – key slot of
the phdr.
The user password is entered and processed by PBKDF2. The master key is
then split by the AFsplitter into a number of stripes. The number of stripes is
determined by the stripes field already stored in the key slot. The split result is
written into the key material section, but encrypted. The encryption uses the
same cipher setup as the bulk data (cipher type, cipher mode, ...), but while
for the bulk data the master key is used, the key material section is keyed by
the result of the PBKDF2.

4.3 Master key recovery
To access the payload bulk data, the master key has to be recovered. Compare
the pseudo code in Figure 5.
First, the user supplies a password. Then the password is processed by
PBKDF2 for every active key slot individually and an attempt is made to
recover the master key. The recovery is successful, when a master key candidate
correctly checksums against the master key checksum stored in the phdr. Before
this can happen, the master key candidate is read from storage, decrypted and
after decryption processed by the anti-forensic information splitter in reverse
gear, that is AFmerge.
When the checksumming of the master key succeeds for one key slot, the
correct user key was given and the partition is successfully opened.

4.4 Password revocation
The key material section is wiped according to Peter Gutmann’s data erasure
principals [Gut96]. To wipe the sectors containing the key material, start from
the sector as recorded in key slot’s key-material-offset field, and proceed for
phdr.key-bytes * ks.stripes bytes.
10 The iteration count should be determined by benchmarking with suggested minimum
of 1000 iterations.

4. LUKS OPERATIONS

10

masterKey = must be a v a i l a b l e , e i t h e r b e c a u s e i t i s s t i l l i n
memory from i n i t i a l i s a t i o n o r b e c a u s e i t has been
r e c o v e r e d by a c o r r e c t password
masterKeyLength = phdr . key−b y t e s
e m p t y K e y S l o t I n d e x = f i n d i n a c t i v e key s l o t i n d e x i n phdr by
scanning the k e y s l o t . a c t i v e f i e l d f o r
LUKS_KEY_DISABLED .
k e y s l o t k s = phdr . k e y s l o t s [ e m p t y K e y S l o t I n d e x ]
PBKDF2−I t e r a t i o n s P e r S e c o n d = benchmark system
k s . i t e r a t i o n −count = PBKDF2−I t e r a t i o n s P e r S e c o n d ∗
intendedPasswordCheckingTime ( i n seconds )
k s . s a l t = g e n e r a t e random v e c t o r , l e n g t h : LUKS_SALTSIZE
s p l i t K e y = A F s p l i t ( masterKey ,
masterKeyLength ,
ks . s t r i p e s )

// s o u r c e
// s o u r c e l e n g t h
// number o f s t r i p e s

s p l i t K e y L e n g t h = masterKeyLength ∗ k s . s t r i p e s
pwd = r e a d password from u s e r i n p u t
pwd−PBKDF2ed = PBKDF2( password ,
ks . s a l t ,
k s . i t e r a t i o n −count
masterKeyLength ) // key s i z e i s t h e same
// a s f o r t h e b u l k d a t a
e n c r y p t e d K e y = e n c r y p t ( phdr . c i p h e r −name ,
phdr . c i p h e r −mode ,
pwd−PBKDF2ed ,
splitKey ,
splitKeyLength )

//
//
//
//
//

c i p h e r name
c i p h e r mode
key
content
content length

w r i t e t o p a r t i t i o n ( encryptedKe y ,
// s o u r c e
k s . key−m a t e r i a l −o f f s e t , // s e c t o r number
splitKeyLength )
// l e n g t h i n b y t e s
k s . a c t i v e = LUKS_KEY_ACTIVE

// mark key a s a c t i v e i n phdr

update k e y s l o t k s i n phdr

Figure 4: Pseudo code for key creation

4. LUKS OPERATIONS

11

r e a d phdr from d i s k
check f o r c o r r e c t LUKS_MAGIC and c o m p a t i b l e v e r s i o n number
masterKeyLength = phdr . key−b y t e s
pwd = r e a d password from u s e r i n p u t
f o r each a c t i v e k e y s l o t i n phdr do a s k s {
pwd−PBKDF2ed = PBKDF2( pwd , k s . s a l t , k s . i t e r a t i o n −count
masterKeyLength )
r e a d from p a r t i t i o n ( en cryptedK ey ,
// d e s t i n a t i o n
k s . key−m a t e r i a l −o f f s e t ,
// s e c t o r number
masterKeyLength ∗ k s . s t r i p e s ) // number o f b y t e s
s p l i t K e y = d e c r y p t ( phdr . c i p h e r S p e c ,
pwd−PBKDF2ed ,
encrypt edKey ,
encrypted )

//
//
//
//

c i p h e r spec .
key
content
content length

m a s t e r K e y C a n d i d a t e = AFmerge ( s p l i t K e y , m a s t e r k e y L e n g t h ,
ks . s t r i p e s )
MKCandidate−PBKDF2ed = PBKDF2( masterKeyCandidate ,
phdr . mk−d i g e s t −s a l t ,
phdr . mk−d i g e s t −i t e r ,
LUKS_DIGEST_SIZE)
i f e q u a l ( MKCandidate−PBKDF2ed , phdr . mk−d i g e s t ) {
b r e a k l o o p and r e t u r n m a s t e r K e y C a n d i d a t e a s
c o r r e c t m a s t e r key
}
}
r e t u r n e r r o r , password d o e s not match any k e y s l o t

Figure 5: Pseudo code for master key recovery

5. CONSTANTS

12

4.5 Password changing
The password changing is a synthetic operating of ”master key recovery”, ”new
password adding”, and ”old password revocation”.

5 Constants
All strings and characters are to be encoded in ASCII.
Symbol

Value

Description

LUKS_MAGIC
LUKS_DIGESTSIZE

{’L’,’U’,’K’,’S’,
0xBA,0xBE}
20

LUKS_SALTSIZE

32

LUKS_NUMKEYS
LUKS_KEY_DISABLED

8
0x0000DEAD

LUKS_KEY_ENABLED

0x00AC71F3

LUKS_STRIPES

4000

LUKS_ALIGN_KEYSLOTS

4096

LUKS_SECTOR_SIZE

512

partition
header
starts with magic
length of master key
checksum
length
of
the
PBKDF2 salts
number of key slots
magic for disabled
key slot in keyblock[i].active
magic for enabled
key slot in keyblock[i].active
number of stripes
for AFsplit.
See
[Fru05b] for rationale.
Default alignment
for
keyslot
in
bytes.11
LUKS version 1 always use sector of
fixed size 512 bytes.

11 Former version of this definition mentioned alignment to LUKS_SECTOR_SIZE only
while reference implementation always used alignment to 4096 bytes. It is also required on
modern drives with 4096 bytes sectors.

BIBLIOGRAPHY

13

Bibliography
[BCK97]

Mihir Bellare, Ran Canetti, and Hugo Krawczyk. The HMAC
papers. https://cseweb.ucsd.edu/~mihir/papers/hmac.html, 19961997.

[Fru04]

Clemens Fruhwirth. TKS1 - An anti-forensic, two level, and iterated key setup scheme. https://www.kernel.org/pub/linux/utils/
cryptsetup/LUKS_docs/TKS1-draft.pdf, 2004.

[Fru05a]

Clemens Fruhwirth. Fruhwirth’s Cryptography Website. http://
clemens.endorphin.org/cryptography, 2005.

[Fru05b]

Clemens Fruhwirth. New methods in hard disk encryption. http:
//clemens.endorphin.org/nmihde/nmihde-A4-ds.pdf, 2005.

[Gut96]

Peter Gutmann. Secure Deletion of Data from Magnetic and
Solid-State Memory. https://www.cs.auckland.ac.nz/~pgut001/
pubs/secure_del.html, 1996.

[Kal97]

Burt Kaliski. RFC 2898; PKCS #5: Password-Based Cryptography
Specification Version 2.0. http://www.faqs.org/rfcs/rfc2898.html,
1996-1997.

[TBBC10] Meltem Sönmez Turan, Elaine Barker, William Burr, and Lily
Chen. Recommendation for password-based key derivation, part
1: Storage applications. NIST SP 800-132, https://csrc.nist.gov/
publications/detail/sp/800-132/final, 2010.

A. PHDR AS C STRUCT

14

A PHDR as C struct
#d e f i n e
#d e f i n e
#d e f i n e
#d e f i n e
#d e f i n e

LUKS_MAGIC_L
LUKS_CIPHERNAME_L
LUKS_CIPHERMODE_L
LUKS_HASHSPEC_L
UUID_STRING_L

s t r u c t luks_phdr {
char
uint16_t
char
char
char
uint32_t
uint32_t
char
char
uint32_t
char

6
32
32
32
40

magic [ LUKS_MAGIC_L ] ;
version ;
cipherName [ LUKS_CIPHERNAME_L ] ;
cipherMode [LUKS_CIPHERMODE_L ] ;
hashSpec [ LUKS_HASHSPEC_L ] ;
payloadOffset ;
keyBytes ;
mkDigest [ LUKS_DIGESTSIZE ] ;
m k D i g e s t S a l t [ LUKS_SALTSIZE ] ;
mkDigestIterations ;
u u i d [ UUID_STRING_L ] ;

struct {
uint32_t a c t i v e ;
/∗ parameters f o r PBKDF2 p r o c e s s i n g ∗/
uint32_t p a s s w o r d I t e r a t i o n s ;
char
p a s s w o r d S a l t [ LUKS_SALTSIZE ] ;
/∗ parameters f o r AF s t o r e / l o a d ∗/
uint32_t keyMaterialOffset ;
uint32_t s t r i p e s ;
} k e y b l o c k [LUKS_NUMKEYS ] ;
};

B Cipher and Hash specification registry
Even if the cipher-name and cipher-mode strings are not interpreted by any
LUKS operation, they must have the same meaning for all implementations
to achieve compatibility among different LUKS-based implementations. LUKS
has to ensure that the underlaying cipher system can utilise the cipher name
and cipher mode strings, and as these strings might not always be native to the
cipher system, LUKS might need to map them into something appropriate.
Valid cipher names are listed in Table 1.
Valid cipher modes are listed in Table 2. By contract, cipher modes using
IVs and tweaks must start from the all-zero IV/tweak. This applies for all
calls to the encrypt/decrypt primitives especially when handling key material.
Further, these IVs/tweaks cipher modes usually cut the cipher stream into
independent blocks by reseeding tweaks/IVs at sector boundaries. The all-zero

B. CIPHER AND HASH SPECIFICATION REGISTRY
cipher name

normative document

aes
twofish

Advanced Encryption Standard - FIPS PUB 197
Twofish: A 128-Bit Block Cipher -

serpent
cast5
cast6

15

https://www.schneier.com/paper-twofish-paper.html
https://www.cl.cam.ac.uk/~rja14/serpent.html

RFC 2144
RFC 2612
Table 1: Valid cipher names

mode

description

ecb
cbc-plain

The cipher output is used directly.
The cipher is operated in CBC mode. The CBC chaining
is cut every sector, and reinitialised with the sector number
as initial vector (converted to 32-bit and to little-endian).
This mode is specified in [Fru05b], Chapter 4.
The cipher is operated in ESSIV mode using hash for generating the IV key for the original key. For instance,
when using sha256 as hash, the cipher mode spec is “cbcessiv:sha256”. ESSIV is specified in [Fru05b], Chapter 4.

cbc-essiv:hash

xts-plain64

http://grouper.ieee.org/groups/1619/email/pdf00086.
pdf, plain64 is 64-bit version of plain initial vector

Table 2: Valid cipher modes
hash-spec string

normative document

sha1
sha256
sha512
ripemd160

RFC 3174 - US Secure Hash Algorithm 1 (SHA1)
SHA variant according to FIPS 180-2
SHA variant according to FIPS 180-2
http://www.esat.kuleuven.ac.be/~bosselae/
ripemd160.html

Table 3: Valid hash specifications

IV/tweak requirement for the first encrypted/decrypted block is equivalent to
the requirement that the first block is defined to rest at sector 0.
Table 3 lists valid hash specs for hash-spec field. A compliant implementation does not have to support all cipher, cipher mode or hash specifications.

