LUKS: Formatting the Partition

Introduction

When writing this tutorial, I've referenced the [2] Gentoo Linux guide and added some of my own observations and scripts. This guide should provide you with steps of how you can create an encrypted system partition on Linux, but it will also provide you with general observations about doing just that. If you read this article series, you'll gain some knowledge of what is needed to encrypt your system partition as well as the knowledge of the booting processes under Linux. We'll talk about LUKS, LVM, Grub, Gentoo and Initrd. ** **

It's often the case that we may lose our laptops, or that they get stolen. In such cases, the only real protection against data leakage is disk encryption. We need to ensure that even if we lose the laptop or the laptop is stolen, that attackers won't be able to access our data stored on the hard drive.

We'll be using block device encryption, which protects the data on a block device by encrypting it. To access the device's decrypted contents, a user must provide a password or key as authentication.

There are a number of alternatives we could use when encrypting the whole system partitions, which can be seen here: [1]. The best known encryption software products are Truecrypt and LUKS. Truecrypt is well known for having good support for Windows users. If we want to encrypt our whole Windows system partition, we should choose Truecrypt for our encrypting software, since we can do it easily with just a few clicks. However, the Truecrypt support in Linux is lacking; we can't encrypt the whole system partition with Truecrypt, which is its main drawback. Thus, we have to turn to alternative encryption software, such as LUKS, which is most well-known encryption program on Linux.

Since this article talks about encrypting partitions on Linux, we'll be using the LUKS software to encrypt our system partition. In addition to LUKS, which does the encryption part, we'll also be using the LVM, which can manage disk drives with ease. When using LVM, we're not bound to our hardware partitions, but we're rather using software logical volumes (software partitions), which is very scalable.

LUKS (Linux Unified Key Setup) is a specification for block device encryption. It establishes an on-disk format for the data, as well as passphrase/key management policy. LUKS uses the kernel device mapper subsystem via the dm-crypt module, which handles encryption and decryption of the device's data. User-level operations, such as creating and accessing encrypted devices, are accomplished through the use of the cryptsetup utility.

When we try to access the encrypted device after installation, we'll be presented with a password prompt. After the correct password has been provided, the system will continue to boot normally. If we used different passwords for multiple encrypted devices, we may need to enter more than one password during the startup of the Linux system.

First things first: we need to have the needed ciphers to be present in the kernel. We can execute the command below to check whether the cipher is available on the system or not:

# cat /proc/crypto | grep name
name : cbc(serpent)
name : cbc(serpent)
name : stdrng
name : lzo
name : arc4
name : aes
name : tnepres
name : serpent
name : twofish
name : blowfish
name : des3_ede
name : des
name : wp256
name : wp384
name : wp512
name : sha512
name : sha384
name : sha256
name : sha224
name : sha1
name : rmd160
name : md5
name : md4
name : twofish
name : aes

There are multiple ciphers available: aes, twofish, etc.

Note that when the encryption is in use, we need to turn off write caching for our disk. We need to do this because write caching stores I/O data on its own volatile memory before writing it to the disk. So in the event of a power failure, data loss and filesystem corruption might occur. If we're applying the encryption on laptop, we need to make sure to shutdown/suspend the system when it's low on battery.

We'll use the cryptsetup command to setup cryptographic volumes for dm-crypt (including LUKS). LUKS is a standard for hard disk encryption - it standardizes a partition header, as well as the format of the data.

Preparing the Disk

From now on, we'll assume we're already in a livecd or some other linux distribution and we have at least one partition, which will be prepared for the new system encrypted partition. In our case, we have partition /dev/sda1 available:

Device Boot Start End Blocks Id System
/dev/sda1 63 78124094 39062016 83 Linux

It's also a good idea to check the hard drive for bad blocks:

# badblocks -c 10240 -s -w -t random -v /dev/sda1

Checking for bad blocks in read-write mode
From block 0 to 39062015
Testing with random pattern: done
Reading and comparing: done
Pass completed, 0 bad blocks found

The above command can be explained as follows: test 10240 blocks at a time (-c 10240), show the progress of the scan (-s), use write-mode test, which writes some bytes on every block of the partition, then reading every block back and comparing the contents (-w), use random test pattern to be read and written to disk blocks (-t random) and use verbose mode (-v). All of this is done on our partition /dev/sda1.

Now let's fill the disk with random data using the /dev/urandom, which will make it impossible to know how much data has been written (when we start storing encrypted data on the disk). Therefore, breaking it becomes much harder.

# dd if=/dev/urandom of=/dev/sda1

Create the partitioning scheme:

/boot /dev/sda1
swap /dev/sda2
/ /dev/sda3

DM-Crypt works by transparently translating between a physical partition, which is encrypted, and a logical partition, which we can mount and use normally. The physical root partition will be /dev/sda3 and the logical unencrypted partition will be /dev/mapper/root.

We need to load a few modules. The ones we load depend on the cipher we plan to use.

# modprobe dm-crypt

# modprobe dm-mod

# modprobe serpent

# modprobe sha256

# modprobe blowfish

# modprobe aes

Formatting the Device as LUKS Encrypted Device

We can initialize a LUKS partition and set up initialization key by passing luksFormat to the cryptsetup command. To create a mapping for a partition with cryptsetup using a password, we can execute the command below:

# cryptsetup --verify-passphrase --cipher serpent-cbc-essiv:sha256
--key-size 256 luksFormat /dev/sda3

WARNING!
========
This will overwrite data on /dev/sda3 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase:
Verify passphrase:

