Skip to content

Plain dm-crypt unlocking via PKCS#11 with systemd-cryptsetup fails with an encrypted keyfile #38291

@jeth-ro

Description

@jeth-ro

systemd version the issue has been seen with

257.7

Used distribution

Gentoo

Linux kernel version used

6.12.21-gentoo

CPU architectures issue was seen on

x86_64

Component

systemd-cryptsetup

Expected behaviour you didn't see

Expected successful "unlocking" via PKCS#11 of a plain dm-crypt device when the passphrase is read from an encrypted key file. This seems like it should be a supported use case in that it fits with the 1st mechanism listed in the description section of the systemd-cryptsetup man page, albeit specifically for plain mode.

The following entry in /etc/crypttab was used:

enc0   /tmp/<encrypted-volume>   /tmp/<encrypted-keyfile>   noauto,nofail,plain,
                                                            cipher=aes-xts-plain64,hash=sha512,size=512,
                                                            token-timeout=5,pkcs11-uri=<private-key-uri>

/tmp/<encrypted-volume> is an encrypted file with a valid filesystem in it, set up in advance using cryptsetup in plain mode with a the base64 encoding of "foobar" as the passphrase.

/tmp/<encrypted-keyfile> contains the cipher-text of "foobar", encrypted by openssl-rsautl using a 4096-bit RSA public key generated on an OpenPGP card.

<private-key-uri> references the corresponding private key on the security token, adapted from the URI reported by pkcs11-tool --list-objects.

Unexpected behaviour you saw

The corresponding (generated) systemd-cryptsetup unit fails to start. The logs indicate it wasn't able to decrypt the key file:

Jul 16 11:35:11 <hostname> systemd[1]: Starting Cryptography Setup for enc0...
Jul 16 11:35:11 <hostname> systemd-cryptsetup[3001801]: Set cipher aes, mode xts-plain64, key size 512 bits for device
/tmp/<encrypted-volume>.
Jul 16 11:35:14 <hostname> systemd-cryptsetup[3001801]: Successfully logged into security token 'OpenPGP card (User PIN)'.
Jul 16 11:35:14 <hostname> systemd-cryptsetup[3001801]: Failed to decrypt key on security token: The operation failed
Jul 16 11:35:14 <hostname> systemd[1]: systemd-cryptsetup@enc0.service: Main process exited, code=exited, status=1/FAILURE
Jul 16 11:35:14 <hostname> systemd[1]: systemd-cryptsetup@enc0.service: Failed with result 'exit-code'.
Jul 16 11:35:14 <hostname> systemd[1]: Failed to start Cryptography Setup for enc0

Turning on debug=3 in /etc/opensc.conf and comparing the resulting OpenSC log output from both systemd-cryptsetup and pkcs11-tool (both are using opensc-pkcs11.so) reveals what seems to be the problem:

<much redacted noise>
...
[opensc-pkcs11] reader-pcsc.c:328:pcsc_transmit:
Outgoing APDU (74 bytes):
00 2A 80 86 00 00 41 00 74 C4 59 F9 E3 21 49 05 .*....A.t.Y..!I.
95 EB 18 1F 71 86 AD 89 3F DE D8 A8 58 FF 8C D7 ....q...?...X...
42 2D C3 08 E7 B7 60 38 97 DB 96 83 42 62 89 60 B-....`8....Bb.`
94 6C D9 B3 33 A3 B4 BD 98 3C BA C7 00 F0 57 5E .l..3....<....W^
A8 3D 90 70 E0 11 ED FC 02 00                   .=.p......

[opensc-pkcs11] reader-pcsc.c:245:pcsc_internal_transmit: called
[opensc-pkcs11] reader-pcsc.c:337:pcsc_transmit:
Incoming APDU (2 bytes):
69 85 i.

[opensc-pkcs11] apdu.c:382:sc_single_transmit: returning with: 0 (Success)
[opensc-pkcs11] apdu.c:539:sc_transmit: returning with: 0 (Success)
[opensc-pkcs11] card.c:523:sc_unlock: called
[opensc-pkcs11] iso7816.c:128:iso7816_check_sw: Conditions of use not satisfied
[opensc-pkcs11] card-openpgp.c:2486:pgp_decipher: Card returned error: -1209 (Not allowed)
[opensc-pkcs11] sec.c:50:sc_decipher: returning with: -1209 (Not allowed)
[opensc-pkcs11] card.c:523:sc_unlock: called
[opensc-pkcs11] pkcs15-sec.c:169:use_key: returning with: -1209 (Not allowed)
[opensc-pkcs11] pkcs15-sec.c:313:sc_pkcs15_decipher: use_key() failed: -1209 (Not allowed)
[opensc-pkcs11] card.c:523:sc_unlock: called
[opensc-pkcs11] reader-pcsc.c:734:pcsc_unlock: called
[opensc-pkcs11] framework-pkcs15.c:4626:pkcs15_prkey_decrypt: Decryption complete.

The above outgoing APDU seen in the systemd-cryptsetup case is much shorter than that sent by pkcs11-tool. It appears that systemd-cryptsetup has passed only the first 64-bytes of the encrypted key file the OpenSC library. The security token has then returned the status bytes 0x69 0x85, which in the OpenPGP card specification does indeed mean "Condition of use not satisfied" (as logged). That's a pretty unhelpful message, but I'd hazard a guess that the token wants 512-bytes for a 4096-bit RSA key.

Best I can tell, this is actually documented behaviour, as per the explanation of keyfile-size= in the crypttab man page, which says "this option is ignored in plain mode" and the block cipher key size is used instead. That would seem to make sense when the key is directly stored in the key file, but seems incompatible with security tokens using cryptosystems with expanded ciphertexts.

For what it's worth, things work fine in LUKS mode with systemd-cryptenroll and the exact same key files and PKCS#11 URI.

Steps to reproduce the problem

Approximate steps to reproduce:

  1. Choose a test passphrase
  2. Base64 encrypt the passphrase into a plaintext key file
  3. Create a plain dm-crypt mapping using /etc/crypttab and the above plaintext key file (no security token)
  4. Start systemd-cryptsetup and create some valid data in the resulting device, then stop systemd-cryptsetup
  5. Encrypt the test passphrase using RSA, or some other cryptosystem supported by the token
  6. Modify the crypttab entry from step 3 to point to the encrypted keyfile and add the token URI
  7. Do the daemon-reload dance to reload crypttab
  8. Start systemd-cryptsetup, authenticate with the token when prompted.

If the ciphertext in the encrypted keyfile is longer than the dm-crypt block cipher then unlocking the plain dm-crypt volume fails.

Additional program output to the terminal or log subsystem illustrating the issue

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug 🐛Programming errors, that need preferential fixingcryptsetup

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions