Encrypting a USB Flash Drive

Given how easy it is to lose flash drives, I always make sure to encrypt them if I intend to store any important information on them. In this post, I’m going to go over the steps for creating an encrypted flash drive under Ubuntu. Note that there are a lot of other tutorials out there that pretty much take you through the same thing with some additional information on security and advanced options (for example, this one, or this one). I’m always forgetting the steps, so I wanted to document it for myself!

Finding the Right Device

The first step is to make sure you have the right device selected. This amounts to plugging in the device and checking out how the kernel registers it. Under Ubuntu, a simple command will print out kernel messages for you:

dmesg

That should print out all of the kernel activity that is being logged. You should see near the bottom a lot of output relating to the USB devices:

[5161642.499490] usb 1-1.2: new high-speed USB device number 8 using ehci-pci
[5161642.593412] usb 1-1.2: New USB device found, idVendor=0781, idProduct=5581
[5161642.593423] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[5161642.593429] usb 1-1.2: Product: Ultra
[5161642.593434] usb 1-1.2: Manufacturer: SanDisk
[5161642.593439] usb 1-1.2: SerialNumber: *********************************
[5161642.838071] usb-storage 1-1.2:1.0: USB Mass Storage device detected
[5161642.838160] scsi7 : usb-storage 1-1.2:1.0
[5161642.838357] usbcore: registered new interface driver usb-storage
[5161643.835928] scsi 7:0:0:0: Direct-Access     SanDisk  Ultra            1.00 PQ: 0 ANSI: 6
[5161643.837080] sd 7:0:0:0: Attached scsi generic sg2 type 0
[5161643.837920] sd 7:0:0:0: [sdc] 31266816 512-byte logical blocks: (16.0 GB/14.9 GiB)
[5161643.838987] sd 7:0:0:0: [sdc] Write Protect is off
[5161643.839003] sd 7:0:0:0: [sdc] Mode Sense: 43 00 00 00
[5161643.840239] sd 7:0:0:0: [sdc] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
[5161643.862424]  sdc: sdc1
[5161643.866058] sd 7:0:0:0: [sdc] Attached SCSI removable disk

In this case, you can see that I plugged in a SanDisk USB flash drive, with 16 GB of storage on it. More importantly, the kernel has told us what device name it has assigned to the drive:

[5161643.862424]  sdc: sdc1

As always, it’s a good idea to double check the drive information. The following command prints out the partitions on /dev/sdc:

sudo fdisk /dev/sdc -l

This will print out information relating to the device:

Disk /dev/sdc: 16.0 GB, 16008609792 bytes
255 heads, 63 sectors/track, 1946 cylinders, total 31266816 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
 
   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1             192    31266815    15633312    c  W95 FAT32 (LBA)

This matches what we expected to see: /dev/sdc is a 16 GB drive, formatted with FAT 32. This is good.

Delete the Existing Partition

The next step is to delete the existing partition, and create a new Linux partition.

WARNING: this will destroy everything on the drive, so be careful! Make sure that the contents of the drive are backed up, and that you check to make sure you are typing the right commands and the right drive letters. As always, make sure you educate yourself if you don’t know what the command is going to do. I am not responsible for any damages that may occur – run any of the following commands at your own risk!

sudo fdisk /dev/sdc

You will now be in the fdisk program. It’s a good idea just to print out the contents of the drive again to confirm this is the correct device:

p

This should give us the same information we saw above:

Disk /dev/sdc: 16.0 GB, 16008609792 bytes
255 heads, 63 sectors/track, 1946 cylinders, total 31266816 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
 
   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1             192    31266815    15633312    c  W95 FAT32 (LBA)

Since this is the only partition, the delete operation will be applied to it:

d

You should see:

Selected partition 1

Create the New Parition

You can now create a new partition that will hold the encrypted container:

n

And, you will be asked for the type of partition:

Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p):

If this is the only partition that you will be creating on the stick, then you will want to make a primary partition. If you want to make many partitions on the stick, then things get a little trickier. For historical reasons, you can only have 4 partitions on any given disk. However, you can create an extended partition that can hold additional logical drives. But, that discussion is beyond this simple tutorial. In this case, I made a primary partition:

p

Next, you will be asked to choose the partition number:

Partition number (1-4, default 1):

In this case, I want to use the default of 1:

1

As a side note, the partition number is associated with the device that you will then mount when it is created. In this case, by making it 1, when I plug it into any computer, it will become /dev/sdX1 where X will depend on what other devices are already mounted. If I made it 2, then it would be /dev/sdX2.

Next, the we are asked for the first sector, and the last sector. I just used the defaults in order to make the partition span the disk. To accept the default values, you just press enter:

First sector (2048-31266815, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-31266815, default 31266815):
Using default value 31266815

With the partition creation complete, I printed out the new partition information with p to see what the new partition looked like:

Command (m for help): p
 
Disk /dev/sdc: 16.0 GB, 16008609792 bytes
64 heads, 32 sectors/track, 15267 cylinders, total 31266816 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x805a51a5
 
Device    Boot Start End      Blocks   Id System
/dev/sdc1      2048  31266815 15632384 83 Linux

With the new partition created, I wrote the partition information to the disk with w, which also quits fdisk.

Create the LUKS Container

Usually at this stage of readying a new drive you would format the partition with a filesystem. With encrypted drives however, you need to first create an encrypted container. For this, I used cryptsetup with the luksFormat option. I usually use the default options when it comes to the choice of encryption. For those that are more concerned with choice of encryption and hash options, you can check out the manpages with man cryptsetup.

sudo cryptsetup luksFormat /dev/sdc1

Issuing the command will prompt you with a warning:

WARNING!
========
This will overwrite data on /dev/sdc1 irrevocably.
 
Are you sure? (Type uppercase yes): YES
Enter passphrase:
Verify passphrase:

Make sure you remember the passphrase you type – if you forget it, there is no way to retrieve it. For those interested, the passphrase is stored in a keyslot. Additional passphrases for the same disk can be added to different keyslots. This is useful if more than one person needs to access the disk and you want to have a different passphrase.

Open the Device

Once the container is created, you need to open it. Opening an encrypted container is akin to unlocking it. This is performed with the luksOpen sub-command in cryptsetup:

sudo cryptsetup luksOpen /dev/sdc1 sdc1_crypt

What this does is open the container on /dev/sdc1 and maps it to /dev/mapper/sdc1_crypt. Essentially you write your data as you would normally to the remapped device, which will automatically encrypt and decrypt the data for you as you read and write to the device.

Create the New Filesystem

With the new encrypted container open, you need to create the ext4 filesystem on it:

sudo mke2fs -t ext4 /dev/mapper/sdc1_crypt

This runs through the mke2fs routine:

mke2fs 1.42.9 (4-Feb-2014)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
977280 inodes, 3907584 blocks
195379 blocks (5.00%) reserved for the super user
First data block=0
Maximum filesystem blocks=4001366016
120 block groups
32768 blocks per group, 32768 fragments per group
8144 inodes per group
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208
 
Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

With the format complete, the new encrypted stick is ready to use!

Note: some tutorials suggest writing zeros or other random numbers to the device prior to creating the filesystem. Why? Well most drives are zeroed out initially, so even though your data is encrypted on the drive, an attacker would be able to see where you have written data, as well as how much data has been written to disk. The security issue at play is that the attacker could use that information when trying to crack your encryption. But since flash media has a limited number of write cycles, doing this is somewhat costly. It’s up to you to determine how far you want to take your security.

Check that Everything Works

Once everything is complete, I always run a quick test to make sure there are no problems. First, close the container:

sudo cryptsetup luksClose sdc1_crypt

And then open it again to make sure your password works, and that the contents can be decrypted correctly:

sudo cryptsetup luksOpen /dev/sdc1 sdc1_crypt

Then, mount the device to make sure that you can actually read the contents:

sudo mount /dev/mapper/sdc1_crypt /mnt/Backup

Wrapping Up

Encrypting a drive is really easy these days. Simply partition your drive, create the encrypted container in the new partition, and then format the container with the filesystem of your choice. Just remember when you mount the device that you first must use cryptsetup luksOpen to open the container prior to mounting the filesystem!

Booting a Raspberry Pi From a 16 MB SD Card

Raspberry Pis make great little servers. With low power consumption, they make great devices if you need cheap web services running 24/7. One aspect I dislike about them however, is that they need to boot using an SD card. Given the limited number of write cycles that most SD cards have, I hate having to run anything more than the bootloader off of one.

While there are many tutorials that talk about how you can clone the SD card to a USB drive, I wanted to do something a little different. Why waste a 4 GB SD card? I have lots of smaller SD cards kicking around. In this post, I’ll discuss how I made my Raspberry Pi boot from a 16 MB SD card and use a USB hard drive for the root filesystem.

