Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tomb 2.9.0 as root with smartcard [Bug? + Workaround] #449

Open
so-rose opened this issue Oct 22, 2022 · 5 comments
Open

Tomb 2.9.0 as root with smartcard [Bug? + Workaround] #449

so-rose opened this issue Oct 22, 2022 · 5 comments
Assignees
Labels
enhancement An issue to improve current behavior
Milestone

Comments

@so-rose
Copy link

so-rose commented Oct 22, 2022

A little background first. I'm using Secure Boot, which requires one to sign kernel modules with a user-generated, firmware-enrolled key. Anybody with this key can theoretically execute kernel-level code. Therefore, I'm attempting to use tomb to make these keys inaccessible without a GPG private key, stored on a piece of hardware (Yubikey).

This is my setup for running tomb:

  • On Debian 11 (uname -a: Linux <> 5.10.0-18-amd64 #1 SMP Debian 5.10.140-1 (2022-09-02) x86_64 GNU/Linux)
  • Exclusively as root (Secure Boot kernel module signing keys shouldn't touch non-root users)
  • With GPG private keys on a smartcard (only configured for the primary user)
  • At version 2.9 (latest in Debian repo)

I'm running the following commands as root, with no preexisting /root/.gnupg:

gpg --recv-keys $KEY_ID  ## import the tomb's owner + initialize /root/.gnupg

tomb dig -s 10 /root/mok.tomb
tomb forge /root/mok.tomb.key -gr $KEY_ID
tomb lock /root/mok.tomb -k /root/mok.tomb.key -gr $KEY_ID

#...open the tomb and use it!

The Problem

Running a similar script (s/root/$HOME/g) as a normal user works perfectly: The GUI pinentry shows, all is well.

As root, however, tomb lock fails insisting that there's no valid password (<> is redaction):

$ tomb lock /root/mok.tomb -k /root/mok.tomb.key -gr $KEY_ID -D
tomb  .  Locking using cipher: aes-xts-plain64
tomb [D] no password needed, using GPG key
tomb [D] get_lukskey
...
tomb [D] [GNUPG:] ENC_TO <> 1 0
tomb [D] [GNUPG:] KEY_CONSIDERED $KEY_ID 0
tomb [D] [GNUPG:] PINENTRY_LAUNCHED 140666 gnome3:curses 1.1.0 - xterm-kitty :0
tomb [D] [GNUPG:] KEY_CONSIDERED <> 0
tomb [D] gpg: encrypted with 4096-bit RSA key, ID $KEY_ID, created <>
tomb [D]       "<> <>"
tomb [D] gpg: public key decryption failed: Inappropriate ioctl for device
tomb [D] [GNUPG:] ERROR pkdecrypt_failed 83918950
tomb [D] [GNUPG:] BEGIN_DECRYPTION
tomb [D] [GNUPG:] DECRYPTION_FAILED
tomb [D] gpg: decryption failed: No secret key
tomb [D] [GNUPG:] END_DECRYPTION
tomb [D] get_lukskey returns 1
tomb [E] No valid password supplied.

It seems like gpg can't find anywhere to launch its pinentry. I observed:

  • The pinentry never launches. Neither in the terminal or GUI. Switching pinentry to point at pinentry-tty also doesn't help. This makes this problem distinct from the solved Unable to lock tomb using GPG #251.
  • Switching pinentry out to point to pinentry-tty (using update-alternatives) does has two effects:
    • The error Inappropriate ioctl for device is switched out for Invalid IPC response.
    • gnome3:curses alone is switched out for tty.

All in all, it seems like gpg doesn't know how to launch the pinentry, and thus just fails. tomb gets no secret to unlock the key with, and thus - no tomb ☹️

The Workaround

I noticed that the end of gpg_decrypt was where the critical gpg invocation was in the locking/opening procedure:

https://github.com/dyne/Tomb/blob/f35ad11e3f5b29fd9b441a3111cc7a0c097036b1/tomb#L1118-L1121

As it seemed like the pinentry-mode was an issue. I tried setting /root/.gnupg/gpg.conf after reading things like https://superuser.com/questions/520980/how-to-force-gpg-to-use-console-mode-pinentry-to-prompt-for-passwords, but this didn't seem to get picked up on.

Finally, because of answers like https://stackoverflow.com/questions/18123918/why-is-gpg-not-working-even-with-pinentry-installed, I tried adding --pinentry-mode loopback:

TOMBSECRET=`print - "$gpgpass" | \
		gpg --decrypt ${gpgpopt[@]} \
			--status-fd 2 --no-mdc-warning --no-permission-warning \
			--no-secmem-warning --pinentry-mode loopback 2> $tmpres`

Now, when I run the same command as root, it works!

$ tomb lock /root/mok.tomb -k /root/mok.tomb.key -gr $KEY_ID -D
tomb  .  Locking using cipher: aes-xts-plain64
tomb [D] no password needed, using GPG key
tomb [D] get_lukskey
tomb [D] Created tempfile: /tmp/14336175871231220299
Enter Passphrase: 

Again, it's curious that it still doesn't call the pinentry. This also breaks tomb when used as a non-root user.

Patch

If I understood the problem better, I'd be happy to suggest a PR. Perhaps a CLI option to explicitly turn on loopback pinentry? For now, I just have a patch (works on the Debian 11 version of tomb; I haven't tested upstream. It should be easy enough to modify the line number 1123 below to work on any tomb install)

tomb-loopback.patch

1123c1123
< 			--no-secmem-warning 2> $tmpres`
---
> 			--no-secmem-warning --pinentry-mode loopback 2> $tmpres`

used with:

patch /usr/bin/tomb < tomb-loopback.patch       ## Apply the patch
patch -R /usr/bin/tomb < tomb-loopback.patch   ## Remove the patch

Whenever I need to run tomb as root, I just wrap it in the patch:

gpg --recv-keys $KEY_ID  ## import the tomb's owner + initialize /root/.gnupg

patch /usr/bin/tomb < tomb-loopback.patch  ## A trap could make this more reliable
    tomb dig -s 10 /root/mok.tomb
    tomb forge /root/mok.tomb.key -gr $KEY_ID
    tomb lock /root/mok.tomb -k /root/mok.tomb.key -gr $KEY_ID
    
    tomb open /root/mok.tomb -k /root/mok.tomb.key -g -p
patch -R /usr/bin/tomb < tomb-loopback.patch

#...add root:root owned secrets to the tomb (courtesy -p).

When actually signing kernel modules via DKMS, I just modified /etc/dkms/sign_helper.sh to patch tomb, open mok.tomb (with GPG and -p, to avoid chowning files to a user calling via sudo), sign, tomb slam and unpatch tomb.

Thus, it's been achieved that no kernel modules can be signed without the presence of the smartcard w/the GPG private key 😄

System Info

Here's tomb -v:

  Tomb 2.9.0 - a strong and gentle undertaker for your secrets

   Copyright (C) 2007-2021 Dyne.org Foundation, License GNU GPL v3+
   This is free software: you are free to change and redistribute it
   For the latest sourcecode go to <http://dyne.org/software/tomb>

   This source code is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   When in need please refer to <http://dyne.org/support>.

  System utils:

No $DBUS_SESSION_BUS_ADDRESS found, falling back to curses
gpg: WARNING: unsafe ownership on homedir '/home/sofus/.gnupg'
gpg: WARNING: unsafe ownership on homedir '/home/sofus/.gnupg'
  zsh 5.8 (x86_64-debian-linux-gnu)
  Sudo version 1.9.5p2
  cryptsetup 2.3.7
  pinentry-gnome3 (pinentry) 1.1.0
  findmnt from util-linux 2.36.1
  gpg (GnuPG) 2.2.27 - key forging algorithms (GnuPG symmetric ciphers):
  IDEA 3DES CAST5 BLOWFISH AES AES192 AES256 TWOFISH CAMELLIA128 CAMELLIA192 CAMELLIA256

  Optional utils:

  /usr/bin/gettext
  dcfldd not found
  /usr/bin/shred
  steghide not found
  /usr/sbin/resize2fs
  /usr/libexec/tomb/tomb-kdb-pbkdf2
  /usr/bin/qrencode
  swish-e not found
  unoconv not found
  /usr/bin/lsof
@jaromil
Copy link
Member

jaromil commented Nov 11, 2022

Hi @so-rose and thanks for the detailed description!

I suspect that it may be possible to detect the specific situation of calling tomb from root user and then add the pinentry-loopback option to gpg invokation.

@so-rose
Copy link
Author

so-rose commented Dec 20, 2022

@jaromil Sure thing! Hoped it might be of help to others.

Would you be open to a PR that detects root invocation (not just sudo) and injects --pinentry-mode loopback accordingly? It still bugs me that the normal pinentry doesn't show when starting explictly as root, but perhaps that's by gpg's design...

If you'd like, I could also document the firmware-key usage somewhere. I don't know where would be best, though?

@jaromil
Copy link
Member

jaromil commented Dec 30, 2022

Yes, that would be good, as long as it doesn't break current tests.

@jaromil jaromil added the enhancement An issue to improve current behavior label Dec 30, 2022
@jaromil
Copy link
Member

jaromil commented Jan 29, 2024

Hi @so-rose ! in case you are still up for this, I keep this issue open. It is a very interesting use case so please let us know if we can link your docs on firmware-key usage and of course you are welcome to file such a PR, else I'll do it myself.

@jaromil jaromil self-assigned this May 11, 2024
@jaromil
Copy link
Member

jaromil commented May 11, 2024

Will try, any help crafting the right check is very welcome.

@jaromil jaromil added this to the 3.0 milestone May 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement An issue to improve current behavior
Projects
None yet
Development

No branches or pull requests

2 participants