Cifrando uma partição com DM-Crypt + LUKS

A situação é a seguinte: imagine que tenhamos um pendrive no qual são armazenadas informações confidenciais e que, portanto, devem ser protegidas de acessos indevidos. Este é um cenário comum atualmente. A mesma situação se aplica à quem utiliza notebooks no dia-a-dia, e o procedimento aqui apresentado é o mesmo: você pode cifrar uma partição de vazia de um notebook ou uma partição de um pendrive, a única coisa que muda é o nome do dispositivo. Observe, no entanto, que todos os dados da partição a ser cifrada serão perdidos. Então, faça cópias de segurança dos dados antes de tentar cifrar a partição. Uma vez que o procedimento de cifragem tenha sido executado TODOS os dados lá existentes serão perdidos.

Outra informação importante: sempre verifique e certifique-se de estar usando o nome correto do dispositivo (exemplo: /dev/sdb1, /dev/sdc1 etc), porque basta errar uma única vez para que todos os dados existentes sejam perdidos.

Por fim, o objetivo deste artigo é apresentar o procedimento de cifragem de uma partição de disco ou pendrive, mas não assumo nenhuma responsabilidade por eventuais danos provocados pela execução dos comandos apresentados aqui. Este artigo foi publicado com o intuito de ajudar a quem quer que seja e assume que quem o utilize tenha conhecimentos suficientes de Linux para alterar os comandos conforme suas necessidades.

Existem várias soluções capazes de cifrar uma partição no Linux, como o TrueCrypt, que funciona tanto em Linux como em Windows, e o dm-crypt, que será o nosso assunto aqui.

Optei pelo DM-Crypt por ter suporte nativo no kernel do Linux e também por ser uma solução que não depende da existência de interface em modo gráfico.

O suporte à criptografia de discos no Linux é chamado LUKS (Linux Unified Key Setup), que fornece um padrão para o formato de gravação dos dados no disco. No LUKS, todos os dados necessários para o acesso ao dispositivo são armazenados no cabeçalho da partição.

Desde a série 2.6 do kernel do Linux foi introduzida uma nova característica chamada device mapper, que é uma infraestrutura que fornece uma forma genérica de criar camadas virtuais de dispositivos de bloco, que permite que diferentes ações possam ser realizadas nas camadas superiores de um dispositivo de bloco, como por exemplo, concatenação de vários discos e/ou partições diferentes para formar um único dispositivo lógico para o sistema. Este é o caso, por exemplo, do LVM (Linux Volume Manager), que utiliza o conceito de device mapper para criar uma unidade virtual formada por vários discos ou partições.

Mas e o DM-Crypt?

DM-Crypt é um acrônimo para Device Mapper Crypto Target, que oferece uma interface transparente de criptografia para dispositivos de bloco. Basicamente, o usuário define um algoritmo simétrico, uma chave e o modo de geração do vetor de inicialização e pode então criar um novo dispositivo de blocos cifrado. As escritas serão cifradas antes da gravação e as leituras serão decifradas automaticamente. O sistema de arquivos é criado usando esta interface, o que significa que, no disco, os dados serão cifrados.

Agora vamos à parte prática da coisa.

Como exemplo, irei utilizar uma partição criada num pendrive. Atente para o fato de que o processo é o mesmo tanto para uma partição de um pendrive como para uma partição de um disco rígido. O importante é estar atento para o fato de que TODOS os dados da partição serão perdidos durante a cifragem da partição, portanto, faça o backup antes de continuar.

Neste exemplo, vamos considerar que o pendrive está conectado ao computador e que desejamos cifrar a partição 1 do mesmo. O exemplo também, considera que a partição do pendrive foi identificada pelo sistema em /dev/sdb1. Identifique corretamente o seu dispositivo antes de continuar.

Para uma segurança maior, primeiramente grave dados aleatórios na partição. Isto garante que nenhum resquício de informação válida seja mantido na partição. O problema deste processo é que ele pode ser demorado, dependendo do tamanho da partição.

Use o comando shred para gravar dados aleatórios na partição:

# shred -v -n 1 /dev/sdb1
shred: /dev/sdb1: pass 1/1 (random)...
shred: /dev/sdb1: pass 1/1 (random)...8.8MiB/8GiB 0%
shred: /dev/sdb1: pass 1/1 (random)...17MiB/8GiB 0%
shred: /dev/sdb1: pass 1/1 (random)...26MiB/8GiB 0%
shred: /dev/sdb1: pass 1/1 (random)...34MiB/8GiB 0%
...
shred: /dev/sdb1: pass 1/1 (random)...GiB/8GiB 100%

Inicialize a partição com o cryptsetup. Será solicitada a entrada de uma senha (e posterior confirmação). Esta senha deverá ser usada toda vez que o dispositivo for conectado ao sistema. Observe que, antes da senha, o software solicita a confirmação de que você deseja realmente fazer isso, já que TODOS os dados existentes no dispositivos serão sobrescritos e não poderão ser recuperados de forma alguma. Se você tiver certeza de que deseja continuar, digite YES (com letras maiúsculas). O comando é o seguinte:

sudo cryptsetup luksFormat /dev/sdb1

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

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

Quando usamos o DM-Crypt temos, basicamente, duas camadas de software: uma camada formada pelos mecanismos de criptografia, que cuidam de cifrar os dados na gravação e decifrá-los na leitura. Uma segunda camada, situada sobre a camada criptográfica, é formada pelo sistema de arquivos. Assim, uma vez que a camada criptográfica tenha sido estabelecida, criamos o sistema de arquivos desejado sobre a mesma, de forma que, para as aplicações e para o próprio sistema de arquivos todos os acessos fiquem transparentes.

Este mecanismo impõe um passo adicional nos processos de montagem e desmontagem do sistema de arquivos: primeiro deve ser habilitado o acesso ao dispositivo criptográfico e somente depois o sistema de arquivos pode ser montado. Da mesma forma, o processo de desmontagem de um dispositivo de blocos deve ser executado em duas etapas: primeiro desmonta-se o sistema de arquivos seguido do fechamento do dispositivo criptográfico.

Vamos então habilitar a camada criptográfica, criando um dispositivo no device mapper (será solicitada a senha de acesso ao dispositivo):

sudo cryptsetup luksOpen /dev/sdb1 sdb1
Enter passphrase for /dev/sdb1:

Este comando cria o dispositivo /dev/mapper/sdb1, que agora pode ser utilizado da mesma forma que uma partição normal, só que todos os dados serão cifrados antes de serem gravados, e decifrados ao serem lidos, de forma transparente.

Agora, precisamos criar o sistema de arquivos (formatar) sobre o nosso dispositivo (ou partição) cifrado:

sudo mkfs -t ext4 -L COISAS /dev/mapper/sdb1
mke2fs 1.42.12 (29-Aug-2014)
Creating filesystem with 1957883 4k blocks and 489600 inodes
Filesystem UUID: 5a48816c-0488-4cbf-b8c2-ffabf0554102
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632

Allocating group tables: done
Writing inode tables: done
Creating journal (32768 blocks): done
Writing superblocks and filesystem accounting information: done

No exemplo, a partição foi formatada com o sistema de arquivos EXT4, mas poderia ser qualquer outro formato suportado e de sua preferência.

Partição formatada, podemos agora montá-la da mesma forma que faríamos com uma partição normal (este procedimento deve ser utilizado para montagem manual, caso o ambiente gráfico esteja ativo, provavelmente ele o executará automaticamente quando o pendrive ou HD externo for conectado ao computador), utilizando o dispositivo mapeado pelo device mapper:

sudo mount /dev/mapper/sdb1 /mnt/data/

Agora é a parte legal do processo: temos duas camadas para acessar o dispositivo. Quando gravarmos um arquivo no ponto de montagem /mnt/data, os dados serão enviados para o dispositivo lógico /dev/mapper/sdb1. Neste ponto, os dados serão cifrados (criptografados) e gravados efetivamente no dispositivo /dev/sdb1. Esta é a magia das camadas lógicas.

Quando terminarmos de utilizar o dispositivo, precisamos desfazer as coisas na ordem inversa:

Desmonte o sistema de arquivos do dispositivo:

sudo umount /mnt/data

Encerre a camada de criptografia, desvinculando o device mapper do dispositivo real:

sudo cyprtseyup luksClose sdb1

Agora o dispositivo pode ser removido do computador.

Resumo: comandos úteis

Resumo do processo de montagem e desmontagem:

Para montar o dispositivo (nossa partição), precisamos sempre executar os seguintes passos:

sudo cryptsetup luksOpen /dev/sdb1 sdb1
sudo mount /dev/mapper/sdb1 /mnt/data/

Para desmontar este dispositivo (partição, no nosso caso), devemos sempre executar os seguintes comandos:

sudo umount /mnt/data/
sudo cryptsetup luksClose sdb1

Consultando informações da partição cifrada

Com a partição desmontada, podemos consultar o header da mesma:

sudo cryptsetup luksDump /dev/sdb1
LUKS header information for /dev/sdb1

Version:            1
Cipher name:        aes
Cipher mode:        xts-plain64
Hash spec:          sha1
Payload offset:     4096
MK bits:            256
MK digest:          65 8c 39 3b 0c 17 9f d8 0e 85 83 0d dd 39 db 77 48 93 ff ba
MK salt:            8d d5 46 be 3f 2f 3a de c1 ea 46 8a ed af fa 2b
                    dc 6a 8d 21 12 19 b5 ac 6e b7 e3 fd 35 1e 80 c8
MK iterations:      105500
UUID:               c0a4211d-3aea-42bb-b92c-a0d7be49bca8

Key Slot 0: ENABLED
        Iterations:        424543
        Salt:              95 02 a4 02 a5 ca 21 fd 0f e5 53 79 07 1c b6 ca
                           32 54 d7 48 d6 80 3c 34 6a d9 f3 df 6d 52 c8 89
        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

Podemos observar que há apenas uma chave (Key Slot 0): o header do LUKS permite até 8 chaves de acesso a um mesmo dispositivo.

Para adicionar uma chave, use o comando, observando que será solicitada uma senha já configurada no dispositivo:

sudo cryptsetup luksAddKey /dev/sdb1
Enter any existing passphrase:        <- Digite uma das senhas  configuradas
Enter new passphrase for key slot:    <- Digite a nova senha a ser cadastrada
Verify passphrase:                    <- Confirme a nova senha

Listando o header novamente, teremos:

sudo cryptsetup luksDump /dev/sdb1
LUKS header information for /dev/sdb1

Version:            1
Cipher name:        aes
Cipher mode:        xts-plain64
Hash spec:          sha1
Payload offset:     4096
MK bits:            256
MK digest:          65 8c 39 3b 0c 17 9f d8 0e 85 83 0d dd 39 db 77 48 93 ff ba
MK salt:            8d d5 46 be 3f 2f 3a de c1 ea 46 8a ed af fa 2b
                    dc 6a 8d 21 12 19 b5 ac 6e b7 e3 fd 35 1e 80 c8
MK iterations:      105500
UUID:               c0a4211d-3aea-42bb-b92c-a0d7be49bca8

Key Slot 0: ENABLED
        Iterations:        424543
        Salt:              95 02 a4 02 a5 ca 21 fd 0f e5 53 79 07 1c b6 ca
                           32 54 d7 48 d6 80 3c 34 6a d9 f3 df 6d 52 c8 89
        Key material offset:        8
        AF stripes:                 4000
Key Slot 1: ENABLED
        Iterations:                 426666
        Salt:              88 a5 31 5f 77 c4 aa 01 0a 67 9b 42 6b de 08 42
                           5a f9 38 53 ea 6e 2a b3 bc 7d a9 46 b8 0e 61 c3
        Key material offset:        264
        AF stripes:                 4000
Key Slot 2: DISABLED
Key Slot 3: DISABLED
Key Slot 4: DISABLED
Key Slot 5: DISABLED
Key Slot 6: DISABLED
Key Slot 7: DISABLED

Agora pode ser utilizada qualquer uma das senhas configuradas para acessar o dispositivo (Key Slot 0 e Key Slot 1).

Para apagar a senha, devemos escolher o slot que desejamos apagar. Por exemplo, vamos apagar a senha do slot 1, que acabamos de criar (slot 1), lembrando que deve ser utilizada uma das senhas restantes, isto é, qualquer uma das senhas, exceto a que está sendo removida:

sudo cryptsetup luksKillSlot /dev/sdb1 1
Enter any remaining passphrase:

Observe que a chave a ser utilizada para remover a chave indicada deve ser uma das chaves remanescentes, isto é, não podemos remover uma chave utilizando a própria chave.

Verificando o header novamente:

sudo cryptsetup luksDump /dev/sdb1
LUKS header information for /dev/sdb1

Version:            1
Cipher name:        aes
Cipher mode:        xts-plain64
Hash spec:          sha1
Payload offset:     4096
MK bits:            256
MK digest:          65 8c 39 3b 0c 17 9f d8 0e 85 83 0d dd 39 db 77 48 93 ff ba
MK salt:            8d d5 46 be 3f 2f 3a de c1 ea 46 8a ed af fa 2b
                    dc 6a 8d 21 12 19 b5 ac 6e b7 e3 fd 35 1e 80 c8
MK iterations:      105500
UUID:               c0a4211d-3aea-42bb-b92c-a0d7be49bca8

Key Slot 0: ENABLED
        Iterations:        424543
        Salt:              95 02 a4 02 a5 ca 21 fd 0f e5 53 79 07 1c b6 ca
                           32 54 d7 48 d6 80 3c 34 6a d9 f3 df 6d 52 c8 89
        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

Se tentarmos remover a última (única) chave, o sistema avisará que o dispositivo ficará inutilizado em termos de acesso:

sudo cryptsetup luksKillSlot /dev/sdb1 0

WARNING!
========
This is the last keyslot. Device will become unusable after purging this key.

Are you sure? (Type uppercase yes):

Observe que só havia uma chave cadastrada e, portanto, se continuássemos o processo, a partição ficaria sem nenhuma chave de acesso e, portanto, inutilizada!

Para permitir que a partição seja montada automaticamente na inicialização, devemos habilitar o dispositivo usando o arquivo cryttab, adicionando a seguinte linha:

# <target name>     <source device>         <key file>      <options>
sdb1            /dev/sdb1           none        luks

Isso habilita a criação do dispositivo no device mapper. Para montar a partição, usamos o método convencional (/etc/fstab):

/dev/mapper/sdb1 /mnt/data      ext4  defaults  0   2

Agora o sistema deve pedir a chave na inicialização.

Se, por outro lado, o disco for ser utilizado esporadicamente como, por exemplo, um pendrive, não há necessidade de adicionar nada no arquivo fstab, mas faça as alterações no crytptab. Se você estiver usando alguma interface gráfica, como o Gnome, provavelmente ao conectar o dispositivo o sistema solicitará a senha e irá montar o dispositivo em /media/<usuário>/dispositivo, usando o nome definido na formatação. Se isso não acontecer, use os comandos manualmente, ou tente adicionar a seguinte linha no fstab:

/dev/mapper/sdb1 /media/Crypto  ext4 user,noauto 0 0

That’s all folks!