LUKS-on-Raspberry-Pi

Guida per eseguire una crittografia completa della partizione di root su scheda SD di un Raspberry Pi con Raspberry Pi OS

View on GitHub

LUKS su Raspberry Pi + sblocco e avvio automatico

Ultimo aggiornamento: Marzo 2024.

Questa guida spiega come crittografare la partizione root di una scheda SD con Raspberry Pi OS utilizzando LUKS. Il processo richiede un Raspberry Pi con Raspberry Pi OS sulla scheda SD e una memoria USB con almeno la stessa capacità della scheda SD. È importante avere un backup della scheda SD, nel caso in cui qualcosa vada storto, poiché verrà sovrascritta, così come della memoria USB.

La crittografia del disco completo è abbastanza semplice da eseguire con le moderne distribuzioni Linux. Raspberry Pi è un’eccezione perché la partizione di avvio non include la maggior parte dei programmi e dei moduli del kernel necessari. D’altra parte, è importante utilizzare la crittografia del disco con Raspberry Pi perché la scheda SD può essere estratta dall’unità e il suo contenuto letto abbastanza facilmente.

Requisiti

Kernel Linux 5.0 o successivo. Puoi verificarlo con questo comando:

uname -s -r

Installa i programmi necessari:

sudo apt install busybox cryptsetup initramfs-tools resize2fs cryptsetup-initramfs

I microprocessori dei computer Raspberry Pi non includono l’accelerazione AES. Ciò significa che è necessaria un’implementazione software di AES, che è lenta con un hardware modesto. Fortunatamente esiste una recente alternativa, Adiantum, che funziona velocemente nel software. Il kernel Linux 5.0 o successivo include i moduli del kernel crittografico necessari per Adiantum. Puoi verificare che ogni modulo sia presente e caricato con questo comando:

cryptsetup benchmark -c xchacha20,aes-adiantum-plain64

L’output, se tutto è a posto, sarà simile a questo:

# Tests are approximate using memory only (no storage IO).
#            Algorithm |       Key |      Encryption |      Decryption
xchacha20,aes-adiantum        256b       111.2 MiB/s       114.6 MiB/s

Preparazione avvio di Linux

Bisogna specificare alcuni programmi che devono essere inclusi nell’ ‘initramfs’. Lo facciamo con un nuovo file:

/etc/initramfs-tools/hooks/luks_hooks

e deve contenere questo contenuto:

#!/bin/sh -e
PREREQS=""
case $1 in
        prereqs) echo "${PREREQS}"; exit 0;;
esac

. /usr/share/initramfs-tools/hook-functions

copy_exec /sbin/resize2fs /sbin
copy_exec /sbin/fdisk /sbin
copy_exec /sbin/cryptsetup /sbin

I programmi sono ‘resize2fs’, ‘fdisk’ e ‘cryptsetup’. Il file deve essere reso eseguibile:

sudo chmod +x /etc/initramfs-tools/hooks/luks_hooks

L’initramfs per Raspberry Pi OS non include di default i moduli del kernel per LUKS e la crittografia. Bisogna configurare i moduli del kernel da aggiungere. Modifica:

/etc/initramfs-tools/modules

e le seguenti righe con i nomi dei moduli del kernel aggiunti:

algif_skcipher
xchacha20
adiantum
aes_arm
sha256
nhpoly1305
dm-crypt

Rigenera ‘initramfs’:

sudo update-initramfs -u

Verifica la presenza dei programmi nell’initramfs con il seguente comando:

lsinitramfs /boot/initramfs.gz | grep -P "sbin/(cryptsetup|resize2fs|fdisk)"

Verifica che i moduli del kernel siano presenti nell’initramfs con il seguente comando:

lsinitramfs /boot/initramfs.gz | grep -P "(algif_skcipher|chacha|adiantum|aes-arm|sha256|nhpoly1305|dm-crypt)"

Preparazione dell’avvio

Prima di riavviare il Raspberry Pi, è necessario apportare alcune modifiche ai file. Queste modifiche servono per istruire il processo di avvio affinché utilizzi un filesystem root crittografato. Dopo aver effettuato le modifiche precedenti, il Raspberry Pi si avvierà correttamente. Tuttavia, dopo aver apportato le modifiche ai seguenti file, il Raspberry Pi non avvierà l’interfaccia desktop finché non sarà completato l’intero processo di crittografia della partizione radice e la configurazione di LUKS. Nel caso in cui si verifichino problemi dopo aver apportato modifiche ai successivi quattro file e prima della crittografia della partizione radice, è possibile ripristinare le modifiche nei quattro file e il Raspberry Pi si avvierà normalmente. È consigliabile fare una copia di questi file prima di apportare modifiche.

File: /boot/cmdline.txt

Contiene una riga con dei parametri. Uno di essi è ‘root’, che specifica la posizione della partizione root. Per il Raspberry Pi di solito è ‘/dev/mmcblk0p2’, ma può anche essere un altro dispositivo (o lo stesso) specificato come “PARTUUID=xxxxx”. Il valore di ‘root’ deve essere cambiato in ‘/dev/mapper/sdcard’. Ad esempio, se ‘root’ è:

root=/dev/mmcblk0p2

deve essere cambiato in:

root=/dev/mapper/sdcard

inoltre, alla fine della riga, separato da uno spazio, deve essere aggiunto:

cryptdevice=/dev/mmcblk0p2:sdcard

File: /etc/fstab

Il dispositivo per la partizione root (‘/’) deve essere cambiato con il mapper. Ad esempio, se il dispositivo per la root è:

/dev/mmcblk0p2

deve essere cambiato con:

/dev/mapper/sdcard

File: etc/crypttab

Alla fine del file, una nuova riga deve essere aggiunta con il seguente contenuto:

sdcard	/dev/mmcblk0p2	none	luks

Tutto è pronto per il riavvio. Dopo il riavvio, Raspberry Pi OS non riuscirà a avviarsi perché abbiamo configurato una partizione root che non esiste ancora. Dopo diversi messaggi uguali che indicano il fallimento, verrà visualizzata la shell ‘initramfs’.

Crittografia della partizione root

Nella shell ‘initramfs’, possiamo verificare l’utilizzo di ‘cryptsetup’ con i moduli kernel dei cifrari:

cryptsetup benchmark -c xchacha20,aes-adiantum-plain64

Se il test viene completato con successo, tutto è a posto. Ora dobbiamo copiare la partizione root della scheda SD nella memoria USB. L’idea è quella di avere una copia della partizione root della scheda SD nella memoria USB, creare un volume crittografato nella partizione root (il contenuto verrà perso) e copiare la partizione root dalla memoria USB nella partizione crittografata della scheda SD. Tieni presente che il contenuto precedente della memoria USB verrà perso. Prima di farlo, controlliamo la partizione root e riduciamo le dimensioni del suo filesystem al minimo possibile, in modo che l’operazione di copia richieda meno tempo. Il comando per controllare e correggere eventuali errori è:

e2fsck -f /dev/mmcblk0p2

Una volta terminato, dobbiamo ridimensionare il filesystem. È estremamente importante annotare attentamente le dimensioni del filesystem dopo il ridimensionamento, in particolare il numero di blocchi da 4k:

resize2fs -fM -p /dev/mmcblk0p2

Un esempio dell’output del programma è:

Resizing the filesystem on /dev/mmcblk0p2 to 524288 (4k) blocks.

Il numero da annotare è ‘524288’ nell’esempio. Una volta completato il ridimensionamento, otterremo un valore del checksum dell’intera partizione. Faremo lo stesso dopo ogni operazione di copia tra la scheda SD e la memoria USB. Se il checksum è lo stesso, la copia sarà identica. Creiamo il checksum per la partizione root da copiare. Ricordati di sostituire ‘XXXXX’ con il numero di blocchi da 4 kB ottenuto dopo il ridimensionamento del filesystem. È utile aggiungere “time “ prima di “dd” per ottenere quanto tempo impiega l’operazione. Quando vengono calcolati i restanti checksum, permette di sapere, più o meno, quanto tempo ci vorrà.

time dd bs=4k count=XXXXX if=/dev/mmcblk0p2 | sha1sum

Annota il valore SHA1. Collega ora la memoria USB al Raspberry Pi. Verranno stampate alcune informazioni sulla memoria USB. Se non è collegata un’altra memoria USB, il dispositivo per la memoria sarà probabilmente /dev/sda. Può essere verificato con:

fdisk -l /dev/sda

Stiamo per utilizzare l’intera memoria USB, /dev/sda. Questa operazione copierà il filesystem root della scheda SD nel dispositivo di memoria USB, cancellando tutto il suo contenuto (ricorda di sostituire ‘XXXXX’ con il numero di blocchi da 4k ottenuto dopo il ridimensionamento del filesystem):

time dd bs=4k count=XXXXX if=/dev/mmcblk0p2 of=/dev/sda

Durante la copia da o verso schede SD e memorie USB potrebbe comparire un messaggio che indica che il task worker è stato bloccato per diversi secondi. Può essere ignorato se i checksum sono corretti.

Ora abbiamo il filesystem root originale e la copia. Abbiamo anche il checksum dell’originale. Dobbiamo calcolare il checksum della copia e confrontarli. Possiamo considerarli una copia esatta se i checksum coincidono. Il comando per calcolare il checksum della copia è (ricordati di sostituire ‘XXXXX’ con il numero di blocchi da 4k che hai ottenuto dopo il ridimensionamento del filesystem):

time dd bs=4k count=XXXXX if=/dev/sda | sha1sum

Se i checksum sono corretti, è il momento di criptare il filesystem root della scheda SD, per creare il volume LUKS utilizzando ‘cryptsetup’. Ci sono molti parametri e possibili valori per la crittografia. Questo è il comando che ho scelto:

cryptsetup --type luks2 --cipher xchacha20,aes-adiantum-plain64 --hash sha256 --iter-time 5000 –-key-size 256 --pbkdf argon2i luksFormat /dev/mmcblk0p2

Ulteriori informazioni sui parametri possono essere trovate qui: https://man7.org/linux/man-pages/man8/cryptsetup.8.html

Il comando richiederà una passphrase due volte (per conferma). È importante che la passphrase sia lunga e utilizzi diversi set di caratteri (lettere, numeri, simboli, maiuscole, minuscole, ecc.). Dopo aver creato il volume LUKS, dobbiamo aprirlo e copiare il contenuto del filesystem root al suo interno. Il comando per aprire il volume LUKS è:

cryptsetup luksOpen /dev/mmcblk0p2 sdcard

Chiederà la passphrase scelta nella fase precedente. Una volta aperto, copiamo il filesystem root dalla memoria USB nel volume crittografato (ricordati di sostituire ‘XXXXX’ con il numero di blocchi da 4k ottenuti dopo il ridimensionamento del filesystem):

time dd bs=4k count=XXXXX if=/dev/sda of=/dev/mapper/sdcard

Dopo aver copiato, calcola nuovamente il checksum della copia per convalidarlo. Se i checksum coincidono, la copia è corretta (ricordati di sostituire ‘XXXXX’ con il numero di blocchi da 4k ottenuti dopo il ridimensionamento del filesystem):

time dd bs=4k count=XXXXX if=/dev/mapper/sdcard | sha1sum

Oltre al controllo del checksum, verifica anche il filesystem del volume LUKS:

e2fsck -f /dev/mapper/sdcard

Il fylesystem è ridotto. Ora espandilo alla dimensione della scheda SD:

resize2fs -f /dev/mapper/sdcard

Il processo è quasi terminato ora. La memoria USB può essere rimossa perché non è più necessaria. Esci dall’initramfs:

exit

Durante il processo di avvio, si entrerà nuovamente nella shell di initramfs. In questo momento bisogna aprire il volume LUKS appena creato per rendere disponibile il filesystem root:

cryptsetup luksOpen /dev/mmcblk0p2 sdcard

Dopo aver aperto il volume LUKS, dobbiamo uscire nuovamente e il sistema operativo Raspberry Pi OS si avvierà normalmente:

exit

Avvio

Non vogliamo entrare nella shell di initramfs ogni volta che accendiamo il nostro Raspberry Pi. Possiamo fare in modo che Raspberry Pi OS chieda la password. Per farlo, è necessario rigenerare l’initramfs e riavviare:

sudo update-initramfs -u

Dopo il riavvio, dovrebbe apparire un messaggio di prompt, simile a “Please unlock disk…”. Forse il prompt che chiede una password si perderà tra alcuni messaggi di avvio, ma puoi comunque inserire la tua passphrase e dovrebbe funzionare.

Sblocco e avvio automatico della partizione root crittografata con LUKS tramite file chiave memorizzato nella partizione Boot ⚠️(NON SICURO)

In questa sezione della guida, viene spiegato come configurare il sistema per lo sblocco automatico della partizione root crittografata utilizzando LUKS tramite un file chiave. È importante tenere presente che questa procedura comporta il rischio di sicurezza associato al salvataggio del file chiave nella cartella di boot del sistema. Si consiglia di considerare attentamente i rischi e di adottare misure aggiuntive per proteggere la sicurezza del sistema.

Crea la cartella contenente la chiave:

sudo mkdir /boot/key && cd /boot/key 

Generazione della chiave Crea la chiave e rendila in sola lettura:

sudo dd if=/dev/urandom of=keyfile bs=4096 count=4

rendila in sola lettura

sudo chmod 0400 keyfile

I dispositivi abilitati LUKS/dm_crypt possono contenere fino a 10 diverse keyfile/password. Quindi, oltre ad avere la password già impostata, aggiungi questo file chiave come metodo di autorizzazione aggiuntivo, ti verrà chiesto di inserire la passpharse.

sudo cryptsetup luksAddKey /dev/mmcblk0p2 keyfile

Puoi verificare l’aggiunta della chiave con il comando:

sudo cryptsetup luksDump /dev/mmcblk0p2

Come risultato dovresti vedere i 2 keyslot “0”, “1”. Puoi testare la chiave appena creata usandi il comando:

sudo cryptsetup open -v -d keyfile --test-passphrase /dev/mmcblk0p2

Il risultato dovrebbe essere simile a questo:

No usable token is available.
Key slot 2 unlocked.
Command successful.

Modifichiamo il mapper precedentemente creato quindi:

sudo nano /etc/crypttab

modifichiamo la prima riga da:

sdcard	/dev/mmcblk0p2	none	luks

così:

sdcard  /dev/mmcblk0p2  /boot/key/keyfile luks

Rigenera l’initramfs

sudo update-initramfs -u

Ora riavvia e il sistema dovrebbe avviarsi senza richiederti la pass se tutto è andato bene.