Luks On Disk Format
Luks On Disk Format
Luks On Disk Format
Version 1.1.1
Clemens Fruhwirth <clemens@endorphin.org>
December 8, 2008
Document History
Version
Date
Changes
1.0
22.01.2005
1.0.1
15.01.2006
1.1
18.02.2006
1.1.1
08.12.2008
Introduction
LUKS 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, see [Fru03].
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 sources1 . LUKS is also treaded extensivly in Chapters 5 and
1 such
as a user password
1. OVERVIEW
Overview
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
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 cant 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
2. PREREQUISITES
encrypted master key is stored in the key material section. These sections are
labelled as KMx in the figure above.
2
2.1
Prerequisites
Block encryption system
2.2
Cryptographic hash
2.3
PBKDF2
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 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
2.4
AF-Splitter
(1)
dk = H(dk1 sk )
sn = dn1 D
(2)
(3)
2.4.1
(4)
H1
(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
(6)
Notice the missing subscript of d in contrast to (5). This version will be used
in future LUKS revisions.4
3.1
Version 1
The LUKS partition header has the layout as described in Figure 1. It starts
at sector 0 of the partition. 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 characters5
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.
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 phdrs magic is not present.
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
4 The
transition has not happend yet. It is likely that the transition will occour in
conjunction with a version nummer bump to Version 2. Do not use H2 until then.
5 also known as C string
4. LUKS OPERATIONS
start offset
field name
length
6
data type
description
byte[]
magic
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
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
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
active
unit32 t
iterations
uint32 t
salt
32
byte[]
40
key-material-offset
uint32 t
44
stripes
uint32 t
4. LUKS OPERATIONS
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 (f.i. an incorrect start
of the bulk data can overwrite key material, same is true in reverse).
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 count 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.
4.2
4.3
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
6 The
4. LUKS OPERATIONS
m a s t e r K e y L e n g t h = d e f i n e d by u s e r
m a s t e r K e y = g e n e r a t e random v e c t o r , l e n g t h : m a s t e r K e y L e n g t h
p h d r . magic
phdr . v e r s i o n
p h d r . c i p h e r name
p h d r . c i p h e r mode
p h d r . keyb y t e s
p h d r . mkd i g e s t s a l t
=
=
=
=
=
=
LUKS MAGIC
1
a s s u p p l i e d by u s e r
a s s u p p l i 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 : LUKS SALTSIZE
p h d r . mkd i g e s t i t e r a t i o n c o u n t = LUKS MKD ITER o r u s e r i n p u t
p h d r . mkd i g e s t = PBKDF2( masterKey ,
p h d r . mkd i g e s t s a l t ,
p h d r . mkd 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 r o u n d e d down :
b a s e O f f s e t = ( s i z e o f p h d r ) / 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 m a s t e r K e y L e n g t h ) / SECTOR SIZE + 1
f o r each k e y s l o t i n phdr as ks {
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 . keym 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
}
p h d r . p a y l o a d o f f s e t = b a s e O f f s e t
phdr . uuid = ge n e ra t e uuid
w r i t e phdr to d i s k
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 Gutmanns data erasure
principals [Gut96]. To wipe the sectors containing the key material, start from
the sector as recorded in key slots key-material-offset field, and proceed for
phdr.key-bytes * ks.stripes bytes.
4. LUKS OPERATIONS
m a s t e r K e y = 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 h a s been
r e c o v e r e d by a c o r r e c t p a s s w o r d
m a s t e r K e y L e n g t h = p h d r . keyb 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 k e y s l o t i n d e x i n p h d r 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 ks = phdr . k e y s l o t s [ emptyKeySlotIndex ]
PBKDF2I t e r a t i o n s P e r S e c o n d = benchmark s y s t e m
k s . i t e r a t i o n c o u n t = PBKDF2I t e r a t i o n s P e r S e c o n d
intentedPasswordCheckingTime ( in 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 t e d 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 t e d K e y L e n g t h = masterKeyLength ks . s t r i p e s
pwd = r e a d p a s s w o r d from u s e r i n p u t
pwdPBKDF2ed = PBKDF2( p a s s w o r d ,
ks . s a l t ,
k s . i t e r a t i o n c o u n t
m a s t e r K e y L e n g t h ) // k e y 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 ( p h d r . c i p h e r name ,
p h d r . c i p h e r mode ,
pwdPBKDF2ed ,
splittedKey ,
splittedKeyLength )
//
//
//
//
//
c i p h e r name
c i p h e r mode
key
content
content length
w r i t e to p a r t i t i o n ( encryptedKey ,
// s o u r c e
k s . keym a t e r i a l o f f s e t , // s e c t o r number
splittedKeyLength )
// 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 k e y a s a c t i v e i n p h d r
update k e y s l o t ks i n phdr
10
4. LUKS OPERATIONS
r e a d p h d r from d i s k
c h e c k 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
m a s t e r K e y L e n g t h = p h d r . keyb y t e s
pwd = r e a d p a s s w o r d from u s e r i n p u t
f o r e a c h a c t i v e k e y s l o t i n p h d r do a s k s {
pwdPBKDF2ed = PBKDF2( pwd ,
ks . s a l t ,
k s . i t e r a t i o n c o u n t
masterKeyLength )
r e a d from p a r t i t i o n ( e n c r y p t e d K e y ,
// d e s t i n a t i o n
k s . keym a t e r i a l o f f s e t ,
// s e c t o r number
m a s t e r K e y L e n g t h k s . s t r i p e s ) // number o f b y t e s
s p l i t t e d K e y = d e c ryp t ( phdr . cipherSpec ,
pwdPBKDF2ed ,
encryptedKey ,
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 t e d K e y ,
masterkeyLength ,
ks . s t r i p e s )
MKCandidatePBKDF2ed = PBKDF2( m a s t e r K e y C a n d i d a t e ,
p h d r . mkd i g e s t s a l t ,
p h d r . mkd i g e s t i t e r ,
LUKS DIGEST SIZE )
i f e q u a l ( MKCandidatePBKDF2ed , p h d r . mkd 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 master key
}
}
r e t u r n e r r o r , p a s s w o r d d o e s n o t match any k e y s l o t
4.5
Password changing
11
5. CONSTANTS
Constants
{L,U,K,S, 0xBA,
0xBE }
20
LUKS SALTSIZE
32
LUKS NUMKEYS
LUKS MKD ITER
8
10
0x0000DEAD
0x00AC71F3
LUKS STRIPES
4000
Bibliography
[BCK97] Mihir
Bellare,
Ran
Canetti,
and
Hugo
Krawczyk.
The
HMAC
papers.
http://www.cs.ucsd.edu/users/mihir/papers/hmac.html,
1996-1997.
[Fru03]
[Fru04]
Burt Kaliski.
RFC 2898;
PKCS #5:
PasswordBased
Cryptography
Specification
Version
2.0.
http://www.faqs.org/rfcs/rfc2898.html, 1996-1997.
12
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
6
32
32
32
40
struct {
uint32 t active ;
/ p a r a m e t e r s f o r PBKDF2 p r o c e s s i n g /
uint32 t passwordIterations ;
char
p a s s w o r d S a l t [ LUKS SALTSIZE ] ;
/ p a r a m e t e r s f o r AF s t o r e / l o a d /
uint32 t keyMaterialOffset ;
uint32 t st ripes ;
} k e y b l o c k [ LUKS NUMKEYS ] ;
};
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
13
cipher name
normative document
aes
twofish
serpent
cast5
cast6
description
ecb
cbc-plain
cbc-essiv:hash
normative document
sha1
sha256
sha512
ripemd160