The cryptsetup asked us if we are sure we want to encrypt the partition and we had to confirm by typing an uppercase YES into the command prompt. After that, we supplied the password, which is used to encrypt/decrypt the partition. We don't necessarily have to use a password to protect our partition, but we can use a keyfile or a gpg protected keyfile. The commands for both those cases can be seen below:

To create a mapping for a partition with cryptsetup using keyfile:

# cryptsetup --verify-passphrase --cipher serpent-cbc-essiv:sha256
--key-size 256 luksFormat /dev/sda3 rootkey

To create a mapping for a partition with cryptsetup using gpg protected keyfile:

# gpg --quiet --decrypt rootkey.gpg | cryptsetup --verify-passphrase
--cipher serpent-cbc-essiv:sha256 --key-size 256 luksFormat /dev/sda3

We can use any of the three options presented above, but using a password is the best option in my option, at least for laptop users. If you use any other option you'll have a more secure system (because the chosen password can be weak and easily bruteforacable, while a keyfile cannot be bruteforced in real time), but you're sacrifice simplicity.

After supplying the password or key, the device will be formatted for use. To verify if that is true, we can execute the command below, which will output 'Yes' if the partition has indeed been encrypted or 'No' if some error occurred:

# cryptsetup isLuks /dev/sda3; if [[ $? == 0 ]]; then echo "Yes";
else echo "No"; fi
Yes

To see a summary of the information about our encrypted device we can execute the luksDump command as follows:

# cryptsetup luksDump /dev/sda3
LUKS header information for /dev/sda3

Version: 1
Cipher name: serpent
Cipher mode: cbc-essiv:sha256
Hash spec: sha1
Payload offset: 2056
MK bits: 256
MK digest: 16 2d 07 4b a5 ec 9b 84 14 45 1c 1d ad a9 3a 43 dd 00 d6
65
MK salt: aa 28 fc 71 e8 51 dc 12 40 bd 70 83 00 51 27 da
ef 83 37 11 27 f4 80 5d 76 19 29 31 cc 8b 17 14
MK iterations: 47625
UUID: bc883c93-ad97-4cb0-a6b2-07e0c5e918d5

Key Slot 0: ENABLED
Iterations: 190775
Salt: f6 cb b8 66 e4 ad bf c5 14 7c 20 7a 20 93 75 aa
74 51 3d e3 10 23 18 11 c4 fc f3 54 e7 07 38 e9
Key material offset: 8
AF stripes: 4000
Key Slot 1: DISABLED
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED

We can see that there are 8 key slots that can be used with each LUKS encrypted device. Currently, only the key slot 0 is in use, because we only supplied a password. We can fill optional number of key slots and then use multiple techniques to decrypt the partition. We could also add a keyfile into key slot 1 and decrypt the partition with a keyfile stored on USB drive. If we forgot the USB key somewhere or if we lost it, we could still decrypt the partition with a password stored in key slot 0.

Opening LUKS Partition

To access the device's decrypted contents, mapping must be established using the kernel device-mapper. It's useful to choose a meaningful name for this mapping. LUKS provides a UUID (Universally Unique Identifier) for each device. To find a LUKS device's UUID, we can run the command below:

# cryptsetup luksUUID /dev/sda3
bc883c93-ad97-4cb0-a6b2-07e0c5e918d5

To open a LUKS partition which uses passwords, we need to run the following command:

# cryptsetup luksOpen /dev/sda3 <strong>system</strong>

To open a LUKS partition that uses a keyfile:

# cryptsetup --key-file rootkey luksOpen /dev/sda3<strong>
system</strong>

To open a LUKS partition which uses a gpg protected keyfile:

# gpg --decrypt keyfile.gpg 2>/dev/null | cryptsetup luksOpen
/dev/sda3 <strong>system</strong>

Upon completion the above command, there will be a mapping in /dev/mapper/system. From now on, every time we need to operate on our system partition /dev/sda3 we need to do so using /dev/mapper/system, which represents the decrypted block device.

To see some information about the mapped device, we can use:

# dmsetup info system
Name: system
State: ACTIVE
Read Ahead: 3072
Tables present: LIVE
Open count: 0
Event number: 0
Major, minor: 253, 1
Number of targets: 1
UUID: CRYPT-LUKS1-bc883c93ad974cb0a6b207e0c5e918d5-system

Creating a FileSystem on a Mapped Device

We must use mapped device node /dev/mapper/system as any other block device. To create an ext3 filesystem on the mapped device, we can use the following command:

# mkfs.ext3 /dev/mapper/system

To mount the filesystem on /mnt mountpoint, we can run the command below:

# mount /dev/mapper/system /mnt

Conclusion

We've successfully encrypted the whole /dev/sda3 partition and created a mapping between /dev/sda3 and /dev/mapper/system. We also created an ext3 filesystem on the decrypted partition /dev/mapper/system and mounted it on the /mnt mountpoint. Now we can freely copy/move and delete files in the /mnt directory and when the partition is unmounted, all the contents of that partition are encrypted and safely stored. If we later want to mount the partition again, we must first open it with cryptsetup and provide a password for the system to be able to access the contents of the partition. This ensures that a password is needed whenever we try to access the partition's contents.

References:

[1]: Comparison of disk encryption software, Wikipedia, http://en.wikipedia.org/wiki/Comparison_of_disk_encryption_software.

[2]: DM-Crypt with LUKS,

http://en.gentoo-wiki.com/wiki/SECURITY_System_Encryption_DM-Crypt_with_LUKS#Choosing_a_hibernation_implementation_with_dm-crypt.

Comments