Pages

Wednesday, May 8, 2013

Multiple Encrypted Disks with Linux

This is a fallow up to the parent guide, Full Disk Encryption with Linux. If you have not yet read it, then you are advised to do so before continuing with this one.

Encrypting you entire hard drive is great. But what if you like me, have more than one hard drive in your computer? One thing that is not great, is having to enter multiple passwords on each boot. Well, you don't have to.

The magic word here is Key File. It is a small file containing some random bytes which can be used as a key to unlock an encryption without using a password. An if you are a person that sucks at coming up with great passwords, it will in most cases be more secure than any password you would assign an encryption. The insecure part is how you store it.

In this guide, we will store this key on our primary encrypted hard drive. It will not be accessible until the first drive has been unlocked. We can then use it to unlock any additional drives that you may have attached to your computer, and get away with only having to type in one single password to unlock multiple drives.


Preparing the hard drive


You can skip this step if you already have an additional and fully encrypted hard drive, and just want to know how to assign a key to it.

Otherwise, let' wipe your drive.

shred -v /dev/sd<Y>

Remember to change Y to the letter matching your additional drive.

Now let's partitioning this drive. We will just create one single partition which will hold the encryption. Also, we will not be using LVM in this guide as we do not need things like SWAP or an OS on it. We have this on the primary disk.

cryptsetup -y --cipher aes-xts-plain --key-size 512 luksFormat /dev/sd<Y>

We will also need it unlocked in order to use it.

cryptsetup luksOpen /dev/sd<Y> <Enc_Name_Add>

And last, creating a new file system inside the encryption.

mkfs.ext4 -L Additional <Enc_Name_Add>

You can use whatever file system or label that you wish.


Creating the key


dd if=/dev/urandom of=/root/encryption.key bs=4096 count=1
chmod 0440 /root/encryption.key

Now we have an 4096bit key and it is only accessible by root, which means that it is quite secure even on a booted system.


Assigning the key


In order to use this key, we need to assign it to the encryption.

cryptsetup luksAddKey /dev/sd<Y> /root/encryption.key

Now the encryption can be unlocked by both the assigned password and this key.


Adding the encryption to crypttab


We will also need to add the encryption and key to crypttab to let the boot loader know how to handle this. Open /etc/crypttab with a file editor and add the line below.

<Enc_Name_Add> /dev/sd<Y> /root/encryption.key luks


Adding the unlocked partition to fstab


If you would like the partition to be mounted during boot, you will need to add it to fstab. Open the file /etc/fstab and add the line below.

/dev/mapper/<Enc_Name_Add> /media/additional ext4 defaults 0 2


Update grub and boot loader


Now we just need to rebuilt the kernel image, reboot and we are done.

update-grub
update-initramfs -u

You can redo this guide for as many disks as you like.

Full Disk Encryption with Linux

A great thing about Linux, is the built-in subsystem DMCrypt, which, with some help from the brilliant Initrd, allows you to make a full disk encryption, including the root partition (Boot excluded of cause) and have it unlocked by a key file or password during boot, all without any third party software. This guide will show you how to encrypt your entire hard drive and set up your computer to unlock it on each boot using a password.

What is even better, is Logical Volume Manager.  This will allow us to create partitions inside a partition, which means that we only need to encrypt one partition on the hard drive, and then create whatever volumes we need, inside that single encrypted partition.

Because Ubuntu is the most used distro of all the available once, this guide will use this for the examples. But it should be easy enough to incorporate this guide into other distro's as well, especially since this guide will be using a terminal to do all of the work, and the shell is mostly the same across all distro's.

Before we can continue, you need to download Ubuntu (Or any distro  of your choice), and create a live CD or USB Pen. Then boot up the live system, and once in the UI, press Ctrl+Alt+F1 to enter a terminal.

This guide will assume that you know your way around Linux. So we will not cover anything about creating live disks or how the shell works. You can google it if you don't already know. This is all about the encryption part.


Erasing the hard drive


The first thing to do, is erasing any existing data on the hard drive and replacing it with random bytes. Even though the hard drive will be encrypted, attachers will still be able to see which part of the drive contains any data. This allows them to focus on that specific part of the drive, and making it much easier cracking it. By placing random bytes across the whole drive, we hide the real data which makes it much harder to determinant which parts of the drive contains anything worth cracking.

shred -v /dev/sd<X>

Remember to replace X with the letter matching your drive. 


Preparing the hard drive


Next we need to create a new partitioning table. By wiping the drive, the existing table was erased along with the rest of the content. Use fdisk, or another partition manager, to create the table below.

Device  Type  Size
/dev/sd<X>1  Primary  1GB
/dev/sd<X>2  Extended  Everything
/dev/sd<X>5  Logical  Everything


Creating the encryption


