Creare partizioni cifrate usando cryptsetup (dm-crypt)

Da TondoWiki.


Questa guida si prefigge l'obbiettivo di spiegare come sia possibile cifrare in modo sicuro i propri dati sul proprio disco fisso, ricorrendo ad algoritmi affidabili utilizzando software gratis e opensource. Vedremo come sia possibile fare ciò sia su Linux che su Windows e scopriremo che i dati cifrati in questo modo (siano essi su un disco o una partizione locale ma anche su un archivio removibile) siano accessibili da entrambi i sistemi operativi.

Quando fu scritta questa guida (2007) si presupponeva che il lettore sapesse compilare un modulo del kernel perchè tali moduli (come tanti altri all'epoca) non erano inclusi di default. Attualmente invece grazie all'incredibile evoluzione di tutte le distribuzioni Linux quasi sicuramente tali moduli del kernel saranno inclusi nella vostra distribuzione.

Indice

Hardware utilizzato

  • CPU: AMD Athlon XP-M 2000+ [AXMH2000FLQ3C]
  • DISCO: Seagate Barracuda PATA 320Gb / 16Mb Cache / 7200rpm [ST3320620A]

Premessa

Nella stesura di questa guida ho (ovviamente) abbiamo preso spunto da guide che abbiamo trovato in giro.

L'ultima è davvero una guida che merita una menzione particolare, vista l'esaurienza dei temi trattati e i vari approfondimenti. Se trovate tutto quello che vi serve (e anche più) nella guida di "Sanata", seguite pure quella che è davvero fatta bene. Questa che trovate di seguito vuole essere una guida passo-passo più semplice e veloce di quella di Sanata ma allo stesso tempo un po più commentata e spiegata rispetto alle prime due.

Kernel

Per prima cosa è necessario abilitare o verificare che sia già presente nel proprio kernel, il supporto alla creazione di device cifrati. Lo schema seguente ha l'unico scopo di agevolarne l'individuazione ma tenete presente che la collocazione o la dicitura potrebbe variare da una versione di kernel ad un altra.

     Device Drivers 
        --> [*] Multi-device support (RAID and LVM)
              --> [*] Device Mapper
                   --> [*] Crypt Target Support

Inoltre è necessario compilare (se non sono già compilati ed inclusi nel kernel) anche i seguenti moduli: aes, sha e dm_crypt. Anche questi moduli potrebbero chiamarsi in modo diverso come aes_generic ecc, ma si tratta ovviamente degli stessi moduli semplicemente rinominati.

Se necessario riavviate la macchina (per utilizzare il nuovo kernel), quindi caricate i moduli necessari manualmente digitando in sequenza i seguenti comandi:

# modprobe dm_crypt
# modprobe sha256
# modprobe aes

Se tutto procede senza errori vi consigliamo di inserirli uno sotto l'altro in /etc/modules per evitare di doverli ricaricare manualmente ogni volta che riavviate la macchina come nel modo seguente (estratto del file):

# /etc/modules file
dm_crypt
sha256
aes

Preparazione

Ragionamento preliminare

Se il disco è NUOVO (o la partizione non è mai stata usata), presumibilmente (quasi sicuramente) conterrà tutti i bit uguali a ZERO. L'algoritmo di cifratura del disco (o partizione) è noto anche a chi non conosce la chiave. E i dati cifrati li conosciamo (sono quelli che leggiamo non conoscendo la chiave). Quindi siamo di fronte ad una situazione di questo tipo:

 ZERO_BITS + ALGORITMO(CHIAVE) = RISULTATO

La chiave è ottenibile in maniera più "semplice" del dovuto. Ecco perchè sovrascriviamo l'intera partizione (o disco) con dati pseudo-casuali (sufficenti al nostro scopo) usando /dev/urandom

Prepariamo il disco

Cominciamo con il riempire il nostro disco di dati pseudo-casuali (o totalmente casuali) in modo da non fornire involontariamente informazioni vulnerabili, nel seguente modo:

# dd if=/dev/urandom of=/dev/hdb<cite_reference_link>

Di seguito è stato lanciato lo stesso comando preceduto dal comando time solo per calcolare il tempo impiegato che ci permetterà di fare dei ragionamenti in seguito.

# time dd if=/dev/urandom of=/dev/hdb
dd: scrittura di `/dev/hdb': No space left on device
625142449+0 records in
625142448+0 records out
320072933376 bytes (320 GB) copied, 105298 seconds, 3,0 MB/s

real    1754m57.798s   [29 ORE cioè 1 giorno e 5 ore]
user    5m24.008s
sys     1418m11.446s

Come potete notare tra parentesi sono stati necessarie 29 ORE (ricordando l'hardware utilizzato).

Da notare anche l'utilizzo delle risorse qua di seguito:

Utilizzo cpu
I/O stat
VM stat
Load average
Available entropy
Interrupts

Se siete paranoici (o volete il massimo della sicurezza) allora usate il device /dev/random (che utilizza dati casuali e non pseudo-casuali) ma sappiate che potreste impiegare diversi giorni o quasi una settimana.

In ogni caso la situazione sarà la seguente:

 (PSEUDO)RANDOM_BITS + ALGORITMO(CHIAVE) = RISULTATO

Che è molto meglio della precedente che prevedeva i bit a ZERO.

Ora che il disco contiene dati pseudo-casuali va partizionato come meglio desideriamo, sia per quanto riguarda la dimensione delle partizioni, sia il loro numero. Io ho scelto di creare un' unica partizione. Per creare le partizioni siete liberi di utilizzare il programma che preferite, io ho scelto cfdisk, che mi sembra la miglior soluzione da usare anche dove è presente un eventuale desktop manager. Quindi digitate

# cfdisk /dev/hdb<cite_reference_link>

e in sequenza effettuate la scelta evidenziata in grassetto

Unknown partition table type
Do you wish to start with a zero table [y/N] ? y

Anche la tabella delle partizioni è stata piallata dal comando dd precedente quindi cfdisk ne creerà una vuota.

Quindi create una nuova paritizione (l'unica se avete seguito pari pari questa guida)

[  Help  ]  [  New   ]  [ Print  ]  [  Quit  ]  [ Units  ]  [ Write  ]

Create new partition from free space

...primaria...

[Primary]  [Logical]  [Cancel ]

Create a new primary partition

...della dimensione che volete (massima in questo caso)...

Size (in ME): 320070,32

...e scrivete i cambiamenti su disco (che equivale a 'salvare' le modifiche)...

[Bootable]  [ Delete ]  [  Help  ]  [Maximize]  [ Print  ]  [  Quit  ]  [  Type  ]  [ Units  ]  [ Write  ]

Write partition table to disk (this might destroy data)

...confermate...

Are you sure you want write the partition table to disk? (yes or no): yes

Warning!!  This may destroy data on your disk!

E uscite ignorando l'avvertimento perchè la tabella delle partizioni è stata scritta quando avete fatto [Write]

[Bootable]  [ Delete ]  [  Help  ]  [Maximize]  [ Print  ]  [  Quit  ]  [  Type  ]  [ Units  ]  [ Write  ]

Quit program without writing partition table

Ora avrete una partizione che si chiamerà /dev/hdb1<cite_reference_link>.

Installazione

Installiamo cryptsetup

# apt-get install cryptsetup

Formattiamo /dev/hdb<cite_reference_link> con luksFormat utilizzando cryptsetup e una cifratura più robusta di quella di default come di seguito:

# cryptsetup -h sha256 -c aes-cbc-essiv:sha256 -s 256 luksFormat /dev/hdb1<cite_reference_link>

Attenzione alla F maiuscola perchè "luksformat" come riportato in altre guide non è altro che un wrapper di cryptsetup per semplificare l'operazione precedente, ma utilizza metodi di cifratura più deboli. Dato il comando otterremo

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

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase:
Verify passphrase:
Command successful.

Dobbiamo scegliere una passphrase SERIA. Come consiglio diciamo che va bene una frase relativamente lunga contenente almeno un carattere numerico e di punteggiatura e sia lettere minuscole che maiuscole.

ATTENZIONE: Pur rispettando le regole appena menzionate, fate in modo che tale password sia mnemonica perchè andrà usata ogni volta che dovete accedere ai dati quindi scordarla significherà perdere PER SEMPRE tutti i vostri dati.

Esempi: w1k1.T0nd0k0b3.Com o n.44GattiInFilaX6=7r2 o P4ssWordXacc&dErEaiM1E1d4t1.

Quindi date il comando

# cryptsetup luksOpen /dev/hdb1<cite_reference_link> seagate<cite_reference_link>
Enter LUKS passphrase:
key slot 0 unlocked.
Command successful.
  • /dev/hdb1<cite_reference_link> - la partizione "reale"
  • seagate<cite_reference_link> - il nome del device mappato che troverete poi in /dev/mapper

Il risultato è il seguente:

# cryptsetup status seagate<cite_reference_link>
/dev/mapper/seagate is active:
  cipher:  aes-cbc-essiv:sha256
  keysize: 256 bits
  device:  /dev/hdb1
  offset:  2056 sectors
  size:    625135226 sectors
  mode:    read/write
# ls -la /dev/mapper/
totale 0
drwxr-xr-x  2 root root      80 2007-10-16 15:26 .
drwxr-xr-x 14 root root   13380 2007-10-16 15:26 ..
crw-rw----  1 root root  10, 63 2007-10-02 19:17 control
brw-rw----  1 root disk 253,  0 2007-10-16 15:26 seagate<cite_reference_link>

Il device è a blocchi quindi da trattare come se fosse il nostro device reale. In pratica noi effettuiamo le operazioni su /dev/mapper/seagate<cite_reference_link> che farà tutte le sue operazioni e mettera i dati fisicamente su /dev/hdb1<cite_reference_link> (ovviamente). Quindi formattiamo la nostra partizione (come faremmo solitamente, semplicemente dobbiamo fare riferimento a /dev/mapper/seagate<cite_reference_link> anzichè /dev/hdb1<cite_reference_link>)

mkfs.reiserfs<cite_reference_link> /dev/mapper/seagate<cite_reference_link>

che generarà il seguente output

A pair of credits:
Elena Gryaznova performed testing and benchmarking.

Yury Umanets  (aka Umka)  developed  libreiser4,  userspace  plugins,  and  all
userspace tools (reiser4progs) except of fsck.
 
Guessing about desired format.. Kernel 2.6.16.37 is running.
Format 3.6 with standard journal
Count of blocks on the device: 78142160
Number of blocks consumed by mkreiserfs formatting process: 10596
Blocksize: 4096
Hash function used to sort names: "r5"
Journal Size 8193 blocks (first block 18)
Journal Max transaction length 1024
inode generation number: 0
UUID: 452828c0-7853-40cf-9b7e-1f71a7219e58
ATTENTION: YOU SHOULD REBOOT AFTER FDISK!
        ALL DATA WILL BE LOST ON '/dev/mapper/seagate'!
Continue (y/n): y

confermiamo ovviamente con y e completiamo la formattazione.

Initializing journal - 0%....20%....40%....60%....80%....100%
Syncing..ok

Tell your friends to use a kernel based on 2.4.18 or later, and especially not a
kernel based on 2.4.9, when you use reiserFS. Have fun.

ReiserFS is successfully created on /dev/mapper/seagate.

Benchmark

Per i nostri scopi spiegheremo solo marginalmente questi risultati e tenete presente l'hardware utilizzato.

Senza cifratura

# bonnie++ -uroot
Using uid:0, gid:0.
Writing with putc()...done
Writing intelligently...done
Rewriting...done
Reading with getc()...done
Reading intelligently...done
start 'em...done...done...done...
Create files in sequential order...done.
Stat files in sequential order...done.
Delete files in sequential order...done.
Create files in random order...done.
Stat files in random order...done.
Delete files in random order...done.
Version  1.03      ------Sequential Output------ --Sequential Input- --Random-
                   -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
              Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
                3G 32545  96 84612  52 29780  15 29975  93 70626  23 247.4   0
                   ------Sequential Create------ --------Random Create--------
                   -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
             files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                16 20997  99 +++++ +++ 17596 100 20256  99 +++++ +++ 15331  99
non-cifrato,3G,32545,96,84612,52,29780,15,29975,93,70626,23,247.4,0,16,20997,99,+++++,+++,17596,100,20256,99,+++++,+++,15331,99

In breve abbiamo ottenuto una velocità massima di 82,6 M/sec in lettura e 68,9 M/sec in scrittura.

Con cifratura

# bonnie++ -uroot
Using uid:0, gid:0.
Writing with putc()...done
Writing intelligently...done
Rewriting...done
Reading with getc()...done
Reading intelligently...done
start 'em...done...done...done...
Create files in sequential order...done.
Stat files in sequential order...done.
Delete files in sequential order...done.
Create files in random order...done.
Stat files in random order...done.
Delete files in random order...done.
Version  1.03      ------Sequential Output------ --Sequential Input- --Random-
                   -Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--
              Size K/sec %CP K/sec %CP K/sec %CP K/sec %CP K/sec %CP  /sec %CP
                3G 13227  39 22233  25 10346  24 11599  40 17312   5 232.4   0
                   ------Sequential Create------ --------Random Create--------
                   -Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--
             files  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP  /sec %CP
                16 21398  99 +++++ +++ 18086  99 20402 100 +++++ +++ 14571  93
cifrato,3G,13227,39,22233,25,10346,24,11599,40,17312,5,232.4,0,16,21398,99,+++++,+++,18086,99,20402,100,+++++,+++,14571,93

In questo caso (con i dati cifrati) i benchmark sono andati molto peggio perchè abbiamo ottenuto solo 21,7 M/sec in lettura e 19,9 M/sec in scrittura che confrontati con i dati precedenti si traducono in un abbondante 70% in meno. Cioè nemmeno 1/3 delle prestazioni senza cifratura.

Di seguito ne trovate un altro (non realizzato da noi).

Mount

Per accedere ai nostri dati, dobbiamo montare la partizione come se fosse una partizione normale (facendo attenzione al fatto che dobbiamo montare però quella mappata) e quindi procedimo creando dapprima una cartella in /mnt

mkdir /mnt/seagate

quindi montando il device/partizione (mappata)

mount /dev/mapper/seagate /mnt/seagate

Proprio come se montaste un device "normale".

Per smontare e chiudere il tutto invece basta fare in sequenza

umount /mnt/seagate
cryptsetup luksClose /dev/mapper/seagate

Windows

Non ci crederete, ma tutti i dati che risiedono in quella partizione, accuratamente cifrati, sono accessibili anche da un sistema windows.

Utilissimo, se la partizione cifrata risiede su un disco esterno, o se si tratta di una partizione di "solo dati" di un sistema multi-boot (per esempio Windows, Linux).

Per raggiungere il nostro scopo ci serviremo del famigerato FreeOFTE disponibile addirittura in versione PDA (portable) che non necessita di installazione (potreste cifrare la SD del vostro PDA, non è male!).

Una guida in italiano a FreeOFTE la trovate qua ed essendo stra-esauriente, di seguito mi limiterò solo a indicare la semplicissima configurazione da impostare per accedere al device che abbiamo appena cifrato con Linux.

Per accedere dobbiamo fare File > Linux Volume > Mount Partition (se la partizione è stata creata cifrata con Linux). Quindi inserire la passphrase, selezionare eventuali opzioni utili ai nostri scopi e confermare.

Una volta settato tutto correttamente, vi troverete un nuova unità disco (per esempio D: o F: o Z:) accessibile "normalmente".

NOTA: E' possibile accedere solo a File System supportati nativamente (o circa) da Windows (quindi NTFS o FAT). Abbiamo provato a formattare ReiserFS una partizione cifrata da linux, ma poi con il lettore di ReiserFS per windows, non vediamo nemmeno la partizione, e quindi non possiamo nemmeno pensare di affrontare il problema.

NOTA 2: In Windows 2000 SP4 EN è possibile usare e montare le partizioni utilizzando anche un account PowerUser (cioè senza essere per forza Administrator). Tutto sembrerà funzionare correttamente ma quando andrete per smontare la partizione.... puffffff! Si riavvierà il PC. Un bel reset! Almeno questo è quello che ci è successo in tutte le nostre prove. Quindi fate attenzione!

Approfondimenti

Annotazioni

<cite_references_prefix><cite_references_link_many> <cite_references_link_many> <cite_references_link_one><cite_references_suffix>

03-10-2007

Strumenti personali