To use the librem key for sudo (and eventually other tasks) install and configure
I use Kubuntu on a Librem 15 with Pureboot and on a UEFI based system. The process is mostly the same but pureboot (heads) adds a few steps.
The system installs and I use the Librem key to decrypt data. I also use the librem key for some authentication operations and am working toward as many as possible.
To get 20.10 to install successfully using LUKS for the root partition I ran the Kubuntu live environment. I updated it to get the latest bugfixes for the installer but that doesn't seem to make a difference.
sudo apt update && apt -y dist-upgrade
Then, I manually setup the LUKS partition so it would be available for the kde install. I use the guid of the partition as the basis for the luks device after it is decrypted. This shows a relationship between the two.
sudo luksformat /dev/sdaX
guid=`blkid -s UUID -o value /dev/sdaX`
sudo cryptsetup luksOpen /dev/sdaX luks-$guid
I tried LVM for more flexibility and regretted this later as it makes the boot process more complicated and it broke. Ultimately, I abandoned LVM.
sudo su
pvcreate /dev/mapper/luks-$guid
vgcreate vg_kubuntu /dev/mapper/luks-$guid
lvcreate -n lv_root -L 40G vg_kubuntu
exit
Then I ran the installer in kde mode and told it to NOT install the bootloader. On this system I use heads/pureboot. I don't want the grub boot in the MBR of the drive and it won't work on my lvm or boot partitions. We'll do more with this later.
ubiquity --no-bootloader kde_ui
Don't allow the installer to restart. Instead continue 'testing' in the live environment. There are more changes needed.
I need to modify files in the distro I just installed before it will boot properly. If it is not already mounted I mount the root partition at /target.
mount /dev/mapper/vg_kubuntu-lv_root /target
Now I have to mount other filesystems needed for the setup and then use chroot to 'pretend' that I booted the distro. Lastly, I tell it to mount everything else.
cd /target
mount -o bind /dev dev
mount -o bind /proc proc
chroot /target
mount -a
This should have mounted the /boot partition. If not there is a bigger problem.
I need a grub.cfg for heads to find kernels to boot. Since I skipped installing it I have to generate it manually. Having mounted the system and used chroot before I can then run
grub-mkconfig -o /boot/grub/grub.cfg
After the install the initrd needs updates to allow Linux to boot and find the encrypted filesystem. Later I will add the Librem key. Since I already used chroot I will treat this as if I am in the system after it has booted. I need to know what the ID is for the root file system. Since I am still in the environment where I did the install I have the variable $guid and know that the luks device name is luks-$guid. The encrypted luks partition is /dev/sdaX.
I use blkid to get the UUID of the luks drive and echo the appropriate settings into crypttab.
echo "luks-$guid UUID=$guid none luks" >> /etc/crypttab
Next, I update the initrd files to get the encryption/decryption into the boot process. (this will also be done for me if I use apt to update the system which requires having network on and a nameserver specified in /etc/resolv.conf)
update-initramfs -u -k all
If I didn't use the same open luks device name in /etc/crypttab that was used to decrypt in the install environment the initrd updates will fail.
If I dont tear everything down the system may hang on restart.
umount -a
umount /proc
exit
cd /
umount /target
lvchange -an vg_kubuntu
cryptsetup luksClose /dev/mapper/luks-$guid
I now restart the system to make sure the boot process works. Once Kubuntu has booted I use the passphrase to decrypt root.
The next setup is to configure boot to use the smartcard instead of a passphrase. I have tried to combine this into the previous steps but not been able to make it work.
First, add smartcard utilities
sudo apt install opensc scdaemon libccid pcscd pcsc-tools pinentry-tty
You can try pinentry-curses but it has lots of problems. I have to uninstall it and resetup every time I try it.
test key
gpg --card-status
I try to export public key for smartcard for use in boot process. and it in /boot for future reference. but the format is invalid. ultimately I end up grabbing the original public key I exported from gpg when I setup the smartcard
pkcs15-tool --read-public-key ID > pubkey.asc #bad format
sudo cp /path/to/original/pubkey.asc /boot/pubkey.asc
gpg --export XYZ > pubring.gpg
sudo mv pubring.gpg /etc/cryptsetup-initramfs/pubring.gpg
I uploaded the public key to a keyserver and I have the file locally.
gpg --import /boot/pubkey.asc
Once again I run into pkcs15-tool not being able to see my librem key. Have to dig around in old posts to solve again.
pkcs15-tool -D
which shows No smart card readers found. I have to hack my librem key into the libccid settings per this post.
after libccid is installed, the file with the list of supported devices can be found at: /etc/libccid_Info.plist
And adding the following strings:
in <key>ifdVendorID</key>
add: <string>0x316D</string>
in: <key>ifdProductID</key>
add: <string>0x4C4B</string>
in: <key>ifdFriendlyName</key>
add: <string>Librem Key</string>
After rebooting the machine, libccid will recognize the Librem Key
echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="316d", ATTR{idProduct}=="4c4b", ENV{ID_SMARTCARD_READER}="1", ENV{ID_SMARTCARD_READER_DRIVER}="gnupg"' > /etc/udev/rules.d/60-librem-key.rules
Need to restart to make sure the librem key is recognized. (I wonder if we can restart libccid or pcsc instead of restarting?) After the restart check using
pkcs15-tool -D
This should output lines that start with PIN and Public RSA.
To add the smartcard (Librem key for me) to the boot process I create a new binary data key and add it to a keyslot on the luks root device. In addition, the key is encrypted using the smartcard. The boot process also needs the encrypted luks key for unlocking the disk to be placed in /etc/cryptsetup-initramfs/cryptkey.gpg
I cannot get gpg to accept the private key on standard input which requires that it be written to disk. This is a security risk. To mitigate I use /run/user/1000/ since it is a ramdisk and should be lost on next boot. In addition I shred the file after I am finished
dd if=/dev/urandom of=/run/user/1000/foo bs=1 count=245
gpg --trust-model=always --yes --default-recipient-self --encrypt --armor foo
sudo cryptsetup luksAddKey "${LUKS_TARGET_DEV}" foo
#if that works shred the key
shred foo
rm -f foo
sudo mv cryptkey.gpg /etc/cryptsetup-initramfs/
If this all works the keys are all in place for use in the boot process. The boot process must be modified to put everything together. add another line to /etc/crypttab and comment out the first line. Lastly, update the ramdisk to make it all work. might want to backup the current working ramdisk too.
sed -i 's/^/#/g' /etc/crypttab
echo "luks-$guid UUID=$guid /etc/cryptsetup-initramfs/cryptkey.gpg luks,keyscript=decrypt_gnupg-sc" >> /etc/crypttab
tar -czf /boot/initrd.bak.tar /boot/initrd*
sudo update-initramfs -u -k all
????? is this needed?
#echo "CRYPTSETUP=y" >> /etc/cryptsetup-initramfs/conf-hook
If the boot up fails, you may need to run a rescue image such as the kubuntu installer environment. From there try to use the smart card to access the LUKS drive. Run konsole and mount the boot partition
sudo su
guid=`blkid -s UUID -o value /dev/sdaX`
echo $guid
mkdir /mnt/boot
mount /dev/sdaX /mnt/boot
apt install opensc
gpg --decrypt /mnt/boot/cryptkey.gpg | cryptsetup -q --key-file=- luksOpen /dev/disk/by-uuid/$guid luks-$guid
If I was using grub to boot I would update grub to remove splash screen because otherwise I can't see the prompt for pin entry.
/etc/default/grub: GRUB_CMDLINE_LINUX_DEFAULT="quiet"
update grub for all settings just made
update-grub
heads will prompt to re-sign boot files which is good. boot should ask for the PIN that leads to decrypting the hard disk rather than asking for the passphrase.
To use the librem key for sudo (and eventually other tasks) install and configure poldi
sudo apt install libpam-poldi
The configuration files are in /etc/poldi. Add my user account and the librem key to the configuration then add the keyfile for the smartcard.
ID=`gpg --card-status | grep 'Application ID' | awk -F: '{print $2;}' | tr -d ' '`
sudo echo "$ID $USER" >> /etc/poldi/localdb/users
sudo touch /etc/poldi/localdb/keys/$ID
sudo chown myuser /etc/poldi/localdb/keys/$ID
gpg-connect-agent "/datafile /etc/poldi/localdb/keys/$ID" "SCD READKEY --advanced OPENPGP.3" /bye
That last statement extracts the public key in a particular format and puts it into the poldi configs. Since I use more than one key I have to run it for each one of them (or copy from another setup). The public key is the same for each of them so I really just need the file duplicated using the key ID for each.
GDM has some smartcard extensions. I am trying to get them to work even though I prefer anything other than GDM for a display manager. Can't find any info on smartcards with KDE. Will probably need to read source code and maybe patch.
Possible solutions
cackey
poldi
gnome/gdm feature
sudo apt install gnome-tweaks gdm3 gnome-shell-extensions chrome-gnome-shell
gnome-tweaks
https://itsfoss.com/gnome-shell-extensions/
I am already using pam_poldi with sudo. If the auth is delegated by screensaver/gdm/kdm to pam/poldi then this should work the same way.
I'm going for.
https://askubuntu.com/questions/1097458/login-fails-silently-on-system-restart-after-adding-new-module-to-etc-pam-d-co
https://www.reddit.com/r/kde/comments/chaysj/state_of_sddm_pam_2fa_prompts/
1
First attempt I put 'auth sufficient pam_poldi.so' in common-auth but this has the side effect of requiring the smartcard for all logins (2fa?) which is not what
2
# tried in sddm and sddm-greeter. greeter didn't do anything#could not login with sddm when setting poldi#this freezes on sddm#auth sufficient pam_poldi.sopam-anyauth is a tool I built for authenticating against data in a database. It could be used to authenticate with smartcard. This would be a quick and dirty solution if poldi doesn't work. In theory they would do the same thing.
Using a certificate to authenticate is a less common but industry standard. This requires a certificate authority to mange the certs. The cert can be placed on the smartcard. Given the overhead for all of this it is unlikely I will pursue this approch further.
https://help.ubuntu.com/community/CommonAccessCard (not using certificate with smartcard?) this doesn't work for me
configuring sddm to use pam_pkcs11 and looking at /var/log/syslog I see that the token is recognized as a government issued CAC but I don't know what to put in /etc/pam_pkcs11/subject_mapping.
sudo apt-get install libssl-dev libpam0g-dev pkg-config libpcsclite-dev libcackey
sudo apt-get install libssl-dev libpam0g-dev pkg-config libpcsclite-dev
sudo ln -s /usr/lib/pkcs11/libcackey.so .
sudo echo "/C=US/O=U.S. Government/OU=DoD/OU=PKI/OU=CONTRACTOR-or-USN-or-USMC-etc/CN=LASTNAME.FIRSTNAME.MIDDLENAME.DODID -> local_username" > /etc/pam_pkcs11/subject_mapping
Dont seem to have pam_pkcs11.conf so I pulled an example and started with it. I'll post mine when it works.
#/etc/pam_pkcs11/pam_pkcs11.conf
...
found an interesting post for redhat that includes a line for pam config that might help https://bugzilla.redhat.com/show_bug.cgi?id=1358039
auth required pam_env.so
auth [success=3 default=ignore] pam_succeed_if.so service notin login:gdm:xdm:kdm:xscreensaver:gnome-screensaver:kscreensaver:sudo quiet use_uid
auth [success=ok authinfo_unavail=2 ignore=2 default=die] pam_pkcs11.so card_only
auth optional pam_krb5.so use_first_pass no_subsequent_prompt preauth_options=X509_user_identity=PKCS11:/usr/lib64/pkcs11/libcoolkeypk11.so
auth sufficient pam_permit.so
auth sufficient pam_fprintd.so
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 500 quiet
auth sufficient pam_krb5.so use_first_pass
auth required pam_deny.so
this is for kerberos but it might be enough to parse out the kde setup and maybe even kdm...