diff options
author | Lennart Poettering <lennart@poettering.net> | 2019-11-04 19:36:47 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2019-12-09 19:25:25 +0100 |
commit | c2d54475c4313bed04d1894491ab3c63463f3687 (patch) | |
tree | 5b61b04c82b74ba7f290650f08c3cab5703bb8fd | |
parent | 086697094ec7ea5e51b8fb7d545ecbadab6b9a11 (diff) | |
download | systemd-c2d54475c4313bed04d1894491ab3c63463f3687.tar.gz |
man: document pkcs#11 hookup in /etc/crypttab
-rw-r--r-- | man/crypttab.xml | 44 | ||||
-rw-r--r-- | man/yubikey-crypttab.sh | 45 |
2 files changed, 84 insertions, 5 deletions
diff --git a/man/crypttab.xml b/man/crypttab.xml index e933b2db78..d84a914a5e 100644 --- a/man/crypttab.xml +++ b/man/crypttab.xml @@ -10,7 +10,7 @@ The Red Hat version has been written by Miloslav Trmac <mitr@redhat.com>. --> -<refentry id="crypttab" conditional='HAVE_LIBCRYPTSETUP'> +<refentry id="crypttab" conditional='HAVE_LIBCRYPTSETUP' xmlns:xi="http://www.w3.org/2001/XInclude"> <refentryinfo> <title>crypttab</title> @@ -413,9 +413,22 @@ <varlistentry> <term><option>verify</option></term> - <listitem><para> If the encryption password is read from - console, it has to be entered twice to prevent - typos.</para></listitem> + <listitem><para>If the encryption password is read from console, it has to be entered twice to + prevent typos.</para></listitem> + </varlistentry> + + <varlistentry> + <term><option>pkcs11-uri=</option></term> + + <listitem><para>Takes a <ulink url="https://tools.ietf.org/html/rfc7512">RFC7512 PKCS#11 URI</ulink> + pointing to a private RSA key which is used to decrypt the key specified in the third column of the + line. This is useful for unlocking encrypted volumes through security tokens or smartcards. See below + for an example how to set up this mechanism for unlocking a LUKS volume with a YubiKey security + token. The specified URI can refer directly to a private RSA key stored on a token or alternatively + just to a slot or token in which case a suitable private RSA key object is automatically searched on + it. In this case if multiple suitable objects are found the token is refused. The key configured in + the third column is passed as is to RSA decryption. The resulting decrypted key is then base64 + encoded before it is used to unlock the LUKS volume.</para></listitem> </varlistentry> <varlistentry> @@ -458,7 +471,7 @@ </refsect1> <refsect1> - <title>Example</title> + <title>Examples</title> <example> <title>/etc/crypttab example</title> <para>Set up four encrypted block devices. One using LUKS for @@ -471,6 +484,27 @@ truecrypt /dev/sda2 /etc/container_password tcrypt hidden /mnt/tc_hidden /dev/null tcrypt-hidden,tcrypt-keyfile=/etc/keyfile external /dev/sda3 keyfile:LABEL=keydev keyfile-timeout=10s</programlisting> </example> + + <example> + <title>Yubikey-based Volume Unlocking Example</title> + + <para>The PKCS#11 logic allows hooking up any compatible security token that is capable of storing RSA + decryption keys. Here's an example how to set up a Yubikey security token for this purpose:</para> + +<programlisting><xi:include href="yubikey-crypttab.sh" parse="text" /></programlisting> + +<para>A few notes on the above:</para> + +<itemizedlist> + <listitem><para>We use RSA (and not ECC), since Yubikeys support PKCS#11 Decrypt() only for RSA keys</para></listitem> + <listitem><para>We use RSA2048, which is the longest key size current Yubikeys support</para></listitem> + <listitem><para>LUKS key size must be shorter than 2048bit due to RSA padding, hence we use 128 bytes</para></listitem> + <listitem><para>We use Yubikey key slot 9d, since that's apparently the keyslot to use for decryption purposes, + <ulink url="https://developers.yubico.com/PIV/Introduction/Certificate_slots.html">see + documentation</ulink>.</para></listitem> +</itemizedlist> + + </example> </refsect1> <refsect1> diff --git a/man/yubikey-crypttab.sh b/man/yubikey-crypttab.sh new file mode 100644 index 0000000000..b7e8ee686f --- /dev/null +++ b/man/yubikey-crypttab.sh @@ -0,0 +1,45 @@ +# Make sure noone can read the files we generate but us +umask 077 + +# Destroy any old key on the Yubikey (careful!) +ykman piv reset + +# Generate a new private/public key pair on the device, store the public key in 'pubkey.pem'. +ykman piv generate-key -a RSA2048 9d pubkey.pem + +# Create a self-signed certificate from this public key, and store it on the device. +ykman piv generate-certificate --subject "Knobelei" 9d pubkey.pem + +# Check if the newly create key on the Yubikey shows up as token in PKCS#11. Have a look at the output, and +# copy the resulting token URI to the clipboard. +p11tool --list-tokens + +# Generate a (secret) random key to use as LUKS decryption key. +dd if=/dev/urandom of=plaintext.bin bs=128 count=1 + +# Encode the secret key also as base64 text (with all whitespace removed) +base64 < plaintext.bin | tr -d '\n\r\t ' > plaintext.base64 + +# Encrypt this newly generated (binary) LUKS decryption key using the public key whose private key is on the +# Yubikey, store the result in /etc/encrypted-luks-key.bin, where we'll look for it during boot. +openssl rsautl -encrypt -pubin -inkey pubkey.pem -in plaintext.bin -out /etc/encrypted-luks-key.bin + +# Configure the LUKS decryption key on the LUKS device. We use very low pbkdf settings since the key already +# has quite a high quality (it comes directly from /dev/urandom after all), and thus we don't need to do much +# key derivation. +cryptsetup luksAddKey /dev/sda1 plaintext.base64 --pbkdf=pbkdf2 --pbkdf-force-iterations=1000 + +# Now securely delete the plain text LUKS key, we don't need it anymore, and since it contains secret key +# material it should be removed from disk thoroughly. +shred -u plaintext.bin plaintext.base64 + +# We don't need the public key anymore either, let's remove it too. Since this one is not security +# sensitive we just do a regular "rm" here. +rm pubkey.pem + +# Test: Let's run systemd-cryptsetup to test if this all worked. The option string should contain the full +# PKCS#11 URI we have in the clipboard, it tells the tool how to decypher the encrypted LUKS key. +systemd-cryptsetup attach mytest /dev/sda1 /etc/encrypted-luks-key.bin 'pkcs11-uri=pkcs11:…' + +# If that worked, let's now add the same line persistently to /etc/crypttab, for the future. +echo "mytest /dev/sda1 /etc/encrypted-luks-key 'pkcs11-uri=pkcs11:…' >> /etc/crypttab |