There are various solutions to use yubikey with LUKS. Most of them (except one) have a certain security risk: though LUKS passphrase is generated by yubikey, it is static. So if anybody can save the key in some way, it can unlock LUKS partition without yubikey.
I came across the experimental project for Gentoo Linux to change LUKS key after each login. But Gentoo Linux is very different from Kali (Kali is based on Debian) and it has completely different way to initialize kernel and unlock encrypted drives. I took the challenge and implemented similar script for Kali Linux. Though I did not test it with stock Debian, I guess it should work there too because Kali is based on Debian.
There are several important things you should know:
- This is not a beginner's guide! While I made sure that instructions here truly work, there still can be typos, mistakes, differences between Linux releases, etc. Make sure that you are comfortable with shell, shell scripting, and how to recover from unusual situations.
- Security note: Due to the structure of Kali init scripts, key handling had to be split to several scripts. To transfer data, temporary files are created in the
/boot/yubikey/
directory. To prevent those keys from being readable, they are encrypted with GnuPG. Private key for this encryption is stored on your LUKS partition, thus there is no way for anybody to decrypt your current or new key unless they run the whole system in the emulator and can pause after each step before those keys are encrypted. - LUKS key slot 2 is hard-coded in the script to let you use key slot 1 for the nuke key (which you definitely should use!)
- You should always have a backup password: long and hard to guess. Choose a quote from your favorite book that you can memorize forever. You will be able to enter this backup password each 3rd time when you are prompted for the password. It will unlock your LUKS partition in any case.
You have to build some packages manually. While Yubico packages exist in Kali repositories, they are not suitable for initramfs
.
Install packages:
apt-get install pkg-config
Don't use libusb-1.0.0
, see here why.
apt-get install libusb-dev
apt-get install libyubikey-dev
apt-get install asciidoc
apt-get install dh-autoreconf
mkdir yubico
cd yubico
git clone https://github.com/Yubico/yubico-c.git
cd yubico-c
autoreconf --install
./configure --with-backend=libusb
make LD_FLAGS=-all-static
git clone https://github.com/Yubico/yubikey-personalization.git
autoreconf --install
./configure --with-backend=libusb
make LD_FLAGS=-all-static
make install
Let's free some disk space and remove huge packages that we will never use again.
Remove asciidoc
:
apt-get purge asciidoc dblatex dblatex-doc docbook-dsssl docbook-utils docbook-xml docbook-xsl fonts-texgyre jadetex libfile-homedir-perl libfile-which-perl libosp5 libostyle1c2 libsgmls-perl libxml2-utils libyaml-tiny-perl lynx lynx-common openjade opensp preview-latex-style prosper ps2eps sgml-data sgmlspl tex-gyre texlive texlive-bibtex-extra texlive-extra-utils texlive-font-utils texlive-fonts-recommended texlive-fonts-recommended-doc texlive-generic-recommended texlive-htmlxml texlive-latex-extra texlive-latex-extra-doc texlive-latex-recommended texlive-latex-recommended-doc texlive-luatex texlive-math-extra texlive-pictures texlive-pictures-doc texlive-pstricks texlive-pstricks-doc tipa xmlto xsltproc
Remove autoreconf
:
apt-get purge autoconf automake autopoint autotools-dev debhelper dh-autoreconf dh-strip-nondeterminism gettext intltool-debian libarchive-zip-perl libfile-stripnondeterminism-perl libltdl-dev libmail-sendmail-perl libsys-hostname-long-perl libtool po-debconf
Copy scripts using copy_scripts.sh
inside this directory.
Modify /etc/crypttab
:
sda5_crypt UUID=4d435248-dfa8-4f77-8adb-c75242e178a0 none luks,keyscript=yubikey_unlock
sda5_crypt
is the default if you used "full disk encrypted" option during setup. UUID
will be different in your case.
Note: you may see Linux compalin about unknown parameter ,keyscript=yubikey_unlock
if you montor /var/log/
. Ignore that. This parameter is for init scripts and other parts of the system are not familiar with it.
Connect yubikey and personalize it:
ykpersonalize -2 -ochal-resp -ochal-hmac -oserial-usb-visible -oserial-api-visible
Create initial challenge and key:
mkdir /boot/yubikey
chmod u+rwx,g-rwx,o-rwx /boot/yubikey
uuidgen > /boot/yubikey/yk_challenge
ykchalresp -2 "yourpassword`cat /boot/yubikey/yk_challenge`" > kf
cryptsetup luksAddKey --key-slot 2 /dev/sda5 kf
shred -u -z kf
Note: yourpassword
above is the password you will type each time during login with yubikey. This is not your initial (safe) password that you entered during Kali installation!
Download GnuPG Classic (!) from the official web site, check its signature, build and install. Make sure that you do download a Classic version (1.4.x), not GnuPG 2!
wget https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-1.4.21.tar.bz2
wget https://www.gnupg.org/ftp/gcrypt/gnupg/gnupg-1.4.21.tar.bz2.sig
gpg --keyserver keys.gnupg.net --recv-keys 4F25E3B6 E0856959 33BD3F06 7EFD60D9
gpg --verify gnupg-1.4.21.tar.bz2.sig gnupg-1.4.21.tar.bz2
You should now see a message about good signature similar to this:
gpg: Signature made Wed 17 Aug 2016 09:30:14 AM EDT
gpg: using RSA key 249B39D24F25E3B6
gpg: Good signature from "Werner Koch (dist sig)" [unknown]
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.
Primary key fingerprint: D869 2123 C406 5DEA 5E0F 3AB5 249B 39D2 4F25 E3B6
Should you see something else but not "Good signature", you should re-download GnuPG and repeat key verification until you have a good signature.
Build and instal GnuPG. Note that Kali comes with a stripped down version of gnupgv1
binary. This build will install a full version into /use/local/bin
but it will not be visible by default from shell, so we will always call it using full path.
tar xjf gnupg-1.4.21.tar.bz2
cd gnupg-1.4.21
./configure --program-suffix=v1
make install
Generate GnuPG keys for initramfs
scripts without password. Note: here we use both gpg v2 and v1 to simplify the whole thing.
gpg --quick-gen-key initramfs "" "" 0
gpg --export initramfs > initramfs.pub
/usr/local/bin/gpgv1 --homedir /boot/yubikey --import initramfs.pub
rm initramfs.pub
gpg --export-secret-keys initramfs > initramfs.pri
/usr/local/bin/gpgv1 --import initramfs.pri
shred -u -z initramfs.pri
Now we need to set the key trust to ultimate or gpg will refuse to decrypt files with it. Find out key id:
/usr/local/bin/gpgv1 --homedir /boot/yubikey --list-keys
You will see something like:
/boot/yubikey/pubring.gpg
--------------------------
pub 2048R/3DB17B0F 2016-10-09
uid initramfs
sub 2048R/13ABC021 2016-10-09
Then you set the trust:
/usr/local/bin/gpgv1 --homedir /boot/yubikey --edit-key 3DB17B0F
You will need your own key id above instead of 3DB17B0F
! When prompted, type trust
and then select I trust ultimately
, wait until it is done and type quit
.
Now after you got GnuPG keys in place, it is time to finalize the installation.
Rebuild initramfs
:
update-initramfs -u
Reboot with youbikey inserted and type the password you created earlier.
If your yubikey password does not work, you can login with safety password when you see Enter your password to unlock the disk (2):
(note (2)
!). After booting, remove the damaged key from the LUKS slot:
cryptsetup luksKillSlot /dev/sda5 2
Now you can re-create initial challenge and key to try again.
There are two scripts in the tools/
directory that can help you to test and reset the password.
"YubiKey and LUKS encrypted partition/disk" at ArchWiki
"YubiKey Full Disk Encryption" project at GitHub
"GnuPG hook for Arch Linux initcpio" project at GitHub
GPL v3 or newer. Remember that copyright has to be kept even in derived work!
While I am interested in improvements and suggestions, I cannot provide any immediate support or guarantees or be responsible for any damage.
Use at your own risk.
You can contact me at dmitry.dulepov@gmail.com.