Správa linuxového serveru: Praxe šifrování s dm-crypt/LUKS

Minule jsem vás uvedl to teorie diskového šifrování, dnes se na toto téma podívám z praktického hlediska.

dm-crypt/LUKS

dm-crypt je specifický subsystém linuxového jádra, který využívá infrastrukturu device mapperu a linuxového CryptoAPI, a vytváří transparentní vrstvu pro online šifrování a dešifrování blokových zařízení. Dodávám, že dm-crypt je možné využívat samostatně, bez LUKS nadstavby, a to prostřednictvím stejného nástroje - cryptsetup. V tomto článku se však plně zaměřím právě na LUKS.

LUKS je nadstavba dm-cryptu, která, vezmu-li to zjednodušeně, přidává dvouúrovňové šifrování, správu klíčů a funkci pro posílení uživatelského hesla PBKDF2. Specifikace LUKS je multiplatformní a je možné s jeho pomocí vytvářet šifrované kontejnery, které lze otevřít i v jiných operačních systémech (třeba s pomocí aplikace pro MS Windows s názvem FreeOTFE).

Dvouúrovňové šifrování v případě LUKS znamená, že samotný svazek je šifrován tzv. hlavním klíčem (master key), který je následně zašifrován uživatelským heslem a uložen do jednoho z úložišť (slotů). Z toho vyplývá jak na jedné straně velká výhoda v podobě nezávislosti šifrování na uživatelském hesle, a tudíž možnost bezproblémové revokace (či změny) existujícího přístupového hesla, tak na straně druhé nevýhoda spočívající v potenciální ztrátě dat, je-li nezálohovaná hlavička s úložištěm klíčů přepsána.

Příprava budoucího šifrovaného svazku

Ještě než začnete s vytvářením šifrovaného svazku, je dobré příslušné blokové zařízení zaplnit co nejkvalitnějšími náhodnými daty. Je to z toho důvodu, aby případný kryptoanalytik viděl na daném blokovém zařízení jednu celistvou oblast a neměl možnost uhodnout, které bloky jsou opravdu šifrované a které ne (zašifrovaná data by měla být neodlišitelná od náhodných dat), což by mu mělo o něco více zkomplikovat jeho práci. Tento krok sice není nutný, ale bývá vhodné ho provést.

Zcela ideální k zaplnění svazku náhodnými daty by bylo použít generátor náhodných čísel /dev/random. Tento generátor vytváří kvalitní náhodná čísla, ale je neuvěřitelně pomalý. Z tohoto důvodu je podstatně vhodnější použít zařízení /dev/urandom, které sice generuje méně "kvalitní" náhodná čísla, ale generuje je neporovnatelně rychleji.

K samotnému zaplnění zvoleného svazku náhodnými daty použijte nástroj dd:

dd if=/dev/urandom of=/dev/svazek

Tato procedura bude obvykle trvat velmi dlouho, řádově hodiny až dny. Existují sice metody, jak tuto fázi uspíšit, ale jejich důsledkem je zaplnění svazku méně kvalitními náhodnými daty, které patrně může zkušený kryptoanalytik rozeznat od šifrovaných dat, což by činilo celý tento krok zbytečným.

Já osobně používám následující urychlovací metodu. Dodávám však, že nejsem kryptolog ani kryptoanalytik, tudíž nejsem schopen odhadnout, zda-li je to správný postup nebo naopak z nějakého důvodu velmi špatný.

Můj postup je následující - vytvořím šifrovaný svazek (viz další bod), následně použiji nástroj badblocks k zaplnění svazku nekvalitními náhodnými daty, která by ovšem po zašifrování měla být nerozeznatelná od kvalitních (nebo od skutečných zašifrovaných dat):

badblocks -v -s -w -t random /dev/mapper/desifrovany_svazek

Následně svazek odpojím pomocí luksClose (viz níže) a přepíšu ještě začátek oddílu s LUKS hlavičkou pomocí /dev/urandom:

dd if=/dev/urandom of=/dev/zarizeni bs=1M count=32

Vytvoření šifrovaného svazku