Now we create the encryption on /dev/sd<X>5. This is the partition that will store our logical volumes.

cryptsetup -y --cipher aes-xts-plain --key-size 512 luksFormat /dev/sd<X>

After you have typed in the password that you wish to use, we need to unlock the encryption in order to use it.

cryptsetup luksOpen /dev/sd<X> <Enc_Name>

The Enc_Name is the name that will be used for the device map. It will create /dev/mapper/<Enc_Name> which is the entry point (door if you will) to the device behind the encryption. Just replace Enc_Name with the name that you wish to use.


Creating the LVM volumes


In this guide, we will be creating 3 volumes. 1 for SWAP, one for root and one for home. You can of cause create whatever you need or want.

Before we can create the volumes, we need to initiate our encrypted volume for LVM and create the volume group that will store the volumes.

pvcreate /dev/mapper/<Enc_Name>
vgcreate <Vg_Name> /dev/mapper/<Enc_Name>

Replace Vg_Name with the name that you wish for your volume group.

Now we are ready to create the actual volumes.

lvcreate -n swap -L 6G <Vg_Name>
lvcreate -n system -L 25G <Vg_Name>
lvcreate -n home -l 100%FREE <Vg_Name>

We now have 3 new devices
  1. /dev/mapper/<Vg_Name>-swap
  2. /dev/mapper/<Vg_Name>-system
  3. /dev/mapper/<Vg_Name>-home 
You can change the names to something else if you'd like, and/or change the sizes. The last volume we created are assigned 100%FREE, which means whatever is left after creating the first two. 


Installing the OS


It is now time to get the OS installed. Press Ctrl+Alt+F7 to get back into the live system UI and select install. Once you get to the partitioning part, select manual. Now assign appropriate mount points to the 3 logical volumes that we created before and use /dev/sd<X>1 as boot. Continue the installation. Once done, do NOT reboot, instead press Ctrl+Alt+F1 again to get back into the terminal.


Set up chroot


Now that we have the OS installed, we need to make some changes to it, but before we can do that, we need for it to act as the main OS. In other words, we need some help from chroot.

mkdir /mnt/system
mount /dev/mapper/<Enc_Name>-system /mnt/system
mount /dev/sd<X>1 /mnt/system/boot
mount --rbind /dev /mnt/system/dev
mount --rbind /sys /mnt/system/sys
mount --rbind /proc /mnt/system/proc
chroot /mnt/system

You should now have entered a new apparent root directory and we are ready to make changes to the OS that you have just installed.


Set up crypttab


The first thing that we need to do here, is edit/create /etc/crypttab. This is a file which will tell the boot loader how to handle the encrypted partition, or more accurate, it will tell the system how initrd should be structured once we rebuild it.

Open  /etc/crypttab with a file editor like nano, and append the content below.

<Enc_Name> /dev/sd<X>5 none luks,retry=1

This will tell the boot loader that /dev/sd<X>5 contains a luks encrypted partition, which should be decrypted to the device map <Enc_Name>. The none part is where we could have assigned a key file, without it, a password prompt will be used instead.


Loading modules


The second thing to do, is have some specific modules loaded on boot, which are needed to unlock the partition.

Open the file /etc/initramfs-tools/modules

dm-crypt
aes-x86_64 (aes-i586 is you are using 32bit)
xts
sha256_generic
sha512_generic
ahci


Recompiling kernel image


And last, we regenerate initrd

update-initramfs -u

Reboot your computer. During boot, you will be prompted to enter a password. Enter the password and your hard drive will decrypted and the computer will continue it's regular boot.

Next time you need to upgrade or for other reasons reinstall your OS, all you have to do, is decrypt/unlock the encrypted partition and then fallow this guide from the parts after the installation of the OS. Everything above that is a one time thing.

Tuesday, May 7, 2013

Redirecting stderr to a function

So, I was writing a shell script where I have made a custom log function to be used for custom messages, errors and warning. However, I also wanted to store everything from stderr in this log file, which I thought would be no big deal. I just added the below code.

exec 2> >(Log)

And then I added my Log function to the script

Log() {
    if [ -z "$1" ]; then
        read Message
    else
        Message="$1"
    fi

    ....
}

And it was working great, until I tested it in Born Shell. Here I got an redirect error. So I needed to look around for another way to do this and I stumbled across an article from Chris Siebenmann.  This is a great example, but I needed to append this to the whole script and not just one single command. This however was easy enough, I just needed to append a sub-process to all of my script content.

Log() {
    if [ -z "$1" ]; then
        read Message
    else
        Message="$1"
    fi

    if [ -n "$Message" ]; then
        ....
    fi
}

exec 3>&1

(
    .... Execute everything from here


) 2>&1 >&3 3>&- | Log

Now everything from stderr will be parsed to the function, and it will work with both Bash and Sh.