Running the Pi from a USB Hard Drive

Most tutorials have you simply clone your SD card to a USB hard drive, and then edit the cmdline.txt file to point to the USB hard drive when booting the main OS. This solves the problem of moving the root filesystem to a more robust storage medium, but ties up a 4 GB SD card that I could be using elsewhere. I know this isn’t too big of a problem, but it does mean buying a bunch of 4 GB SD cards for all my Raspberry Pis.

On a related note, I have a number of digital cameras that I have purchased over the years, and most of them came with a 16 MB SD card. Back in the day, 16 MB was a lot of storage space, but given the megapixel counts that come with most cameras, 16 MB can usually only store a few pictures. In my case, they sit in a stack in my desk drawer, gathering dusk and sulking.

This got me thinking: I’d really love to use the 16 MB card in the Raspberry Pi (plus a hard drive), and use the 4 GB card in my cameras.

Update January 20, 2015: Mike Redrobe discussed on his blog how to do this in May 2014, with great instructions on how to do this under Windows. Also, this blog noted how to do it in 2012, but without the step-by-step breakdown. Many other sources (like this blog, and this blog) outline how to modify the boot partition to mount the root filesystem from a USB drive.

What is Where

I took one of my 4 GB SD cards that had Raspbian on it, and examined how the card was formatted. There is a small MS-DOS partition used for the bootloader, and the rest of the card is used for the root filesystem. The MS-DOS partition is what interests me, because this is what the Raspberry Pi needs to see in order to bootstrap the OS. Here’s the contents:

# ls -lh /boot
total 9.7M
-rwxr-xr-x 1 root root  18K Dec 21 10:53 bootcode.bin
-rwxr-xr-x 1 root root  120 Dec 21 11:14 cmdline.txt
-rwxr-xr-x 1 root root 1.3K Dec 21 11:14 config.txt
-rwxr-xr-x 1 root root 2.3K Dec 21 10:53 fixup_cd.dat
-rwxr-xr-x 1 root root 6.0K Dec 21 10:53 fixup.dat
-rwxr-xr-x 1 root root 9.0K Dec 21 10:53 fixup_x.dat
-rwxr-xr-x 1 root root  137 Dec 24 12:29 issue.txt
-rwxr-xr-x 1 root root 3.2M Dec 21 10:53 kernel.img
-rwxr-xr-x 1 root root  19K Sep 25  2013 LICENSE.oracle
-rwxr-xr-x 1 root root 538K Dec 21 10:53 start_cd.elf
-rwxr-xr-x 1 root root 2.6M Dec 21 10:53 start.elf
-rwxr-xr-x 1 root root 3.5M Dec 21 10:53 start_x.elf

Most of those files look pretty small… hmm… I wonder how much disk space is actually used:

# df -h .
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdc1        56M  9.7M   47M  18% /mnt/raspbianboot

So on the 60 MB MS-DOS boot partition, 9.7 MB worth of files are used for the bootloader. This is perfect! I can fit those files on a 16 MB SD card!

Preparing the 16 MB SD Card

Step 1 was to format the 16 MB SD card as needed in order to boot Raspbian. So, I stuck the card in the computer and took a look at the partitions on it (under Ubuntu, the device registered as /dev/sdc).

Disclaimer: I use fdisk to delete partitions on the card. If you accidentally specify the wrong device, you can destroy your hard disk partition and make your computer unbootable. These instructions are for educational purposes only. Running any of the commands below is at your own risk!

# sudo fdisk -l /dev/sdc
 
Disk /dev/sdc: 16 MB, 16056320 bytes
2 heads, 32 sectors/track, 490 cylinders, total 31360 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
 
   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1              57       31359       15651+   1  FAT12

Okay, so this is the correct device – 16 MB total storage. It’s currently formatted as FAT12. For the Raspberry Pi to boot, we need a FAT32 filesystem instead. So, I started up fdisk and deleted the primary partition:

# sudo fdisk /dev/sdc
 
Command (m for help): d
Selected partition 1

Next, I created a new primary partition on the card:

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-31359, default 2048): 
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-31359, default 31359): 
Using default value 31359

Next, I changed the partition to W95 FAT32 (LBA). This is type ID c:

Command (m for help): t
Selected partition 1
Hex code (type L to list codes): c

Finally, I needed to mark the new primary partition as bootable:

Command (m for help): a
Partition number (1-4): 1

With that done, I saved the partition information, and quit fdisk:

Command (m for help): w
The partition table has been altered!
 
Calling ioctl() to re-read partition table.
Syncing disks.

Note: if you receive messages about the system retaining the old partition information after you create the new primary, simply remove the card from the card reader, and then re-insert it.

Finally, I created the filesystem on the new partition:

# sudo mkfs -t vfat /dev/sdc1
mkfs.fat 3.0.26 (2014-03-07)

Copying the Boot Files

The next step was to copy the boot files from the original Raspbian 4 GB card to the 16 MB card. I removed the 16 MB card from my card reader, and popped in the Raspbian 4 GB SD card. I created a mount point for it, and mounted the boot partition. Note that the first partition on the card (again registered as /dev/sdc) contains the boot partition. So /dev/sdc1 is the boot partition, while /dev/sdc2 contains the root filesystem:

# sudo mkdir /mnt/raspbianboot
# sudo mount /dev/sdc1 /mnt/raspbianboot

I needed a temporary location to store the files, so I copied them to /tmp:

# sudo cp -r /mnt/raspbianboot /tmp

So far so good. Now to put them onto the 16 MB card. I unmounted the boot partition:

# sudo umount /mnt/raspbianboot

I popped out the Raspbian 4 GB SD card and put in the 16 MB card. To keep things clear, I created a new mount point for it… just so I didn’t confuse myself with what I was mounting. Again, when I took out the 4 GB card and put in the 16 MB card, it registered as /dev/sdc:

# sudo mkdir /mnt/raspbianboot16
# sudo mount /dev/sdc1 /mnt/raspbianboot16

Next, I copied the files from /tmp to the 16 MB SD card:

# sudo cp -r /tmp/raspbianboot/* /mnt/raspbianboot16

The final thing was to modify the boot loader on the 16 MB card to boot from the USB hard drive instead of trying to boot on the second partition of the SD card (which would be bad, since there isn’t one!):

# sudo vi /mnt/raspbianboot16/cmdline.txt

I changed:

root=/dev/mmcblk0p2

To the following:

root=/dev/sda1

I also added two additional flags to the file at the end of the line:

bootdelay rootdelay

I saved the file and unmounted the drive:

# sudo sync
# sudo umount /mnt/raspbianboot16

Cloning Raspbian Wheezy to the USB Hard Drive

The last piece of the puzzle is to clone the other Raspbian root filesystem on the SD card to the USB hard drive. I have a 320 GB USB drive that I use for things like my Deer Detector. First up, I put the Raspbian 4 GB SD card back into my card reader, which registered as /dev/sdc. Next, I plugged in the new USB hard drive. In my machine, the new drive shows up as /dev/sdd. I copied the root partition from the Raspbian 4 GB SD card to the new disk. Note that since I want the root partition, it’s /dev/sdc2 that I want to copy from (remember /dev/sdc1 was the boot partition):

# sudo dd if=/dev/sdc2 of=/dev/sdd bs=4M

One final housekeeping point remained. The Raspbian root filesystem has an fstab that tries to mount / from the SD card. I needed to change that. So, I mounted the new USB hard drive under /mnt/raspbianroot and modified the file:

# sudo mkdir /mnt/raspbianroot
# sudo mount /dev/sdd1 /mnt/raspbianroot
# sudo vi /mnt/raspbianroot/etc/fstab

I needed to change the following line:

/dev/mmcblk0p2  /               ext4    defaults,noatime  0       1

To this:

/dev/sda1  /               ext4    defaults,noatime  0       1

With that done, I unmounted the USB drive, and plugged both the 16 MB SD card and the USB hard drive into the Raspberry Pi (to power the drive, I had to use a powered USB hub, but you get the idea). The Raspberry Pi booted perfectly, and I verified that it was running from the USB hard drive by checking that /dev/sda1 was mounted at /.

Note: the new partition on the USB hard drive will be exactly the size as the partition on the 4 GB SD card. Since I wanted to extend the partition to take up the full drive, I ran fdisk and printed out the current partition information, and made note of the starting block. Then, I deleted the partition, and recreated it using the same starting block. I made sure the partition spanned the entire drive. I wrote the table out, rebooted, and then ran resize2fs to resize the filesystem.

Wrapping Up

Making the Raspberry Pi boot from a 16 MB SD card was pretty easy. Essentially it involves cloning the boot partition to the smaller SD card and the root partition to some other USB storage medium. As long as the boot partition continues to be smaller than 16 MB, this trick will continue to work.