Block encryption in OpenBSD
OpenBSD's block encryption is slightly different than on Linux or FreeBSD.
Linux uses dm-crypt
or LUKS
, FreeBSD uses geli
or gbde
. On OpenBSD 5.7 the user can utilise softraid0
driver to acquire the same thing. Please note that you could also use vnconfig
's internal encryption (Blowfish), but on vnconfig
's manpage the maintainer says this method is deprecated. So, I won't even consider it here.
The plan is the same as in other systems:
First we need to create a container file, ideally basing its initial content on
/dev/urandom
or similar,Second, we need to create a loop device, so the file will become a device.
softraid0
's driver --bioctl
accepts only devices as arguments.Third, after creating the virtual device, we need to insert an encryption layer on it (
softraid0
),Last, we can later create the filesystem and mount it to some directory.
So, let's go!
Creating a container file
This is pretty straightforward. We can use dd
to copy the contents of /dev/urandom
to a file:
$ dd if=/dev/urandom of=encrypted_storage.bin bs=1M count=10
This command-line will create a file with 10 megabytes of random bytes in it.
Creating a loop device
OpenBSD contains a command named vnconfig
for creation of loop devices. The name comes from "virtual node configuration", where "virtual node" is a terminology used for loop devices.
The kernel installed by default supports adding 4 vn's. Since OpenBSD removed the ability to dynamically load kernel modules, I guess we're stuck with that.
Here's how you can create a loop device:
$ sudo vnconfig vnd0 encrypted_storage.bin
$ sudo vnconfig -l
vnd0: covering encrypted_storage.bin on sd0a, inode 2808930
vnd1: not in use
vnd2: not in use
vnd3: not in use
vnd0
is the name of the first virtual node that is available.
vnconfig -l
showed us the status of virtual node allocation. It's easy to see that vnd0
is allocated, rest of vn's are unallocated. But, there is a slight complication.
Unlike on Linux, you don't refer to these nodes by /dev/vnd0
or anything like that. In fact, /dev/vnd0
doesn't even exist. But we'll see that in a minute.
Creating an encryption layer
First we need to prepare our device for softraid0
by creating BSD partitions.
Preparations
BSD partitions live inside normal MBR partitions, so we need to create an MBR partition first!
Creation of normal MBR partition is done by the fdisk
command. The name of the device will be our vnd0
device, but we can refer to it only by the /dev/rvnd0c
device. Now let's see:
/dev/rvnd0c
is a character device forvnd0
. "c" at the end of the device name means that we want to refer to the whole disk, not a partition of any kind./dev/vnd0c
is a block device forvnd0
. "c" at the end means the same thing as inrvnd0c
.
fdisk
only accepts character devices, so we need to refer to our virtual node device by using /dev/rvnd0c
.
$ sudo fdisk -i /dev/rvnd0c
Do you wish to write new MBR and partition table? [n] y
Warning CHS values out of bounds only saving LBA values
Writing MBR at offset 0.
The -i
argument will create a new MBR partition table with one partition covering the whole disk. This is perfect for creation of another layer of BSD partitions.
We can verify the allocation by using fdisk /dev/rvnd0c
:
$ sudo fdisk /dev/rvnd0c
Disk: /dev/rvnd0c geometry: 204/1/100 [20480 Sectors]
Offset: 0 Signature: 0xAA55
Starting Ending LBA Info:
#: id C H S - C H S [ start: size ]
-------------------------------------------------------------------------------
0: 00 0 0 0 - 0 0 0 [ 0: 0 ] unused
1: 00 0 0 0 - 0 0 0 [ 0: 0 ] unused
2: 00 0 0 0 - 0 0 0 [ 0: 0 ] unused
*3: A6 1 0 29 - 203 0 100 [ 128: 20272 ] OpenBSD
Now we can start creating BSD partitions. We will need 1 partition, unless your needs are different.
Creation of 1 partition can be done with disklabel
. During installation of OpenBSD you've already used disklabel
, so you'll probably know how to use it. disklabel
seems to accept both block and character devices, so it probably doesn't matter if you pass rvnd0c
or vnd0c
here:
$ sudo disklabel -E /dev/rvnd0c
Label editor (enter '?' for help at any prompt)
First we can make sure our BSD partition layout is empty by using the p
command:
> p
OpenBSD area: 0-20480; size: 20480; free: 20480
# size offset fstype [fsize bsize cpg]
c: 20480 0 unused
Remember, the 'c' partition is a reference to the whole disk. This output doesn't mean that there is a 'c' partition.
If it's empty, let's use a
command to add a parition:
> a
partition: [a]
offset: [0]
size: [20480]
FS type: [4.2BSD] RAID
Notice I've used a different FS type
here. I've used RAID
filesystem type, because this partition will be used by softraid0
later. softraid0
would probably fail to install itself in 4.2BSD
partition (I haven't checked that though).
Let's verify that everything went well by printing the partition table once again:
> p
OpenBSD area: 0-20480; size: 20480; free: 0
# size offset fstype [fsize bsize cpg]
a: 20480 0 RAID
c: 20480 0 unused
Everything seems OK, we can save & quit the partition table by using the q
command:
> q
Write new label?: [y] y
Now our container is prepared for softraid0
.
Creation of softraid0
We can finally create the encryption layer. Since we have every preprequisite already covered, this is very easy.
We will use bioctl
command to interface with softraid0
.
$ sudo bioctl -c C -l /dev/vnd0a softraid0
-c C
will tell bioctl
that we would like to use CRYPTO
RAID discipline. This basically means that we won't actually use RAID functionality, we just want an encryption layer.
-l /dev/vnd0a
specifies the target device we would like to use. We're giving the block device here, because bioctl
wants a block device, and we specify the 'a' partition here as well, because we've created it in the disklabel
step few paragraphs above.
softraid0
is the name of the driver to use, and it needs to stay just like this.
The driver tool will ask us for the passphrase. It won't be echoed, just specify it and we're done here.
$ sudo bioctl -c C -l /dev/vnd0a softraid0
Passphrase:
softraid0: CRYPTO volume attached as sd1
Make sure to write it properly, because bioctl
will not ask twice.
The algorithm used is AES XTS 256, which is a standard one. You don't really have to modify it, because it's considered to be secure. You can modify the number of encryption key generation rounds with the -r
option. Please check man bioctl
for more information on this.
We can see that we have a new device now, sd1
. It's already encrypted and we can finally create a filesystem on it.
We could partition it with fdisk
and disklabel
, but it seems that this isn't necessary. We can just refer to this device with the 'c' suffix, which refers to the whole disk.
Remember, the rsd1c
device means that we want to access the character device of sd1c
. sd1c
means that we would like to refer to the whole space of sd1
, without considering any partitions. newfs
doesn't accept block devices, so we can't use sd1c
here, we have to use rsd1c
.
$ sudo newfs /dev/rsd1c
newfs: reduced number of fragments per cylinder group from 1240 to 1232 to enlarge last cylinder group
/dev/rsd1c: 9.7MB in 19952 sectors of 512 bytes
5 cylinder groups of 2.41MB, 154 blocks, 384 inodes each
super-block backups (for fsck -b #) at:
32, 4960, 9888, 14816, 19744,
We can mount the filesystem now:
$ sudo mount /dev/sd1c /tmp/disk
Done! We have a new encrypted directory with 10 megabytes of free space in it.
$ df -h
Filesystem Size Used Avail Capacity Mounted on
/dev/sd0a 27.6G 2.7G 23.5G 10% /
/dev/sd1c 9.3M 2.0K 8.9M 0% /tmp/disk
Achievement unlocked: creation of your first encrypted storage on OpenBSD ;).