Creating Encrypted Filesystem using Device Mapper (dmcrypt, cryptsetup) Includes LUKS Filesystem encryptions, which makes it a LOT easier, and now standard for Linux systems. ------------------------------------------------------------------------------- Basic Info Main home page dm-crypt for 2.6 kernels http://www.saout.de/misc/dm-crypt/ It works by creating a new block device in the "/dev/mapper" sub-directory which is software linked to the raw encrypted device. The raw control of this device mapping is via the "dmsetup" program (device-mapper package). Redhat FC2 provides all the above, including the initial device files. A better method "cryptsetup" was later develops first as a shell script and later as a binary that also provides a pass-phrase to encryption key algorithm. The kernel requires either loadable or builtin modules for "dm-mod" and "dm-crypt". The former will load the latter using "modprobe dm-mod". pass-phrase A simple user typed string which is used to either create or decode a longer encryption key. encryption key A long key for the encrypting of the data, usally generated from the pass-phrase using a well known algorithm, such as "ripemd160" (see below). Generally the pass-phrase to key algorithm hashing function is done repeatally (thousands of times) so that even on a fast computer it could take a second or so to generate the key from the pass-phrase. This makes it harder to 'crack' even simple pass-phases using brute force dictionary attacks. A technique known as 'hardening'. Alturnativally, I have seen it encrypted by the pass-phase and stored in a block (offset protected) with-in the disk partition itself. This was expanded further to become LUKS, see below. See "key_derivation.txt" ------------------------------------------------------------------------------- Raw "dmsetup" encryption setup The "dmsetup" command is given a table of lines to create the device mapping. echo "{start_sector} {sector_count} {target_type} {arguments}" | dmsetup create {name} Where {name} name of the new /dev/mapper device to create and mount {start_sector} start of 512 byte sectors (usally 0) {sector_count} size of the device ... what sort of mapping is needed. This is expanded for encryption to... echo "{start_sector} {sector_count} crypt {format} {key} {IV offset} {real_device} {sector_offset}" | dmsetup create {name} Where {format} symmetric encryption cipher and an optional IV generation Typically: aes-ecb Equivelent to the old crypto-loop FS encryption aes-plain A better more secure for of AES encription twofish-ecb {key} 8bit encryption key in Hexadecimal for mapping {IV_offset} Offset to sector count before creating 'IV' (usally 0) {real_device} Block device to contain the encrypted data {sector_offset} Offset where encrypted data begins (usally 0) ------ Raw dmsetup example... File System Partition, encrypted USB drive rm -f /dev/mapper/crypted_fs echo 0 `blockdev --getsize /dev/sda1` crypt aes-plain \ 0123456789abcdef0123456789abcdef 0 /dev/sda1 0 |\ dmsetup create crypted_fs mkfs -t ext3 /dev/mapper/crypted_fs mount /dev/mapper/crypted_fs /mnt/crypted_fs ... umount /dev/mapper/crypted_fs dmsetup remove crypted_fs After creating, and unmounting, just skip the "mkfs" file command. EG: set mapping, and mount. That is all... Note the encryption key above is just a test hexadecimal value 256 bits or 32 bytes long (needed for AES encryption). It should be something more suitable, like a 'ripemd160' one-way hash of a user pass-phrase, as the cryptsetup tool does. See "key_deivation.txt" For example ask user for a password and return a256 bit hexadecimal hash hashalot -x -n32 ripemd160 You can recover the key information from a existing mapping using the comand: dmsetup table As such this technique is not safe for suid/sudo access to the "dmsetup" access, particularly on a multi-user system. On the other hand "cryptsetup" does not provide such a option so should be safe for user control, with user specific fstab mount of the mapped partition. You do not have to use a ext3 filesystem, you can use anyfile system type linux can generate, including vfat. You may even be able to use the Windows software "CrossCrypt" to mount encrypted vfat file systems. You don't even have to create a filesystem, just using the raw disk device directly. For example "dd" a compressed tar file onto device, rather than use a filesystem) though that my not be very usable. ASIDE: There are other target other than 'crypt', including making mirrors, and stripes. Type this to see... dmsetup targets The arguments for the other targets is not known. ------------------------------------------------------------------------------- Using cryptsetup Fedora Core Package: cryptsetup https://gitlab.com/cryptsetup/cryptsetup https://gitlab.com/cryptsetup/cryptsetup/-/blob/master/FAQ The advantage and disadvantage is that the the method used for mounting a encrypting file system is well known and other tools can be developed to make use of that proceedure. For example various File Managers, like "konquer" could be made to ask the user of the pass-phrase and mount the file system simply and easilly. Defaults to using "aes-plain" for the files system encryption. Older cryptoloop's defaulted to "aes-ecb", but "aes-plain" is more secure. The pass-phrase is hashed to a 256 bit key (32 bytes) using ripemd160 This is equivelent to the "hashalot" command. Example: Encrypted disk partition cryptsetup create x /dev/hda8 # mkfs -t ext3 /dev/mapper/x mount /dev/mapper/x /extra/x ... umount /dev/mapper/x cryptsetup remove x Example: loopback filesystem (also used for mounting cdroms) # dd if=/dev/zero of=encrypted.img bs=1M count=100 losetup /dev/loop0 encrypted.img cryptsetup create unencrypted /dev/loop0 # mkfs -t ext3 /dev/mapper/unencrypted mount /dev/mapper/unencrypted /mnt/unencrypted ... umount /dev/mapper/unencrypted cryptsetup remove unencrypted losetup -d /dev/loop0 Example: Encrypted swap, using a completely random key cryptsetup --key-file=/dev/urandom create swap /dev/hda5 mkswap /dev/mapper/swap mkswap swapon /dev/mapper/swap Example: Encrypt an existing disk partition (not guranteed) WARNING: DO NOT interupt it. It can take a long time. fsck -fC /dev/hda3 cryptsetup -y create hda3-aes /dev/hda3 dd if=/dev/hda3 of=/dev/mapper/hda3-aes bs=4k fsck /dev/mapper/hda3-aes mount /dev/mapper/hda3-aes {appropriate_location} VFAT USB key WARNING: for some reason you cannot create a vfat filesystem on a mapped device. You need to create the vfat file system, then re-map the FS mkfs -t vfat /dev/sda1 cryptsetup create xusb /dev/sda1 dd if=/dev/sda1 of=/dev/mapper/xusb bs=4k mount /dev/mapper/xusb /extra/xusb ------------------------------------------------------------------------------- Other (non-cryptsetup) Ways of storing keys. If you use the third party cryptsetup, the key is generated directly from the pass-phrase, so does not need need to be stored. But there is an advantage to using the pass-prase only to decrypt the real (purely random generated) encryption key (see LUKS). See "key_derivation.txt" ----- Encrypted Key on Device itself... One way is to use SSL to save a copy of the pass phrase encrypted key in the first block of the raw filesystem, and set up the device mapping so as to ignore that one block. This was incorperated into a perl script, but script has a security flaw, involving the users password on a multi-user machine. For example... Settings device='/dev/sda1' mapper='sda1' magic='fixed identifier string of 32 characters' Generate a random key for the encryption key=`dd if=/dev/random bs=32 count=1 | openssl dgst -md5 -hex` Store the key onto the first partition on the disk, encrypted magic='Encrypt_' passwd=`read password from user (no newline)` ( echo $magic; echo $key; ) | \ openssl enc -e -pass pass:"$passwd" -aes256 | \ dd of=$device bs=512 count=1 Read the key from disk passwd=`read password from user (no newline)` dd if=$device bs=512 count=1 | \ openssl enc -d -pass pass:"$passwd" -aes256 | ( read magic -- compare against original magic and abort if different read key ) Set up mapping (skipping the first block) sectors=`blockdev --getsize $device` sectors-- echo "0 $sectors crypt aes-plain $key 0 $device 1" | \ dmsetup create $mapping Mount it mount /dev/mapper/$mapper /data ----- Store key in a GPG (or other) password protected file WARNING: key should not finish with a newline! Create a secure key head -c 2880 /dev/urandom | uuencode -m - |\ head -n 65 | tail -n 64 |\ gpg --armour --symmetric > keyfile.gpg Use a secure key, pipe into cryptsetup gpg --decrypt keyfile.gpg | cryptsetup create ... Or direct to dm_crypt (needs 32 bytes as hexadecimal) head -c 32 /dev/urandom | perl -0777 -e 'print unpack("H*",<>), "\n"' |\ gpg --armour --symmetric > keyfile.gpg gpg --decrypt keyfile.gpg |\ sed 's%.*%0 35021637 crypt aes-plain & 0 /dev/sda1 0% |\ dmsetup create crypted_fs #mkfs -t ext3 /dev/mapper/crypted_fs mount /dev/mapper/crypted_fs /mnt/crypted_fs ------------------------------------------------------------------------------- En-crypting, De-crypting, Re-crypting an existing filesystem I have tested this with LVM2 devices containing nothing important, it worked for me, but you are advised to have current working backups if the data matters to you... You have been warned In the following example we convert /dev/hda3 to use dm-crypt as the device /dev/mapper/hda3-aes WARNING: do not use this when a mapping offset is also used. * Unmount the device to be converted: umount /dev/hda3 * Optional: fsck the device (to be sure there are no errors to start with): fsck /dev/hda3 * Setup the new dm-crypt device: cryptsetup -y -c aes -s 256 create hda3-aes /dev/hda3 (enter the passphrase twice) * Start up the convertion process (takes a long time do not interupt) dd if=/dev/hda3 of=/dev/mapper/hda3-aes bs=4k * Once the conversion has finished fsck the new device: fsck /dev/mapper/hda3-aes * Mount /dev/mapper/hda3-aes where /dev/hda3 would normally have been mounted: mount /dev/mapper/hda3-aes /mnt/hda3 This can be used in reverse to move a device from being encrypted to be unencrypted. In addition you can use this with 2 different mappings to re-encrypt the device with either a new passphrase or with different options including crypher and key size ---- Before copying or burning a encrypted filesystem you should stop the device mapping temporarilly with dmsetup suspend then when finished restart it with dmsetup resume ------------------------------------------------------------------------------- LUKS - via cryptsetup This is the next advancement in cryptsetup. The crypto keys are encrypted into a table. User passwords are tested against each, until the right cryto key is found, which is then used to decode the filesystem. This allows you to change encryption password without re-encrypting the whole disk, or even have multiple passwords (for different users) decrypting the same partition. However under Fedora 5 it appears to be slow, causing all other applications to lockup for a second or two while the LUKS encrypted filesystem password is checked and the dm-crypt setup, (understandably and actually disirable). Fedora 10 works very well with LUKS, and even reconizes them on USB disks! You can even encrypt the whole disk or just the home, so that passwords are requested on boot, as specified by a /etc/crypttab file. PreConfiguration Just fill with random data, using shred (no delete) shred --verbose --iterations=1 /dev/sdb OR using /dev/urandom (not /dev/random which is slower) dd if=/dev/urandom of=/dev/sdb OR use badblocks to fill it with random data (long time) /sbin/badblocks -c 10240 -s -w -t random -v /dev/sdb Re-Partition the disk /sbin/fdisk /dev/sdb Create LUKS partition (just a header, not the actual partition) device=/dev/sdb1 cryptsetup luksFormat $device YES {passphrase} Is it a LUKS partition (like gnome v3) cryptsetup isLuks $device; echo $? cryptsetup luksUUID $device; echo $? luks=luks-$(cryptsetup luksUUID $device) # last generates a error message if not LUKS Format partition cryptsetup luksOpen $device $luks {passphrase} mkfs -t ext4 -L Encrypted_Disk /dev/mapper/$luks #e2label /dev/mapper/$luks Encrypted_Disk tune2fs -c 0 -i 0 -m 0 /dev/mapper/$luks cryptsetup luksClose $luks Mount # Note arguments are swapped for 'create' and 'luksOpen' device=/dev/sdb1 luks=luks-$(cryptsetup luksUUID $device) cryptsetup luksOpen $device luks-$uuid {passphrase} mkdir /mnt/encrypted mount /dev/mapper/luks-$uuid /mnt/encrypted Unmount umount /dev/mapper/luks-$uuid cryptsetup luksClose luks-$uuid Adding and remove passphrases from LUKS cryptsetup luksAddKey $device cryptsetup luksRemoveKey $device cryptsetup luksChangeKey $device See Keys yum install luksmeta luksmeta show -d $device Re-encrypt (change volume key or encryption algorithm) cryptsetup reencrypt # in LUKS2 you can do this on a live filesystem # if this is aborted it will automatically continue on next 'open' # or you can use "cryptsetup repair" Remember cryptsetup, LUKS or otherwise, can be SUID'd or added to sudo so it can be run as root. Of course a fstab entry is still needed for a user mount of the mapped device. Also if pipeing the password in, do NOT end it with a newline! See my script "mount_encrypted" for a more automated mounting But you can now use Gnome Nautilus to do it too (it used a different mapper name and mount point) -------------------------------------------------------------------------------