Descifrar y usar particiones al conectar un USB

En esta entrada intentaré presentar un método bastante común para automatizar el uso de particiones (volúmenes) cifrados. Normalmente al cifrar una partición la configuramos de tal forma que al arrancar el sistema operativo, se pregunte por la contraseña para proceder a descifrar y así poder montarla (utilizarla).

En mi caso tengo una partición en la cual guardo mi información personal. Información que tiene valor para mí y que no me gustaría ver en manos de otras personas (en el hipotético caso que roben en mi casa y se lleven mi pc). Interrumpir la secuencia de arranca para preguntar por la contraseña no me parece una buena idea ya que la mayoría del tiempo no uso esa partición.

Lo ideal sería poder hacer algo fácil y rápido que habilite el uso de dicha partición cuando lo necesito. Sin tener que memorizar una contraseña ya que lo usaré poco y es probable que termine olvidándola. La solución es guardar la llave en una unidad flash usb y condicionarlo de tal forma que al ingresar el usb en la máquina se realice todo el proceso automáticamente.

Lo primero es preparar la partición, en mi caso es /dev/sdb1 y usaré twofish en modo cbc:

cryptsetup -y --cipher twofish-cbc-essiv:sha256 --key-size 256 luksFormat /dev/sdb1

Después de esto procedemos a descifrar la partición para poder usarla:

cryptsetup luksOpen /dev/sdb1 cryptmedia

Y como es la primera vez, debemos agregar el sistema de archivos (ext4 en mi caso) es decir, formatearla:

mkfs.ext4 /dev/mapper/cryptmedia

Ya con esto tenemos nuestra partición lista, en mi caso he escogido /srv/media como el lugar donde la usaré, por lo cual, después de crear dicho directorio, cada vez que quiero usarla tendría que:

cryptsetup luksOpen /dev/sdb1 cryptmedia
# (ingresar contraseña)
mount /dev/mapper/cryptmedia /srv/media/

Es precisamente esta parte la que queremos automatizar, usando una unidad usb flash. Para lo cual la preparamos de forma similar a esta:

Disk /dev/sdc: 8103 MB, 8103395328 bytes
250 heads, 62 sectors/track, 1021 cylinders, total 15826944 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: 0x2bcfb20c

   Device Boot      Start         End      Blocks   Id  System
/dev/sdc1            2048        4095        1024   83  Linux
/dev/sdc2            4096    15826943     7911424    c  W95 FAT32 (LBA)

Es decir, una partición pequeña al comienzo y luego otra para el resto del disco, Creamos los sistemas de archivos:

mkfs.ext4 /dev/sdc1
mkfs.vfat -F32 /dev/sdc2

Procederemos a montar la primera partición del usb (que será la que guardará la llave) y generaremos 256 bytes aleatorios (pseudo aleatorios) que usaremos como nuestra llave, como podrán ver la almacenaré también en formato base64, el cual facilita mucho escribirla (incluso en papel) para almacenarla:

mkdir /tmp/tmp
mount /dev/sdc1 /tmp/tmp/
cd /tmp/tmp/
dd if=/dev/random of=key.bin bs=1 count=256
base64 key.bin > key.b64

El fichero key.b64 lo podemos imprimir, copiar, duplicar, etc, esté será nuestra copia de respaldo de la llave, para regresar a la versión utilizable (de ser necesario), usaríamos:

base64 -d key.b64 > key.bin

En este punto tenemos una partición cifrada con una contraseña y una memoria flash usb con otra contraseña mucho más grande (256 bytes). Nos falta asociar la contraseña grande a la partición, crear un script para automatizar el proceso y asegurarnos que dicho script se ejecute automáticamente cada vez que conectamos la memoria usb a la pc.

Agregamos la nueva llave con el siguiente comando:

cryptsetup luksAddKey /dev/sdb1 /tmp/tmp/key.bin
# (ingresamos la contraseña anterior)

Es posible ver las llaves que tenemos con:

cryptsetup luksDump /dev/sdb1

Confirmamos que es posible descifrar la partición usando ambas llaves:

cryptsetup luksClose cryptmedia
cryptsetup luksOpen /dev/sdb1 cryptmedia
# (primera contraseña)
cryptsetup luksClose cryptmedia
cryptsetup luksOpen --key-file /tmp/tmp/key.bin /dev/sdb1 cryptmedia
# (con la contraseña de la memoria usb)
cryptsetup luksClose cryptmedia

Ahora sólo falta automatizarlo, para ello crearemos un script que repita los pasos anteriores y usaremos udev para que llamarlo automáticamente cuando se detecte nuestro usb.

Usando el comando lsusb buscamos el id del fabricante y producto, en mi caso:

Bus 009 Device 006: ID 154b:0044 PNY

Lo que interesa es 154b:0044, creamos el fichero /etc/udev/rules.d/100-mount-cryptmedia.rules con lo siguiente:

ACTION=="add", ATTRS{idVendor}=="154b", ATTRS{idProduct}=="0044", SYMLINK+="mediakey%n", RUN+="/usr/local/bin/mount_media.sh"

Es muy importante la parte de SYMLINK, esto no crearé un link simbólico sin importar el número (sdX) que se le asigne, es decir que siempre tendremos un /dev/mediakeyX disponible, en otras palabras:

ls -lh /dev/mediakey*
lrwxrwxrwx 1 root root  3 Jan 10 00:00 /dev/mediakey -> sdc
lrwxrwxrwx 1 root root 11 Jan 10 00:00 /dev/mediakey0 -> bsg/8:0:0:0
lrwxrwxrwx 1 root root  4 Jan 10 00:00 /dev/mediakey1 -> sdc1
lrwxrwxrwx 1 root root  4 Jan 10 00:00 /dev/mediakey2 -> sdc2
lrwxrwxrwx 1 root root 15 Jan 10 00:00 /dev/mediakey5 -> bus/usb/009/003

En lugar de usar /dev/sdc1 (que puede cambiar) usaremos /dev/mediakey1. Ahora sólo falta crear el script (/usr/local/bin/mount_media.sh) el cual sería algo así:

#!/bin/bash

if [ -e /dev/mapper/cryptmedia ]; then
	exit 0
fi

if grep -q cryptmedia /proc/mounts; then
	exit 0
fi

if grep -q tmpmediakey /proc/mounts; then
	exit 0
fi

mkdir -p /tmp/tmpmediakey
mount /dev/mediakey1 /tmp/tmpmediakey || exit 1

/sbin/cryptsetup luksOpen --key-file /tmp/tmpmediakey/key.bin /dev/sdb1 cryptmedia

umount /tmp/tmpmediakey && rm -rf /tmp/tmpmediakey

mount /dev/mapper/cryptmedia /srv/media

Obviamente este script puede ser mejorado mucho más, pero a modo de explicación e intentando mantenerlo lo más simple posible, funciona. Por último sólo nos queda eliminar la primera llave:

cryptsetup luksRemoveKey /dev/sdb1
# (contraseña a eliminar)

Esto nos deja con una sola llave (la de la memoria usb) en nuestro volumen cifrado.

Acerca de Paco

Manuel Argüelles, Panameño, programador, vegetariano, pervertido y buena gente.
Esta entrada fue publicada en Uncategorized y etiquetada , , , , , . Guarda el enlace permanente.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *