man: document pkcs#11 hookup in /etc/crypttab

This commit is contained in:
Lennart Poettering 2019-11-04 19:36:47 +01:00
parent 086697094e
commit c2d54475c4
2 changed files with 84 additions and 5 deletions

View File

@ -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>

45
man/yubikey-crypttab.sh Normal file
View File

@ -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 &lt; plaintext.bin | tr -d '\n\r\t ' &gt; 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