Ke všem operacím se šifrovanými svazky budeme využívat nástroje cryptsetup. Ten byste měli mít k dispozici v repositářích vaší distribuce (v případě Debianu se tento nástroj nachází ve stejnojmeném balíčku). Vytvoření šifrovaného svazku provedete s použitím šifrovacího algoritmu AES a módu XTS takto:

cryptsetup -c aes-xts-benbi -s 512 -y luksFormat /dev/svazek

Povšimněte si parametru -c, kde je na prvním místě šifrovací algoritmus, na druhém, oddělen pomlčkou, šifrovací mód a na třetím způsob generování inicializačního vektoru (v případě XTS máte na výběr mezi 32-bitovým "plain" a 64-bitovým "benbi"). Parametr -s udává délku klíče, -y vám umožní zadat heslo pro kontrolu dvakrát a luksFormat označuje LUKS operaci, tedy inicializaci daného svazku.

V případě, že máte k dispozici starší systém, který nezná XTS, použijte mód cbc-essiv:

cryptsetup -c aes-cbc-essiv:sha256 -s 256 -y luksFormat /dev/svazek

Otevření zašifrovaného svazku

Po tom, co zašifrujete nějaký svazek, budete jistě chtít svazek otevřít a přistupovat k němu jako k nešifrovanému, abyste na něm mohli vytvořit souborový systém, ten připojit a nahrát na něj nějaká data. Za tímto účelem použijete LUKS operaci open:

cryptsetup luksOpen /dev/svazek odsifrovano

Prvním parametrem je samotné zařízení, druhým pak název, pod kterým bude k dispozici dešifrované zařízení umístěné v /dev/mapper. Po této operaci byste tedy měli mít (za předpokladu zadání správného hesla) k dispozici dešifrované zařízení /dev/mapper/odsifrovano, na kterém pak pomocí mkfs vytvoříte souborový systém a zařízení připojíte.

Zrušení mapování

Jakmile skončíte práci s namapovaným dešifrovaným svazkem, bývá dobré příslušné mapování zrušit. K tomu slouží LUKS operace close:

cryptsetup luksClose odsifrovano

Předpokladem je, že před tím odpojíte příslušný souborový systém. Povšimněte si také, že luksCloseoperuje s názvy dešifrovaných svazků, nikoliv s původními zařízeními.

Správa klíčů

Jelikož LUKS oplývá vlastností dvouúrovňového šifrování, máte možnost nastavit více klíčů, přičemž každý pak bude schopen daný svazek dešifrovat. Ke správě klíčů slouží operace luksAddKey (přidá nový klíč) aluksRemoveKey (odstraní stávající klíč).

Po vytvoření šifrovaného svazku pomocí luksFormat již svazek bude mít definováno jeho heslo. Pokud budete chtít později přidat další klíč, zadáte:

cryptsetup luksAddKey /dev/svazek

LUKS vás vyzve k zadání jakéhokoliv jiného hesla (aby mohl získat hlavní klíč), a pak vás nechá zadat heslo nové. Tím pak hlavní klíč zašifruje a uloží do některého z volných "slotů" v úložišti pro klíče.

Všimněte si, že se zde používá název původního zařízení, není tedy nutné před přidáním či odebráním klíče svazek dešifrovat pomocí luksOpen.

Analogicky, budete-li chtít některý z existujících klíčů odebrat, použijete:

cryptsetup luksRemoveKey /dev/svazek

Operace pro odebrání klíče je naštěstí dostatečně inteligentní, aby uživateli zabránila odebrat poslední klíč nebo odebrat klíč bez znalosti nějakého dalšího klíče.

Kromě hesel můžete samozřejmě používat i klíčové soubory (keyfile). V případě operací luksAddKey aluksRemoveKey postačí uvést klíčový soubor za názvem operace, takto:

cryptsetup luksAddKey /cesta/ke/keyfile

A analogicky pro odebrání klíče:

cryptsetup luksRemoveKey /cesta/ke/keyfile

Jelikož klíčový soubor postačí sám o sobě k dešifrování daného svazku, je třeba věnovat zvýšenou pozornost jeho bezpečnému uložení. V ideálním případě by se měl nacházet na jiném šifrovaném svazku.

Tím bych tento díl ukončil. Příště proberu zálohu LUKS hlavičky, začlenění šifrovaných svazků do systému a šifrování celého systému.