Bug 1979256

Summary: clevis added LUKS2 keyslots does not have to use LUKS2 pbkdf defaults for new keyslots.
Product: Red Hat Enterprise Linux 8 Reporter: Renaud Métrich <rmetrich>
Component: clevisAssignee: Sergio Correia <scorreia>
Status: CLOSED ERRATA QA Contact: Martin Zelený <mzeleny>
Severity: medium Docs Contact:
Priority: medium    
Version: 8.4CC: agk, dapospis, guazhang, jbrassow, mzeleny, okozina, prajnoha, rsroka, scorreia
Target Milestone: rcKeywords: Triaged
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: clevis-15-6.el8 Doc Type: No Doc Update
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2022-05-10 13:52:43 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Kickstart
none
Grub config to install the VM
none
libvirt "default" network XML to be able to UEFI+HTTP boot none

Description Renaud Métrich 2021-07-05 12:14:23 UTC
Created attachment 1798118 [details]
Kickstart

Created attachment 1798118 [details]
Kickstart

Description of problem:

Trying to install a QEMU/KVM with 2GB of memory (which should be enough for RHEL8.4) with Luks + TPM2 unlocking, it appears that installing through the network is not possible: cryptsetup called by "clevis luks bind" gets killed by OOM killer:
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
# chroot /mnt/sysimage 
# clevis luks bind -f -k - -d /dev/vda3 tpm2 '{"pcr_ids":"7"}' <<< "temppass"
Warning: Value 512 is outside of the allowed entropy range, adjusting it.
/bin/clevis-luks-bind: line 198: 54461 Killed                  cryptsetup luksAddKey --key-file <(echo -n "${existing_key}") "$DEV"
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

OOM-Kill:
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
Jul 05 11:58:19 vm-tpm84 kernel: Out of memory: Killed process 54461 (cryptsetup) total-vm:1148728kB, anon-rss:724452kB, file-rss:13920kB, shmem-rss:0kB, UID:0 pgtables:1600kB oom_score_adj:0
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

Initially I though about some leak, but executing under Valgrind works for some reason, as if less memory was getting used (or valgrind allocates differently).

Booting with 4GB works, it seems cryptsetup uses ~1GB RSS at some point in time.


Version-Release number of selected component (if applicable):

cryptsetup-2.3.3-4.el8.x86_64


How reproducible:

Always

Steps to Reproduce:

1. Boot a UEFI VM with 2GB over the network (UEFI+HTTP boot), with TPM2 emulated device

  RHEL8.4 DVD mounted on http://192.168.122.1/rhel84 (/var/www/html/rhel84 on my HTTP server)


  UEFI+HTTP bootloader available as http://192.168.122.1/EFI/rhel84/:
  -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
  # mkdir -p /var/www/html/EFI/rhel84
  # cp /var/www/html/rhel84/EFI/BOOT/* /var/www/html/EFI/rhel84/
  -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

  Edit /var/www/html/EFI/rhel84/grub.cfg to specify the boot params for the VM (attached for convenience)

  libvirt "default" network configuration to UEFI+HTTP boot (path to BOOTX64: http://192.168.122.1/EFI/rhel84/BOOTX64.EFI):
  -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
  <network xmlns:dnsmasq='http://libvirt.org/schemas/network/dnsmasq/1.0' connections='1'>
  <name>default</name>
  <uuid>e2d07733-03c4-448c-a9b1-5b192f7010a9</uuid>
  <forward mode='nat'>
    <nat>
      <port start='1024' end='65535'/>
    </nat>
  </forward>
  <bridge name='virbr0' stp='on' delay='0'/>
  <mac address='52:54:00:5a:ef:0d'/>
  <domain name='libvirt' localOnly='yes'/>
  <ip address='192.168.122.1' netmask='255.255.255.0'/>
  <dnsmasq:options>
    <dnsmasq:option value='dhcp-vendorclass=set:efi-http,HTTPClient:Arch:00016'/>
    <dnsmasq:option value='dhcp-option-force=tag:efi-http,60,HTTPClient'/>
    <dnsmasq:option value='dhcp-boot=tag:efi-http,&quot;http://192.168.122.1/EFI/rhel84/BOOTX64.EFI&quot;'/>
  </dnsmasq:options>
  </network>
  -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

  tpm8.4 XML attached for convenience

  kickstart "tpm8.ks" attached for convenience (root password: "redhat")


Actual results:

"clevis luks bind" aborts.


Expected results:

Success

Comment 1 Renaud Métrich 2021-07-05 12:16:24 UTC
Created attachment 1798120 [details]
Grub config to install the VM

Comment 2 Renaud Métrich 2021-07-05 12:17:44 UTC
Created attachment 1798122 [details]
libvirt "default" network XML to be able to UEFI+HTTP boot

Comment 3 Ondrej Kozina 2021-07-08 09:02:50 UTC
Cryptsetup simply can not change defaults here. The utility does not know the use case for the keyslot and it aims to achieve highest security possible for the user by default.

cryptsetup luksAddKey action aims to use half system memory with argon2 pbkdf (or 1GiB whatever hits first). But yes, if the system is under memory pressure it leads to oom. Please mind that memory cost is core feature of memory hard pbkdf function. It serves to protect LUKS2 passphrases against parallel attack performed on systems with high parallel core count but expensive memory (GPUs).

I see following posibilities:

a) you can lower memory cost of pbkdf by adding --pbkdf-memory limit in KiB
b) you can switch to back to pbkdf2 with --pbkdf pbkdf2

this needs to be verified by clevis/tang maintainer:
c) Maybe clevis can safely switch to minimal pbkdf values since I expect new passphrase provided by clevis during luksAddKey action is in fact cryptographicly strong key (key generated with high entropy).

Is that correct Sergio?

example for c) would look like this:

cryptsetup luksAddKey cryptsetup luksAddKey --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --key-file <(echo -n "${existing_key}") "$DEV"

But please bear in mind that c) is safe only if the 'new_passphrase' is generated using approved random key generator. I don't know clevis/tang internals good enough to verify that.

Comment 4 Ondrej Kozina 2021-07-08 09:05:35 UTC
Systemd does something very similar when it's aware new passphrase has key generated with high entropy

Comment 5 Sergio Correia 2021-07-08 12:13:57 UTC
(In reply to Ondrej Kozina from comment #3)

[...]

> 
> this needs to be verified by clevis/tang maintainer:
> c) Maybe clevis can safely switch to minimal pbkdf values since I expect new
> passphrase provided by clevis during luksAddKey action is in fact
> cryptographicly strong key (key generated with high entropy).
> 
> Is that correct Sergio?
> 

Yes -- the key is currently generated with pwmake and 256 bits of entropy.

> example for c) would look like this:
> 
> cryptsetup luksAddKey cryptsetup luksAddKey --pbkdf pbkdf2
> --pbkdf-force-iterations 1000 --key-file <(echo -n "${existing_key}") "$DEV"
> 

Renaud: could you check if something like this helps?

> But please bear in mind that c) is safe only if the 'new_passphrase' is
> generated using approved random key generator. I don't know clevis/tang
> internals good enough to verify that.

Comment 6 Ondrej Kozina 2021-07-08 12:24:33 UTC
(In reply to Sergio Correia from comment #5)
> (In reply to Ondrej Kozina from comment #3)
> 
> [...]
> 
> > 
> > this needs to be verified by clevis/tang maintainer:
> > c) Maybe clevis can safely switch to minimal pbkdf values since I expect new
> > passphrase provided by clevis during luksAddKey action is in fact
> > cryptographicly strong key (key generated with high entropy).
> > 
> > Is that correct Sergio?
> > 
> 
> Yes -- the key is currently generated with pwmake and 256 bits of entropy.
> 
> > example for c) would look like this:
> > 
> > cryptsetup luksAddKey cryptsetup luksAddKey --pbkdf pbkdf2
> > --pbkdf-force-iterations 1000 --key-file <(echo -n "${existing_key}") "$DEV"
> > 
> 
> Renaud: could you check if something like this helps?

I had a typo in the example, use this one instead:

cryptsetup luksAddKey --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --key-file <(echo -n "${existing_key}") "$DEV""

Comment 7 Renaud Métrich 2021-07-08 13:35:51 UTC
I can confirm this works fine on a 2GB system which has not much free during installation:

[anaconda root@vm-tpm84 ~]# free
              total        used        free      shared  buff/cache   available
Mem:        2005084     1087568       70380      388900      847136      364996
Swap:       4102228      723456     3378772

Comment 8 Ondrej Kozina 2021-07-08 15:07:47 UTC
as per comment #7 I'm moving it clevis/tang. This change seems reasonable and it would also speed up clevis/tang based device activations with safe clevis generated LUKS2 passphrases.

Comment 13 Renaud Métrich 2022-01-07 08:57:27 UTC
I don't manage to reproduce on my 8.4 VMs anymore, but now I have some issue with the TPM, could be the reason.

Comment 18 errata-xmlrpc 2022-05-10 13:52:43 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (clevis bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2022:1857