<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="4.1.1">Jekyll</generator><link href="https://microos.opensuse.org/feed.xml" rel="self" type="application/atom+xml" /><link href="https://microos.opensuse.org/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-04-24T13:25:03+00:00</updated><id>https://microos.opensuse.org/feed.xml</id><title type="html">openSUSE MicroOS</title><subtitle>Micro Service OS built by the openSUSE community</subtitle><entry><title type="html">Managing System Extensions with sysextmgrcli</title><link href="https://microos.opensuse.org/blog/2026-04-23-sysextmgr/" rel="alternate" type="text/html" title="Managing System Extensions with sysextmgrcli" /><published>2026-04-23T15:27:00+00:00</published><updated>2026-04-23T15:27:00+00:00</updated><id>https://microos.opensuse.org/blog/sysextmgr</id><content type="html" xml:base="https://microos.opensuse.org/blog/2026-04-23-sysextmgr/">&lt;h1 id=&quot;managing-system-extensions-on-opensuse-microos-with-sysextmgrcli&quot;&gt;Managing System Extensions on openSUSE MicroOS with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysextmgrcli&lt;/code&gt;&lt;/h1&gt;

&lt;p&gt;If you are running &lt;strong&gt;openSUSE MicroOS&lt;/strong&gt;, you already know the drill: the root filesystem is read-only,
and transactional updates are the law of the land.
But what happens when you need to add software or system extensions without rebooting or messing with
your base OS layers?
E.g. You need strace or gdb to debug a running application, but a reboot to install this tools would
change the situation.&lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;System Extensions (sysext images)&lt;/strong&gt; and the utility designed to make them manageable: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysextmgrcli&lt;/code&gt;.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;what-is-sysextmgrcli&quot;&gt;What is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysextmgrcli&lt;/code&gt;?&lt;/h2&gt;

&lt;p&gt;At its core, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysextmgrcli&lt;/code&gt; is a command-line client for managing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-sysext&lt;/code&gt; images and has been written
by Thorsten Kukuk. It is designed specifically to play nice with the atomic nature of MicroOS.&lt;/p&gt;

&lt;p&gt;Instead of forcing you to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sudo&lt;/code&gt; for every query, it talks to a background daemon (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysextmgrd&lt;/code&gt;) via
&lt;strong&gt;Varlink&lt;/strong&gt;. This architecture allows unprivileged users to list existing system extension images without
needing root permissions, while the daemon handles the heavy lifting of downloads and verification via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-pull&lt;/code&gt;.
For security reasons root provileges are still required for installing or updating sysext images.&lt;/p&gt;

&lt;h2 id=&quot;the-architecture-smart-snapshots&quot;&gt;The Architecture: Smart Snapshots&lt;/h2&gt;

&lt;p&gt;One of the cleverest things about &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysextmgrcli&lt;/code&gt; is how it handles storage to be efficient and “rollback-safe”:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;/var/lib/sysext-store&lt;/strong&gt;: This is where the actual image files live. Since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/var&lt;/code&gt; is a separate subvolume
shared across all Btrfs snapshots, you only store the image once, saving disk space. If you have no network available,
that’s the location for storing offline or even own build sysext images via e.g. an USB device.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;/etc/extensions&lt;/strong&gt;: This directory contains &lt;strong&gt;symlinks&lt;/strong&gt; to the images in the store. Because &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt; is part of
your root snapshot, the extensions are tied to your current system state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why does this matter?&lt;/strong&gt; If you perform a system rollback, your symlinks roll back too. This ensures the active
sysext images always match the OS version you are currently booted into.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;essential-commands&quot;&gt;Essential Commands&lt;/h2&gt;

&lt;p&gt;Getting started is straightforward. Here are the primary commands you’ll use to manage your extensions:&lt;/p&gt;

&lt;h3 id=&quot;1-listing-and-checking-images&quot;&gt;1. Listing and Checking Images&lt;/h3&gt;
&lt;p&gt;Want to see what’s available or if your images are compatible with your current OS version?&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# List all images and report compatibility
sysextmgrcli list

# Check for updates and verify compatibility
sysextmgrcli check
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;2-installing-new-extensions&quot;&gt;2. Installing New Extensions&lt;/h3&gt;
&lt;p&gt;You can install by providing a name and a source URL. The tool automatically handles SHA256 verification and
checks if it fits your OS.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# --url is optional (default: https://download.opensuse.org/tumbleweed/appliances/ )
sysextmgrcli install [NAME] --url [https://your-image-repo.com](https://your-image-repo.com)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;3-maintenance-and-updates&quot;&gt;3. Maintenance and Updates&lt;/h3&gt;
&lt;p&gt;Updates are handled by comparing local files against remote manifests. If a newer version matches your current snapshot, it gets pulled down and symlinked.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# Update existing images to the latest compatible versions
sysextmgrcli update

# Clean up: Remove images in the store that are no longer referenced by any snapshot
sysextmgrcli cleanup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-activation-catch&quot;&gt;The “Activation” Catch&lt;/h2&gt;
&lt;p&gt;It is important to note that sysextmgrcli is a manager, not an activator. It handles the logistics: downloading, version checking, and symlinking. To actually “plug in” the extensions to your running system, you still use standard systemd-sysext commands:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Manual activation: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-sysext merge&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Manual deactivation: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-sysext unmerge&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Enable at boot: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl enable systemd-sysext.service&lt;/code&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;available-default-system-extention-sysext-images&quot;&gt;Available default system extention (sysext) images:&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;debug (babeltrace, gdb, ltrace, strace, traceroute)&lt;/li&gt;
  &lt;li&gt;gcc (cpp, gcc, make, patch)&lt;/li&gt;
  &lt;li&gt;git (git, git-core)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;

&lt;h3 id=&quot;you-need-git-on-your-opensuse-microos-&quot;&gt;You need &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; on your &lt;strong&gt;openSUSE MicroOS&lt;/strong&gt; ?&lt;/h3&gt;
&lt;p&gt;Just call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysextmgrcli install git ; systemd-sysext merge&lt;/code&gt; and use it…&lt;/p&gt;

&lt;h3 id=&quot;you-do-not-need-git-anymore-on-your-system-&quot;&gt;You do not need ‘git’ anymore on your system ?&lt;/h3&gt;
&lt;p&gt;Just call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-sysext unmerge&lt;/code&gt; and it is not available anymore…&lt;/p&gt;

&lt;p&gt;sysextmgrcli bridges the gap between static immutable infrastructure and the need for flexible system additions. By leveraging the Btrfs directory structure of MicroOS, it ensures your system remains clean, version-synced, and easy to manage.&lt;/p&gt;</content><author><name>Stefan Schubert</name></author><category term="blog" /><summary type="html">Managing System Extensions on openSUSE MicroOS with sysextmgrcli</summary></entry><entry><title type="html">YaST2 support for Full Disk Encryption with TPM2</title><link href="https://microos.opensuse.org/blog/2025-08-11-fde-tpm2-yast2/" rel="alternate" type="text/html" title="YaST2 support for Full Disk Encryption with TPM2" /><published>2025-08-11T12:07:00+00:00</published><updated>2025-08-11T12:07:00+00:00</updated><id>https://microos.opensuse.org/blog/fde-tpm2-yast2</id><content type="html" xml:base="https://microos.opensuse.org/blog/2025-08-11-fde-tpm2-yast2/">&lt;h2 id=&quot;intro&quot;&gt;Intro&lt;/h2&gt;

&lt;p&gt;The openSUSE MicroOS installer (YaST2) supports since snapshot 20250809 Full Disk Encryption (FDE) secured by a TPM2 chip and &lt;a href=&quot;https://en.opensuse.org/Portal:MicroOS/RemoteAttestation#Measured_boot&quot;&gt;measured boot&lt;/a&gt; or a FIDO2 key.&lt;/p&gt;

&lt;p&gt;Since quite some time the openSUSE project provides already images with Full Disk Encryption and TPM2 (e.g. &lt;a href=&quot;https://download.opensuse.org/tumbleweed/appliances/openSUSE-MicroOS.x86_64-kvm-and-xen-sdboot.qcow2&quot;&gt;openSUSE-MicroOS.x86_64-kvm-and-xen-sdboot.qcow2&lt;/a&gt; or &lt;a href=&quot;https://download.opensuse.org/tumbleweed/appliances/openSUSE-MicroOS.x86_64-kvm-and-xen-grub-bls.qcow2&quot;&gt;openSUSE-MicroOS.x86_64-kvm-and-xen-grub-bls.qcow2&lt;/a&gt; for virtualized environments and there is a &lt;a href=&quot;https://microos.opensuse.org/blog/2024-09-03-quickstart-fde-yast2/&quot;&gt;bog&lt;/a&gt; describing how to setup such a system with YaST2.&lt;/p&gt;

&lt;p&gt;Now the next step is done: YaST2 supports setting up FDE+TPM2 for openSUSE MicroOS, so this feature can be enabled in an easy way during installation.&lt;/p&gt;

&lt;p&gt;This requires a bootloader following the &lt;a href=&quot;https://uapi-group.org/specifications/specs/boot_loader_specification/&quot;&gt;Boot Loader Specification (BLS)&lt;/a&gt;. Available are grub2-bls and systemd-boot. For openSUSE MicroOS we decided to make
systemd-boot the default bootloader.&lt;/p&gt;

&lt;h2 id=&quot;hardware-requirement&quot;&gt;Hardware Requirement:&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;UEFI Firmware&lt;/li&gt;
  &lt;li&gt;TPM2 Chip or FIDO2 key which supports the hmac-secret extension&lt;/li&gt;
  &lt;li&gt;4GB Memory&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;installation-of-opensuse-microos&quot;&gt;Installation of openSUSE MicroOS&lt;/h2&gt;

&lt;h3 id=&quot;boot-installation-media&quot;&gt;Boot installation media&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;Follow the workflow until “Installation Settings”&lt;/li&gt;
  &lt;li&gt;Installation Settings:
    &lt;ul&gt;
      &lt;li&gt;Partitioning: &lt;img src=&quot;/assets/images/yast2-fde-tpm2/YaST2-MicroOS-FDE+TPM2-1.png&quot; alt=&quot;installation-settings&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;Select “Guided Setup”, keep the defaults until the “Partitioning Scheme” screen. &lt;img src=&quot;/assets/images/yast2-fde-tpm2/YaST2-MicroOS-FDE+TPM2-2.png&quot; alt=&quot;suggested-partitioning&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;“Enable Disk Encryption” and enter the password. The password will be the recovery key. &lt;img src=&quot;/assets/images/yast2-fde-tpm2/YaST2-MicroOS-FDE+TPM2-5.png&quot; alt=&quot;partitioning-scheme&quot; /&gt;&lt;/li&gt;
      &lt;li&gt;Accept changes &lt;img src=&quot;/assets/images/yast2-fde-tpm2/YaST2-MicroOS-FDE+TPM2-6.png&quot; alt=&quot;accept-changes&quot; /&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Finish Installation&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;finish-fde-setup&quot;&gt;Finish FDE Setup&lt;/h3&gt;

&lt;p&gt;Boot the new system&lt;/p&gt;

&lt;h2 id=&quot;re-enrollment&quot;&gt;Re-enrollment&lt;/h2&gt;
&lt;p&gt;If the prediction system fails, a new policy must be created for the new measurements to replace the policy stored in the TPM2.&lt;/p&gt;

&lt;p&gt;With the recovery PIN (the password for FDE):&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  # sdbootutil --ask-pin update-predictions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h2&gt;

&lt;p&gt;The next step will be to make FDE+TPM2 the default for MicroOS.&lt;/p&gt;

&lt;h2 id=&quot;further-documentation&quot;&gt;Further Documentation&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.opensuse.org/Portal:MicroOS/FDE&quot;&gt;MicroOS FDE&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://microos.opensuse.org/blog/2024-09-03-quickstart-fde-yast2/&quot;&gt;Quickstart in Full Disk Encryption with TPM and YaST2&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://microos.opensuse.org/blog/2023-12-20-sdboot-fde/&quot;&gt;Systemd-boot and Full Disk Encryption with TPM and FIDO2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Thorsten Kukuk</name></author><category term="blog" /><summary type="html">Intro</summary></entry><entry><title type="html">zypper single transaction mode now default</title><link href="https://microos.opensuse.org/blog/2025-07-29-switch-to-single-rpmtrans/" rel="alternate" type="text/html" title="zypper single transaction mode now default" /><published>2025-07-29T08:48:00+00:00</published><updated>2025-07-29T08:48:00+00:00</updated><id>https://microos.opensuse.org/blog/switch-to-single-rpmtrans</id><content type="html" xml:base="https://microos.opensuse.org/blog/2025-07-29-switch-to-single-rpmtrans/">&lt;h2 id=&quot;default-zypper-backend&quot;&gt;Default zypper backend&lt;/h2&gt;

&lt;p&gt;Over the weekend we switched the default zypper backend from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;classic_rpmtrans&lt;/code&gt; to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;single_rpmtrans&lt;/code&gt; backend in openSUSE MicroOS.&lt;/p&gt;

&lt;p&gt;Anyone who has followed the factory mailing list or openSUSE’s bugzilla over the last two years has probably noticed the regular discussions about faulty updates, mainly because libraries were updated too late. The result was that tools from %pre/%post scripts did not work and in the worst case made the system unbootable.
Traditionally, zypper executes the rpm command separately for each operation in a transaction. The advantage is that with large updates and a small root partition, zypper can download the packages one after the other, making the update possible in the first place.
One of the disadvantages, however, is that the update process is much slower with a large number of packages. And not only that, zypper also has to save the posttrans scripts and execute them manually at the end. This means that the update process runs differently than when all RPMs are updated in one with RPM.
Therefore, the zypper developers have implemented a new backend that executes all operations in a single transaction with librpm. However, for various reasons this is not yet the standard and so there are still bug reports about faulty bootloader configurations or problems updating libopenssl when using hardware-optimized libraries.&lt;/p&gt;

&lt;h2 id=&quot;how-is-this-implemented&quot;&gt;How is this implemented?&lt;/h2&gt;

&lt;p&gt;On the command line and for systemd units, the environment variable ZYPP_SINGLE_RPMTRANS=1 is now set globally, which should cover most cases on MicroOS.&lt;/p&gt;

&lt;p&gt;If there are still situations where zypper uses the old classic backend, please report this via bugzilla.&lt;/p&gt;

&lt;h2 id=&quot;what-does-this-mean-for-the-users&quot;&gt;What does this mean for the users?&lt;/h2&gt;

&lt;p&gt;Hopefully: &lt;strong&gt;nothing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Or better: the update problems are gone. If you still see problems with packages, please report them via bugzilla so that we can fix them.&lt;/p&gt;</content><author><name>Thorsten Kukuk</name></author><category term="blog" /><summary type="html">Default zypper backend</summary></entry><entry><title type="html">Presenting GRUB2 BLS</title><link href="https://microos.opensuse.org/blog/2025-07-18-fde-rogue-devices/" rel="alternate" type="text/html" title="Presenting GRUB2 BLS" /><published>2025-07-18T15:00:00+00:00</published><updated>2025-07-18T15:00:00+00:00</updated><id>https://microos.opensuse.org/blog/fde-rogue-devices</id><content type="html" xml:base="https://microos.opensuse.org/blog/2025-07-18-fde-rogue-devices/">&lt;h1 id=&quot;protecting-against-rogue-devices-in-opensuse-with-full-disk-encryption&quot;&gt;Protecting against rogue devices in openSUSE with Full Disk Encryption&lt;/h1&gt;

&lt;p&gt;openSUSE have now multiple ways to configure a Full Disk Encryption
(FDE) installation.  A very secure and easy way (YaST2) of doing this
is via user space tools, as we described multiple times (like
&lt;a href=&quot;https://news.opensuse.org/2023/12/20/systemd-fde/&quot;&gt;here&lt;/a&gt;, &lt;a href=&quot;https://microos.opensuse.org/blog/2023-12-20-sdboot-fde/&quot;&gt;here&lt;/a&gt;, or &lt;a href=&quot;https://news.opensuse.org/2024/09/20/quickstart-fde-yast2/&quot;&gt;here&lt;/a&gt;).  This solution is based on the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; tool-set like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptenroll&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-pcrlock&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptsetup&lt;/code&gt;, among other, orchestrated by the in-house
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil&lt;/code&gt; script.&lt;/p&gt;

&lt;p&gt;One of the main advantages of using this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; approach is the
possibility of integrating multiple authentication methods.  Together
with the traditional password, asked at boot time during the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;
stage, we can now unlock the system using a certificate, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt;, or
a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIDO2&lt;/code&gt; key.  We can mix some of them creating multiple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt; key
slots, and use, for example, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; to unlock the device in a
unattended fashion and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIDO2&lt;/code&gt; key as a recovery mechanism.&lt;/p&gt;

&lt;p&gt;Honestly, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt;, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2+PIN&lt;/code&gt; variation, are the most
relevant ones for the user.  As described in the other posts, the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; is a (some times virtual) device that can attest the health of
our system using a mechanism known as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;measured boot&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The tl; dr version of this is that each stage of the boot process,
starting from the firmware, will load and “measure” the next stage
before delegating the execution on it.  For example, this means that
there is a moment in the latest stages of the boot process where the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UEFI&lt;/code&gt; firmware will load from the disk the boot loader into memory.
This can be the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shim&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grub2-bls&lt;/code&gt;.  It will
calculate a hash value (usually &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SHA256&lt;/code&gt;) and will command to the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; an “extend” operation for one of the internal register (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The extension is a cryptographic computation that is very easy to
calculate, but impossible to replicate.  It is done to one of those
internal registers (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;) and consist of calculating the hash (again
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SHA256&lt;/code&gt;) of the old value of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; together with the hash of the
component that we are measuring.  This new value will replace the
current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; value, as is the only way to change those registers.
The security property resides in that it is cryptographically
impossible to force the write of a desired value on one of those
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s, but very easy to calculate the final value.&lt;/p&gt;

&lt;p&gt;So this means that if all the components of the boot chain process are
measured (all the stages in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UEFI&lt;/code&gt; firmware, the firmware
configuration, the boot loader, the command line, the kernel and even
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;), the final &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s values can be compared with our
expectations, and discover if the system has been booted with a good
known software and configuration, allowing us to instantly known if
some component in the boot chain has been hacked or modified with out
consent.&lt;/p&gt;

&lt;p&gt;That is a powerful property to have, but what is more interesting is
that we can have secrets that can only be open in case that we are in
one of those good or recognized states.  We can, for example, cipher
(seal) the key that open an encrypted disk using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt;, together
with a policy that will decipher (unseal) the same key only, and only
if we are using the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; values are on a list of
expected ones.  Those policies can be very complicated, and can
include extra passwords, certificates or other checks that will be
validated before the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; can unseal the key.&lt;/p&gt;

&lt;p&gt;With a mechanism like this in place, thanks to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; tools, we
can now avoid entering the password to unlock the encrypted disk if
the system is in a healthy state.  Healthy in the sense that we
cryptographically guarantee that the code and configurations used
during the boot process are the expected one, and no one entered
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;init=/bin/bash&lt;/code&gt; in our kernel command line, or replaced the kernel or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; with a vulnerable one, for example.&lt;/p&gt;

&lt;p&gt;With the integration that we made of this model in openSUSE, we can
make updates of the system, including the boot loader or the kernel,
and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil&lt;/code&gt; will transparently generate new predictions of
expected &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; values that are now considered safe.  This imply an
update of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; policy, that will be taken into consideration for
the next boot, so the automatic unlock will succeed.  If something
goes wrong and the expected &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; values are not meet, the user will
need to enter the password that is stored in a different &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt; key
slot to open the device, to audit the system and validate it.&lt;/p&gt;

&lt;h2 id=&quot;the-fault-in-the-design&quot;&gt;The fault in the design&lt;/h2&gt;

&lt;p&gt;Using a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; as described before is a clear increase in the security
level, but it is not the final answer.  Security is always asymptotic
approximation.&lt;/p&gt;

&lt;p&gt;Some years ago a physical &lt;a href=&quot;https://cybersecurity.bureauveritas.com/blog/tpm-sniffing-attacks-against-non-bitlocker-targets&quot;&gt;attack&lt;/a&gt; was described for the Windows
BitLocker FDE solution.  BitLocker is also using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; in a
similar way that was described before, but was not using encrypted
session to communicate with the device.  Intercepting the SPI bus was
shown possible to recover the password that unlock the disk.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; learned from that and used encrypted sessions early, but
this attack can also be avoided if the policy used to unseal the key
was also demanding a PIN or password that must be entered by the user.
Now the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; can only unseal the secret if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s are in the
correct state and the provided password is the correct one.  Should be
noted that AFAIK the SPI sniffing can &lt;a href=&quot;https://www.securitum.com/extracting_clevisbitlocker_secrets_from_tpm_traffic_.html&quot;&gt;work&lt;/a&gt; with Clevis.&lt;/p&gt;

&lt;p&gt;But more recently a second &lt;a href=&quot;https://oddlama.org/blog/bypassing-disk-encryption-with-tpm2-unlock/&quot;&gt;attack&lt;/a&gt; was made public that fully
affect the original proposal, and does not requires the sophistication
of the original one.  (Disclosure: the attack was also internally
described independently months before and some counter measurements
was put in place much early)&lt;/p&gt;

&lt;p&gt;The article describes how that attack can be done checking in the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; the filesystem UUID used to mount the encrypted device.  This
information is inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/crypttab&lt;/code&gt; stored in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;, that
will do something like this:&lt;/p&gt;

&lt;p&gt;systemd-cryptsetup attach cr_root /dev/disk/by-uuid/$UUID ‘none’ ‘tpm2-device=auto’&lt;/p&gt;

&lt;p&gt;If the expected firmware, configuration files, kernel and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; are
used during the boot process then the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt;’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s registers will
have values that match the policy that unlock the device and the
sealed key can be now unsealed by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt;, the disk will be
unlocked, the switch root will succeed and the boot process will
continue in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rootfs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But what if the original drive is replaced by one that has the same
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UUID&lt;/code&gt; (it is a public information after all) that is also encrypted?
Then the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s will be in the same correct state.  Note that in
measure boot is the previous stage the one that measures the next one
before delegating the execution.  Then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptsetup&lt;/code&gt; will try
to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; to unlock the device using the key successfully
unsealed by the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; and … will fail to open it, of course.  The
rogue device maybe have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; key slot in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt; header, but
for sure cannot be open with this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; nor with the secret password.&lt;/p&gt;

&lt;p&gt;In this situation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptsetup&lt;/code&gt; will ask for the password to
unlock the device, and the attacker can enter one that this time will
open the rogue device.  The switch root will happen but now it will
continue the boot process in the fake &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rootfs&lt;/code&gt;, and a program stored
there can make questions to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt;, that still contains the good
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; values.  One of the questions can be the unseal of the secret
key using the current policy.  And this time (as was done before), the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; will agree to deliver the secret to the bad program.  Game
over.&lt;/p&gt;

&lt;p&gt;There are solutions for this attack, of course.&lt;/p&gt;

&lt;p&gt;One is again to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2+PIN&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt;, the same solution
for the sniffing attack.  In this case the first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptsetup&lt;/code&gt;
call will fail and a password will be asked to unlock the device.  But
now the bad program cannot ask to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; to unseal the device
using the current policy.  The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; values will match, but the policy
also requires the enter of a secret PIN or password known by the real
user, and without it the unseal will fail and the key will be keep
safe.&lt;/p&gt;

&lt;p&gt;Another solution is somehow invalidate the policy, extending some of
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s involved before the switch root, so the policy cannot be
applied anymore after that.  This can be done automatically by
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptsetup&lt;/code&gt; using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;measure-pcr=yes&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/crypttab&lt;/code&gt;.
With this option &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR15&lt;/code&gt; will be extended using the volume key, a
secret that can only be extracted knowing some of the device keys.
For this solution to work, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR15&lt;/code&gt; needs to be included in the current
policy, with an expected value of 0x000..00, the default one.  Once
the rogue device is open by the hacker provided password, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR15&lt;/code&gt; will
be automatically extended and the value will be different from
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x000..00&lt;/code&gt;, invalidating the policy before the switch root.&lt;/p&gt;

&lt;p&gt;That is a good solution, but not for us.  In the daily situation the
user will need to update the system, and a new policy needs to be
calculated to replace the old one (for example when the kernel is
updated).  Because with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-pcrlock&lt;/code&gt; the policy is stored in the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; in one of the Non Volatile RAM slots (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NVIndex&lt;/code&gt;), we need to
protect it somehow, so it cannot be replaced by other process.  For
that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; is storing a secret key (recovery PIN) in a different
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NVIndex&lt;/code&gt; that is sealed by the same policy!  If the key cannot be
automatically recovered, because the policy does not apply anymore,
then the recovery PIN will be asked to the user, making the update
process a bit unpleasant if the policy is always invalidated.&lt;/p&gt;

&lt;p&gt;Finally, another way to address the issue is to stop the boot process
if we detect that the device is not the expected one.  We can think of
a new service, living in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; that is executed in the very last
moment, just before the switch root, that can stop the boot process
(maybe halting the system) if the device that stores the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rootfs&lt;/code&gt; is
not the expected one.&lt;/p&gt;

&lt;p&gt;For this, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR15&lt;/code&gt; is still a good solution.  It contains the
measurement of a secret (volume key) that can only be known by the
real user, and cannot be replicated by the attacker.  Ideally we can
create a prediction for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR15&lt;/code&gt; and make this service to compare the
effective value with the expected one, and if they are different then
it can stop the boot process.&lt;/p&gt;

&lt;p&gt;This is what the &lt;a href=&quot;https://github.com/openSUSE/sdbootutil/blob/main/measure-pcr-validator.sh&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;measure-pcr-validator&lt;/code&gt;&lt;/a&gt; service from
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil&lt;/code&gt; is doing.  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil&lt;/code&gt; first generates a prediction for
all the encrypted devices that are opened during the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;, and
check that the correct tag is present in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/crypttab&lt;/code&gt;.  To be able
to access the volume key, the tool needs the root password, so this
prediction is only update when it is really necessary, like for
example when a new encrypted device is added.  This prediction is
signed by a private key stored in the host, as an extra security
measurement, but because the public key is also stored in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt; it
is honestly not adding too much.&lt;/p&gt;

&lt;p&gt;An extra service (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;measure-pcr-generator&lt;/code&gt;) will put some order on how
the encrypted devices are opened, as this order is critical to produce
a single possible &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR15&lt;/code&gt; value.  If we have one single device the
order of measurements is not relevant, but if when have three
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rootfs&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;swap&lt;/code&gt;, for example) we can have six possible
and valid different values for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR15&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The last step is that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dracut-pcr-signature&lt;/code&gt; service in the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; will import from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt; the prediction, the signature and
the public key, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;measure-pcr-validator&lt;/code&gt; can check the signature and
compare the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; value.&lt;/p&gt;

&lt;p&gt;And that is all!&lt;/p&gt;

&lt;p&gt;This approach is also kind of similar to what the new
&lt;a href=&quot;https://github.com/systemd/systemd/blob/main/man/systemd-validatefs%40.service.xml&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-validatefs&lt;/code&gt;&lt;/a&gt; is doing, but for a file system level.&lt;/p&gt;</content><author><name>Alberto Planas</name></author><category term="blog" /><summary type="html">Protecting against rogue devices in openSUSE with Full Disk Encryption</summary></entry><entry><title type="html">Presenting GRUB2 BLS</title><link href="https://microos.opensuse.org/blog/2024-10-08-grub2-bls/" rel="alternate" type="text/html" title="Presenting GRUB2 BLS" /><published>2024-10-08T12:55:00+00:00</published><updated>2024-10-08T12:55:00+00:00</updated><id>https://microos.opensuse.org/blog/grub2-bls</id><content type="html" xml:base="https://microos.opensuse.org/blog/2024-10-08-grub2-bls/">&lt;h2 id=&quot;grub2-with-bls-is-now-in-microos-and-tumbleweed&quot;&gt;GRUB2 with BLS is now in MicroOS and Tumbleweed&lt;/h2&gt;

&lt;p&gt;Recently the openSUSE project released for MicroOS and Tumbleweed a
new version of the GRUB2 package, with a new subpackage
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grub2-$ARCH-efi-bls&lt;/code&gt;.  This subpackage deliver a new EFI file,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grubbls.efi&lt;/code&gt;, that can be used as replacement of the traditional
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grub.efi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The new PE binary is a version of GRUB2 that includes a set of patches
from Fedora, that makes the bootloader follows the boot loader
specification (&lt;a href=&quot;https://uapi-group.org/specifications/specs/boot_loader_specification/&quot;&gt;BLS&lt;/a&gt;).  This will make GRUB2 understand the boot
entries from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/efi/loader/entries&lt;/code&gt;, and dynamically generate the boot
menu showed during boot time.&lt;/p&gt;

&lt;p&gt;This is really important for full disk encryption (FDE), because this
means that now we can re-use all the architecture and tools designed
for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt;.  For example, installing or updating the boot
loader can now be done with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil install&lt;/code&gt;, the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;suse-module-tools&lt;/code&gt; scriptlets will create new BLS entries when a new
kernel is installed, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tukit&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snapper&lt;/code&gt; plugins will take
care of doing the right thing when snapshots are created or removed.&lt;/p&gt;

&lt;p&gt;Reusing all those tools without change was a great win, but what is
better is that some of the quirks that the classical GRUB2 presented
when extending the event log are not present anymore.  Before this
package, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil&lt;/code&gt; needed to take ownership of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grub.conf&lt;/code&gt;
file, as this will be measured by GRUB2 &lt;em&gt;by executed lines&lt;/em&gt;.  That is
right, for each line that is read and executed by the GRUB2 parser, a
new PCR#8 will take place, and because GRUB2 support conditional as
other complex constructors, it is very hard to predict the final value
of PCR#8 without imposing a very minimal and strict &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grub.conf&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But with the new BLS subpackage this file, together with the fonts and
graphical assets for the theme, and the required modules (like
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bli.mod&lt;/code&gt;) are now included in the internal &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;squashfs&lt;/code&gt; inside the EFI
binary.  GRUB2 will not measure those internal files, without
decreasing the security guarantees, because is now the firmware the
one that measures the full EFI when the bootloader is executed during
the boot process.&lt;/p&gt;

&lt;p&gt;As today we cannot use YaST2 to install GRUB2 with BLS, but we can do
that manually very easily.  We need to make a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt;
&lt;a href=&quot;https://en.opensuse.org/Portal:MicroOS/FDE#Installation_with_YaST&quot;&gt;installation&lt;/a&gt;, replace &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LOADER_TYPE&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt; to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;grub2-bls&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysconfig/bootloader&lt;/code&gt;, install the new GRUB2 BLS package, and do &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil
install&lt;/code&gt;.  Another option is to play with one of the available images
for &lt;a href=&quot;https://download.opensuse.org/tumbleweed/appliances/openSUSE-MicroOS.x86_64-kvm-and-xen-grub-bls.qcow2&quot;&gt;MicroOS&lt;/a&gt; or &lt;a href=&quot;https://download.opensuse.org/tumbleweed/appliances/openSUSE-Tumbleweed-Minimal-VM.x86_64-kvm-and-xen-grub-bls.qcow2&quot;&gt;Tumbleweed&lt;/a&gt;.&lt;/p&gt;</content><author><name>Alberto Planas</name></author><category term="blog" /><summary type="html">GRUB2 with BLS is now in MicroOS and Tumbleweed</summary></entry><entry><title type="html">Quickstart in Full Disk Encryption with TPM and YaST2</title><link href="https://microos.opensuse.org/blog/2024-09-03-quickstart-fde-yast2/" rel="alternate" type="text/html" title="Quickstart in Full Disk Encryption with TPM and YaST2" /><published>2024-09-03T12:07:00+00:00</published><updated>2024-09-03T12:07:00+00:00</updated><id>https://microos.opensuse.org/blog/quickstart-fde-yast2</id><content type="html" xml:base="https://microos.opensuse.org/blog/2024-09-03-quickstart-fde-yast2/">&lt;h2 id=&quot;intro&quot;&gt;Intro&lt;/h2&gt;

&lt;p&gt;This is a quick start guide for Full Disk Encryption with TPM or FIDO2 and
YaST2 on openSUSE MicroOS. It focuses on the few steps to
install openSUSE MicroOS with YaST2 and using Full Disk Encryption
secured by a TPM2 chip and &lt;a href=&quot;https://en.opensuse.org/Portal:MicroOS/RemoteAttestation#Measured_boot&quot;&gt;measured boot&lt;/a&gt;
or a FIDO2 key.&lt;/p&gt;

&lt;h2 id=&quot;hardware-requirement&quot;&gt;Hardware Requirement:&lt;/h2&gt;
&lt;ul&gt;
  &lt;li&gt;UEFI Firmware&lt;/li&gt;
  &lt;li&gt;TPM2 Chip or FIDO2 key which supports the hmac-secret extension&lt;/li&gt;
  &lt;li&gt;2GB Memory&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;installation-of-opensuse-microos&quot;&gt;Installation of openSUSE MicroOS&lt;/h2&gt;

&lt;h3 id=&quot;boot-installation-media&quot;&gt;Boot installation media&lt;/h3&gt;

&lt;p&gt;To avoid the use of the YaST2 expert partitioner, the default LUKS key
derivation function from YaST2 will be used and three unused subvolumes
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/grub2/i386-pc&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/grub2/x86_64-efi&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/boot/writeable&lt;/code&gt;) will
be created.
If you are familiar with the YaST2 expert partitioner, you can remove the
three btrfs subvolumes and change the LUKS key derivation function to
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;argon2id&lt;/code&gt; already during installation.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Follow the workflow until “Installation Settings”&lt;/li&gt;
  &lt;li&gt;Installation Settings:
    &lt;ul&gt;
      &lt;li&gt;Partitioning:
        &lt;ul&gt;
          &lt;li&gt;Select “Guided Setup” and “Enable Disk Encryption”, keep the other defaults&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;Booting:
        &lt;ul&gt;
          &lt;li&gt;Change Boot Loader Type from “GRUB2 for EFI” to “Systemd Boot”, ignore “Systemd-boot support is work in progress” and continue&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Finish Installation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The order of adjusting the partitioning and changing the bootloader is important.&lt;/p&gt;

&lt;h3 id=&quot;finish-fde-setup&quot;&gt;Finish FDE Setup&lt;/h3&gt;

&lt;p&gt;Boot new system&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Enter passphrase to unlock disk during boot&lt;/li&gt;
  &lt;li&gt;Login&lt;/li&gt;
  &lt;li&gt;Enroll system:
    &lt;ul&gt;
      &lt;li&gt;With TPM2 chip: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil enroll --method tpm2&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;With FIDO2 key: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil enroll --method fido2&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Optional, but recommended:
    &lt;ul&gt;
      &lt;li&gt;Upgrade your LUKS key derivation function (do that for every encrypted device listed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/crypttab&lt;/code&gt;):
        &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;      # cryptsetup luksConvertKey /dev/vdaX --pbkdf argon2id
      # cryptsetup luksConvertKey /dev/vdaY --pbkdf argon2id
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;adjusting-kernel-boot-parameters&quot;&gt;Adjusting kernel boot parameters&lt;/h2&gt;

&lt;p&gt;The configuration file for kernel command line options is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/kernel/cmdline&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After editing this file, call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil update-all-entries&lt;/code&gt; to update the
bootloader configuration. If that option does not exist yet or does not work,
a workaround is: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil remove-all-kernels &amp;amp;&amp;amp; sdbootutil add-all-kernels&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;re-enrollment&quot;&gt;Re-enrollment&lt;/h2&gt;
&lt;p&gt;If the prediction system fails, a new policy must be created for the new measurements to replace the policy stored in the TPM2.&lt;/p&gt;

&lt;p&gt;If you have a recovery PIN:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  # sdbootutil --ask-pin update-predictions
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you don’t have the recovery PIN, you can set one with this steps:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  # sdbootutil unenroll --method=tpm2
  # PIN=&amp;lt;new recovery PIN&amp;gt; sdbootutil enroll --method=tpm2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;virtual-machines&quot;&gt;Virtual Machines&lt;/h2&gt;

&lt;p&gt;If your machine is a VM, it is recommended to remove the “0” from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FDE_SEAL_PCR_LIST&lt;/code&gt; variable in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/sysconfig/fde-tools&lt;/code&gt;. An update of the hypervisor can change PCR0. Since such an update is not visible inside the VM, the PCR values cannot be updated. As result, the disk cannot be decrypted automatically at the next boot, the recovery key needs to be entered and a manual re-enrollment is necessary.&lt;/p&gt;

&lt;h2 id=&quot;next-steps&quot;&gt;Next Steps&lt;/h2&gt;

&lt;p&gt;The next steps will be:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Support grub2-BLS (grub2 following the &lt;a href=&quot;https://uapi-group.org/specifications/specs/boot_loader_specification/&quot;&gt;Boot Loader Specification&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Add support to the installers (YaST2 and Agama)&lt;/li&gt;
  &lt;li&gt;Make this the default if a TPM2 chip is present&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any help is welcome!&lt;/p&gt;

&lt;h2 id=&quot;further-documentation&quot;&gt;Further Documentation&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.opensuse.org/Portal:MicroOS/FDE&quot;&gt;Full Disk Encryption (FDE)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.opensuse.org/Systemd-fde&quot;&gt;Systemd-fde&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://microos.opensuse.org/blog/2023-12-20-sdboot-fde/&quot;&gt;Systemd-boot and Full Disk Encryption with TPM and FIDO2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Thorsten Kukuk</name></author><category term="blog" /><summary type="html">Intro</summary></entry><entry><title type="html">Configuration files in /etc and /usr/etc</title><link href="https://microos.opensuse.org/blog/2024-08-14-usr-etc/" rel="alternate" type="text/html" title="Configuration files in /etc and /usr/etc" /><published>2024-08-14T13:28:00+00:00</published><updated>2024-08-14T13:28:00+00:00</updated><id>https://microos.opensuse.org/blog/usr-etc</id><content type="html" xml:base="https://microos.opensuse.org/blog/2024-08-14-usr-etc/">&lt;p&gt;&lt;em&gt;This blog post dates from December 2019 and was updated in August 2024.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;intro&quot;&gt;Intro&lt;/h2&gt;

&lt;p&gt;As some may have already noticed, several configuration files are no
longer in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt; but are below &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr&lt;/code&gt;. This can be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc&lt;/code&gt; or directories
below &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/lib&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/share&lt;/code&gt;, depending on upstream projects.&lt;/p&gt;

&lt;p&gt;What’s behind this move? For a better understanding, let’s first look how
configuration file updates are handled today:&lt;/p&gt;

&lt;h3 id=&quot;rpm-and-configuration-files&quot;&gt;RPM and Configuration Files&lt;/h3&gt;

&lt;p&gt;RPM has limited support for updating configuration files. In the end
this consist of two simple choices:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;modified configuration files are moved away during upgrade and the admin has to redo the changes (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rpmsave&lt;/code&gt; files).&lt;/li&gt;
  &lt;li&gt;modfied configuration files are kept and changes done by the distribution are ignored (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rpmnew&lt;/code&gt; files). In the end the service may not work or could even be insecure!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both options are not really user friendly and will most likely lead to a broken
or insecure service after an upgrade, which requires manual work by the
admin. On desktop systems or a simple server this may be tolerable, but
for big clusters this can lead to a huge amount of work.&lt;/p&gt;

&lt;p&gt;There are several alternative solutions for this like Three-Way-Diff or doing
the update interactively, but the first one does not solve the problem if
conflicting changes are occur, and the second one is no solution for fully
automated updates.&lt;/p&gt;

&lt;h3 id=&quot;atomic-updates&quot;&gt;Atomic Updates&lt;/h3&gt;

&lt;p&gt;For atomic systems another layer of complexity is added, because
different states may contain different versions of a configuration file.
So how can this happen? An atomic update is a kind of update that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Is atomic
    &lt;ul&gt;
      &lt;li&gt;The update is either fully applied or not applied at all&lt;/li&gt;
      &lt;li&gt;The update does not influence your running system&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Can be rolled back
    &lt;ul&gt;
      &lt;li&gt;If the update fails or if the update is not compatible, you can quickly restore the situation as it was before the update&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The update will be activated by rebooting into the new state, so after an
update, before the reboot, the changes done by the update are not visible. If
an admin or configuration management software changes the configuration files
in the runnung system during this time, this will create conflicts, and needs
manual interaction again.&lt;/p&gt;

&lt;h3 id=&quot;image-based-updates&quot;&gt;Image Based Updates&lt;/h3&gt;

&lt;p&gt;Image based updates here means the OS (mostly &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr&lt;/code&gt;) get’s updated as image, we don’t speak about raw disk images.
Since you deploy a new image for e.g. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr&lt;/code&gt;, there is no tool to update configuration files outside this image,
e.g. in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt;. And the image cannot overwrite &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt;, since this would mean all local host depending configuration will go lost.
So a strict separation of distribution provided configuration file and admin made changes is necessary. This is also called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hermetic-usr&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;goal&quot;&gt;Goal&lt;/h2&gt;

&lt;p&gt;The goal is to provide a concept working for most packages and their
configuration files, which makes automatic updates much easier and
robust. For that a new way to store and manage configuration files is needed.&lt;/p&gt;

&lt;h2 id=&quot;requirements-for-a-solution&quot;&gt;Requirements for a Solution&lt;/h2&gt;

&lt;p&gt;The new solution should make sure that:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;It’s visible to the admin that something got updated&lt;/li&gt;
  &lt;li&gt;It’s visible which changes the admin made&lt;/li&gt;
  &lt;li&gt;Package and admin changes should be merged automatically&lt;/li&gt;
  &lt;li&gt;There should be only one directory to search for default configuration files&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;solutions&quot;&gt;Solutions&lt;/h2&gt;

&lt;p&gt;As a longterm solution no package should install anything into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt; any
more, this directory should only contain host specific configuration files 
created during installation and changes made by the system administrator.
Packages are supposed to install their default configuration files to
another directory instead.&lt;/p&gt;

&lt;p&gt;For SUSE/openSUSE the decision was made to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc&lt;/code&gt; as the directory
for the distribution provided configuration files.&lt;/p&gt;

&lt;p&gt;For merging the package and admin configuration files there will have to be
different strategies depending on the file type; the files can be categorized
as follows:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Configuration files for applications&lt;/li&gt;
  &lt;li&gt;Configuration files for the system (network, hardware, …)&lt;/li&gt;
  &lt;li&gt;“Databases” like files (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/rpc&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/services&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/protocols&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;System and user accounts (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/passwd&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/group&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/shadow&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;application-configuration-files&quot;&gt;Application Configuration Files&lt;/h3&gt;

&lt;p&gt;For application configuration files there is already a good solution used
by systemd, which could be adopted for most applications:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc/app.conf&lt;/code&gt; is the distribution provided configuration file.&lt;/li&gt;
  &lt;li&gt;If it exists, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/app.conf&lt;/code&gt; replaces &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc/app.conf&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/app.conf.d/*.conf&lt;/code&gt; contains snippets overiding single entries from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc/app.conf&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/app.conf&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a formal &lt;a href=&quot;https://uapi-group.org/specifications/specs/configuration_files_specification/&quot;&gt;Configuration Files Specification&lt;/a&gt; by the &lt;a href=&quot;https://uapi-group.org/&quot;&gt;UAPI Group&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The workflow for the application to load the configuration file would be:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Application looks for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/app.conf&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;If this file does not exist, load &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc/app.conf&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Look for overides in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/app.conf.d&lt;/code&gt; and merge them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Examples,
“Overriding vendor settings” for more details and examples.
A C library which provides a simple interface and implements above loading
mechanism transparently for the application is &lt;a href=&quot;https://github.com/openSUSE/libeconf&quot;&gt;libeconf&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Depending on the configuration file format above patterns may not work for
all applications. For those applications a solution following the above
guidelines as closely as possible should be found.&lt;/p&gt;

&lt;h3 id=&quot;system-configuration-files-network-hardware-&quot;&gt;System Configuration Files (network, hardware, …)&lt;/h3&gt;

&lt;p&gt;As these configuration files are system specific and only created during
or after installation and not provided by the distribution, these files
will stay in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;system-databases-rpc-services-protocols&quot;&gt;System Databases (rpc, services, protocols)&lt;/h3&gt;

&lt;p&gt;There are files in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt; which, strictly speaking, are no configuration files,
such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/rpc&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/services&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/protocols&lt;/code&gt;. They are changed
very rarely, but sometimes new system applications or third party software
need to make additions.
These files will be moved to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc&lt;/code&gt;; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/nsswitch.conf&lt;/code&gt; has to be changed
to search in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt; first and in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc&lt;/code&gt; second. A glibc NSS plugin
&lt;a href=&quot;https://github.com/kubic-project/libnss_usrfiles&quot;&gt;usrfiles&lt;/a&gt; will be used
for this. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc&lt;/code&gt; will contain only the changes done by the admin and third
party software.&lt;/p&gt;

&lt;h3 id=&quot;etcpasswd-etcgroup-and-etcshadow&quot;&gt;/etc/passwd, /etc/group and /etc/shadow&lt;/h3&gt;

&lt;p&gt;There is no solution yet for these configuration files which would really solve
the problems. Ideas are welcome!&lt;/p&gt;

&lt;h2 id=&quot;further-documentation&quot;&gt;Further Documentation&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;The original, full proposal with many more ideas and background information on the reasoning behind the decisions: &lt;a href=&quot;https://github.com/thkukuk/atomic-updates_and_etc/blob/master/README.md&quot;&gt;Atomic Updates and /etc&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;The openSUSE wiki page: &lt;a href=&quot;https://en.opensuse.org/openSUSE:Packaging_UsrEtc&quot;&gt;Packaging /usr/etc&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Formal &lt;a href=&quot;https://uapi-group.org/specifications/specs/configuration_files_specification/&quot;&gt;Configuration Files Specification&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/uapi-group/specifications/issues/76&quot;&gt;UAPI Group tracking upstream projects not supporting hermetic-usr for configuration&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Hermetic &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr&lt;/code&gt;, as explained in the blog &lt;a href=&quot;https://0pointer.net/blog/fitting-everything-together.html&quot;&gt;Fitting Everything Together&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://0pointer.net/blog/projects/stateless.html&quot;&gt;Factory Reset&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Thorsten Kukuk</name></author><category term="blog" /><summary type="html">This blog post dates from December 2019 and was updated in August 2024.</summary></entry><entry><title type="html">Introduction of soft-reboot</title><link href="https://microos.opensuse.org/blog/2024-06-13-soft-reboot/" rel="alternate" type="text/html" title="Introduction of soft-reboot" /><published>2024-06-13T12:55:00+00:00</published><updated>2024-06-13T12:55:00+00:00</updated><id>https://microos.opensuse.org/blog/soft-reboot</id><content type="html" xml:base="https://microos.opensuse.org/blog/2024-06-13-soft-reboot/">&lt;h2 id=&quot;intro&quot;&gt;Intro&lt;/h2&gt;

&lt;p&gt;systemd v254 introduced a new reboot method: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl soft-reboot&lt;/code&gt;.
A soft-reboot is similar to a regular reboot,  except it affects user-space only. This command does:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Shutdown of all running services and other units&lt;/li&gt;
  &lt;li&gt;Optional: switch to a new root file-system&lt;/li&gt;
  &lt;li&gt;Re-exec systemd&lt;/li&gt;
  &lt;li&gt;Start all systemd services again&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The advantage of this method is a pretty fast reboot:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;No hardware, firmware and bootloader&lt;/li&gt;
  &lt;li&gt;No kernel&lt;/li&gt;
  &lt;li&gt;No initrd&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But there are some challenges to be solved:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Kernel tables will not be flushed (may break services like firewalld+podman).&lt;/li&gt;
  &lt;li&gt;No initrd means that everything that is normally done in the initrd is not executed. In the case of MicroOS, this will break mount of overlayfs for /etc with transactional-update or relabeling the system for a new SELinux policy.&lt;/li&gt;
  &lt;li&gt;/run will not be cleared, which means reboot needed trigger will not be removed. This may affect many more services not expecting that files survive in /run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nevertheless, this method is ideal for quick reboots with transactional-update, e.g. if you only installed another package.&lt;/p&gt;

&lt;h2 id=&quot;current-status&quot;&gt;Current status&lt;/h2&gt;

&lt;p&gt;Support for soft-reboot is fully integrated in transactional-update and rebootmgr. The known, reproducible problems with soft-reboot are solved.&lt;/p&gt;

&lt;p&gt;Currently soft-reboot is still disabled in transactional-update, but will be enabled by default in the near future.&lt;/p&gt;

&lt;h2 id=&quot;how-to-use&quot;&gt;How to use&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;An admin can trigger an immediate soft-reboot with: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemctl soft-reboot&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;A scheduled soft-reboot via rebootmgr can be triggered with: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rebootmgrctl soft-reboot&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;transactional-update&lt;/code&gt; it is not possible to enforce a soft-reboot, if soft-reboot is enabled, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tranactional-update reboot&lt;/code&gt; will choose the best fitting reboot method based on the list of package updates. See &lt;a href=&quot;https://manpages.opensuse.org/zypp-boot-plugin&quot;&gt;man zypp-boot-plugin&lt;/a&gt; for more details and how to configure this.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a soft or a hard reboot was done can be checked with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;last&lt;/code&gt; command. The entries &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;s-reboot&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;soft-reboot&lt;/code&gt; indicates a soft-reboot was done, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reboot&lt;/code&gt; means this was a normal reboot. The detection will only work reliable with systemd v256 or newer.&lt;/p&gt;

&lt;h2 id=&quot;installation-and-configuration&quot;&gt;Installation and Configuration&lt;/h2&gt;

&lt;p&gt;A prerequisite for this feature is that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;patterns-microos-base-zypper&lt;/code&gt; package is installed. This pattern may be missing on old installations that have only been updated regularly.&lt;/p&gt;

&lt;p&gt;The zypper plugin &lt;a href=&quot;https://manpages.opensuse.org/zypp-boot-plugin&quot;&gt;zypp-boot-plugin&lt;/a&gt; analyses the list of packages which get installed or updated and defines, if a hard reboot is required or a soft-reboot is good enough. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc/zypp/zypp-boot-plugin.conf&lt;/code&gt; contains the default configuration, which can be overwritten with drop-ins in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/zypp/zypp-boot-plugin.conf.d/*.conf&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The configuration file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/etc/tukit.conf&lt;/code&gt; defines the system default. The variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;REBOOT_ALLOW_SOFT_REBOOT&lt;/code&gt; is either set to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;, this means soft-reboot is by default disabled, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt;, which means a hard reboot is always done if a reboot is requested.&lt;/p&gt;

&lt;h3 id=&quot;how-to-enable&quot;&gt;How to enable&lt;/h3&gt;

&lt;p&gt;To enable soft-reboot support in transactional-update, create the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/tukit.conf.d/&lt;/code&gt; and create a file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;echo &quot;REBOOT_ALLOW_SOFT_REBOOT=true&quot; &amp;gt; /etc/tukit.conf.d/soft-reboot.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;how-to-disable&quot;&gt;How to disable&lt;/h3&gt;

&lt;p&gt;To disable soft-reboot support in transactional-update, create the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/tukit.conf.d/&lt;/code&gt; and create a file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;echo &quot;REBOOT_ALLOW_SOFT_REBOOT=false&quot; &amp;gt; /etc/tukit.conf.d/soft-reboot.conf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Thorsten Kukuk</name></author><category term="blog" /><summary type="html">Intro</summary></entry><entry><title type="html">Easily set up Passwordless SSH Authentication</title><link href="https://microos.opensuse.org/blog/2024-05-17-ssh-pairing/" rel="alternate" type="text/html" title="Easily set up Passwordless SSH Authentication" /><published>2024-05-17T09:20:37+00:00</published><updated>2024-05-17T09:20:37+00:00</updated><id>https://microos.opensuse.org/blog/ssh-pairing</id><content type="html" xml:base="https://microos.opensuse.org/blog/2024-05-17-ssh-pairing/">&lt;p&gt;MicroOS and Tumbleweed gained a new feature: You can now easily enroll SSH keys for authentication through the firstboot wizard on the very first boot already!&lt;/p&gt;

&lt;h1 id=&quot;motivation&quot;&gt;Motivation&lt;/h1&gt;

&lt;p&gt;Public-key based authentication is safer than password authentication and in most cases also easier to use and maintain. By default, OpenSSH does not even allow root to authenticate with a password anymore.&lt;/p&gt;

&lt;p&gt;Question is how to get the desired public keys into the system to be able to log in. ssh-copy-id needs to be able to log into the target system, which requires password auth. Transferring the keys manually is tedious and error-prone.&lt;/p&gt;

&lt;p&gt;With &lt;a href=&quot;https://github.com/Vogtinator/ssh-pairing&quot;&gt;ssh-pairing&lt;/a&gt; there’s a new approach: a dialog based workflow allows interactive key exchange in both directions. After making an ssh connection and accepting the enrollment, the server’s key is added to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;known_hosts&lt;/code&gt; lists on the client and the selected public keys from the client added to the server’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;authorized_keys&lt;/code&gt; file.&lt;/p&gt;

&lt;h1 id=&quot;how-does-it-look-like&quot;&gt;How does it look like?&lt;/h1&gt;

&lt;p&gt;After starting the pairing procedure, the dialog shows what to do:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/ssh-pairing/connection-dialog.png&quot; alt=&quot;ssh-pairing showing connection info&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After the connection has completed, keys to accept can be individually reviewed and selected.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/ssh-pairing/key-import-dialog.png&quot; alt=&quot;ssh-pairing asking whether to import a key&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;where-can-i-get-it&quot;&gt;Where can I get it?&lt;/h1&gt;

&lt;p&gt;Starting from Snapshot 20240507, MicroOS and Tumbleweed images include this feature in the firstboot wizard. If you want to make use of this on other systems, you can install the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ssh-pairing&lt;/code&gt; package and run the command with the same name (as root).&lt;/p&gt;

&lt;h1 id=&quot;what-about-other-distros&quot;&gt;What about other distros?&lt;/h1&gt;

&lt;p&gt;ssh-pairing is distro-independent, see the &lt;a href=&quot;https://github.com/Vogtinator/ssh-pairing?tab=readme-ov-file&quot;&gt;project page&lt;/a&gt; for installation and usage instructions.&lt;/p&gt;

&lt;p&gt;It would be very welcome to have this available for other distros out of the box as well! If you have questions or find any issues, please don’t hestitate to open tickets.&lt;/p&gt;

&lt;p&gt;Have a lot of fun!&lt;/p&gt;</content><author><name>Fabian Vogt</name></author><category term="blog" /><category term="Announcements" /><category term="openSUSE" /><category term="openSUSE" /><category term="Community" /><category term="Security" /><category term="MicroOS" /><category term="Tumbleweed" /><category term="Rolling Release" /><summary type="html">MicroOS and Tumbleweed gained a new feature: You can now easily enroll SSH keys for authentication through the firstboot wizard on the very first boot already!</summary></entry><entry><title type="html">Systemd-boot and Full Disk Encryption with TPM and FIDO2</title><link href="https://microos.opensuse.org/blog/2023-12-20-sdboot-fde/" rel="alternate" type="text/html" title="Systemd-boot and Full Disk Encryption with TPM and FIDO2" /><published>2023-12-20T09:00:00+00:00</published><updated>2023-12-20T09:00:00+00:00</updated><id>https://microos.opensuse.org/blog/sdboot-fde</id><content type="html" xml:base="https://microos.opensuse.org/blog/2023-12-20-sdboot-fde/">&lt;h1 id=&quot;systemd-boot-and-full-disk-encryption-in-tumbleweed-and-microos&quot;&gt;Systemd-boot and Full Disk Encryption in Tumbleweed and MicroOS&lt;/h1&gt;

&lt;p&gt;openSUSE Tumbleweed and MicroOS are now delivering an image that is
using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt; as boot loader and full disk encryption based
also on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt;.  The unlock of the encrypted device can be done via
the traditional password, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; (a crypto-device that is already
present in your system) that will attach the device if the system is
in good health, or a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIDO2&lt;/code&gt; key that will validate the ownership of a
token.&lt;/p&gt;

&lt;p&gt;There is a lot to explain here, but basically those changes are in the
direction of moving the distribution into a more safe place.  For one
side is making the design of the distribution much more simple, and
for another it is following the current trends about security that
other distributions are also aligning with.&lt;/p&gt;

&lt;p&gt;So, lets start with the beginning …&lt;/p&gt;

&lt;h2 id=&quot;systemd-boot&quot;&gt;systemd-boot&lt;/h2&gt;

&lt;p&gt;We all know and love &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt;.  It is a good boot loader.  It is also
big, complex, rich, massive and tends to move slow on the development
side.&lt;/p&gt;

&lt;p&gt;The openSUSE package for this boot loader contains more than 200
patches.  Some of those patches are there for the last 5, 6 … 10
years.  That is both an indication of the talent of the maintainers,
but also can signal an issue in how slow the upstream contribution
process can be.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; supports all the relevant systems, including mainframes, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arm&lt;/code&gt;
or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;powerpc&lt;/code&gt;.  Multiple types of file systems, including &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;btrfs&lt;/code&gt; or
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NTFS&lt;/code&gt;.  It contains a full network stack, an USB stack, a terminal,
can be scripted … In some sense, it is almost a mini OS by itself.&lt;/p&gt;

&lt;p&gt;But then &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UEFI&lt;/code&gt; happened 18 years ago, making almost all the features
provided by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; somehow redundant.  The system firmware was
already providing most of these functionalities as services that can
be consumed by the operating system, the boot loader or any other user
provided application.  And of course &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; supported &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UEFI&lt;/code&gt; too.&lt;/p&gt;

&lt;p&gt;Soon the Linux kernel gained the option of being compiled as an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EFI&lt;/code&gt;
binary, via a stub that can be attached to the kernel code.  This
implies that the kernel itself could be launched by the firmware
directly, making the boot loader something optional in most of the
cases.&lt;/p&gt;

&lt;p&gt;Over time new and more straightforward boot loaders focused on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UEFI&lt;/code&gt;
appeared, like &lt;a href=&quot;https://cgit.freedesktop.org/gummiboot/&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gummiboot&lt;/code&gt;&lt;/a&gt;. Later this code was integrated into
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; and renamed as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The code is very simple.  Many orders of magnitude simpler than
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt;. It is basically a very small &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EFI&lt;/code&gt; binary that presents a
menu with the different boot loader entries (text files described in
the &lt;a href=&quot;https://uapi-group.org/specifications/specs/boot_loader_specification/&quot;&gt;Boot Loader Specification&lt;/a&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BLS&lt;/code&gt; for short), and a call to
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UEFI&lt;/code&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LoadImage&lt;/code&gt; function to delegate the execution to the
selected kernel.&lt;/p&gt;

&lt;p&gt;This boot loader can also work with the new &lt;a href=&quot;https://uapi-group.org/specifications/specs/unified_kernel_image/&quot;&gt;unified kernel images&lt;/a&gt;
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UKI&lt;/code&gt;), that are files that aggregate in a single unit the kernel,
the command line, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;.  Those &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UKI&lt;/code&gt;s can be very handy
for image based distributions, and openSUSE plans to support them as
well.&lt;/p&gt;

&lt;p&gt;Providing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt; as an alternative for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; is something
that openSUSE wanted to do for a long time.  In August 2023 there was
an &lt;a href=&quot;https://lists.opensuse.org/archives/list/factory@lists.opensuse.org/thread/4FNZ7HEPH6KQQ2JVFNPN7PXWHZZRU5H5/&quot;&gt;announcement&lt;/a&gt; on the Factory mailing list about Tumbleweed
supporting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The announcement references a &lt;a href=&quot;https://en.opensuse.org/Systemd-boot&quot;&gt;wiki entry&lt;/a&gt; that explains how to
migrate an installation using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt; manually.
Soon after the announcement, &lt;a href=&quot;https://github.com/yast/yast-bootloader/pull/686&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;yast-bootloader&lt;/code&gt; gained&lt;/a&gt; support for
it for new installations.&lt;/p&gt;

&lt;p&gt;Supporting another boot loader comes with a cost.  As argued, the code
base is smaller, with less bugs and more easy to reason about.  But
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UEFI&lt;/code&gt; dependency decreases the amount of supported architectures
(x86-64 and aarch64).  That problem can be very much alleviated by
providing another patch for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; to support the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BLS&lt;/code&gt; entries, so
the architecture of the distribution after the boot loader can be
independent of the boot loader itself.  The good news is that the
patch already exists, and could potentially be added into the package.&lt;/p&gt;

&lt;p&gt;Another problem is that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt; does not speak &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;btrfs&lt;/code&gt;.  As an
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EFI&lt;/code&gt; binary, it can read files only from a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAT32&lt;/code&gt; file system.  This
limitation can be resolved by moving the kernel and the initrd into
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EFI&lt;/code&gt; system partition (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Finally, there is also the consideration of supporting snapshots in
Tumbleweed and transactions in MicroOS.  From the boot loader the user
should be able to select what snapshot to boot from, like it is
actually possible to do when using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt;.  Both concepts are
implemented using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;btrfs&lt;/code&gt; subvolumes, and there is only a subset of
kernel, command line, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; combinations that are valid for each of
those subvolumes.&lt;/p&gt;

&lt;p&gt;For example, let’s say we have two snapshots in our system, and each
of these represents a system that has two kernels installed.  It is
possible that those two kernels are not the same across all the
snapshots.  Maybe one of the upgrades replaced one kernel with a newer
version.  We need some tool that can do the bookkeeping required to
associate the correct combination that will produce a successful boot
into any of those snapshots, creating the boot entries under those
restrictions.&lt;/p&gt;

&lt;p&gt;This tool is &lt;a href=&quot;https://github.com/openSUSE/sdbootutil&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil&lt;/code&gt;&lt;/a&gt;.  Every time &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;snapper&lt;/code&gt; creates or
destroys a snapshot (for example, when the system gets updated), it
will call this tool that will analyze the content of the snapshots,
making sure that the corresponding kernel is installed in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt;, a
valid &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; for this kernel is present (if not it will be created
calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mkinitrd&lt;/code&gt;) and a boot entry is created that connects the
kernel, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; and the snapshot via the command line.  It also
takes care of other details, like checking the free space on the
partition.&lt;/p&gt;

&lt;p&gt;Usually his process works transparently, but is good to remember that
we can force a clean state with:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;sdbootutil add-all-kernels
sdbootutil remove-all-kernels
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Just in case, you know …&lt;/p&gt;

&lt;h2 id=&quot;full-disk-encryption&quot;&gt;Full disk encryption&lt;/h2&gt;

&lt;p&gt;The other aspect that we want to announce is the support of full disk
encryption (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FDE&lt;/code&gt;) based on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FDE&lt;/code&gt; is not the new kid on the block.  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; could unlock &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS&lt;/code&gt;
volumes since long ago using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cryptomount&lt;/code&gt; command.  Traditionally
this will request the password from the user two times: once when the
boot loader does the unlock and again when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; does the same
later.  There are ways to avoid the second request injecting the
password into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; or, if you are using the openSUSE package,
it will inject the password transparently into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Recently &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; gained two new features: partial support of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt;
encrypted devices (using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PBKDF2&lt;/code&gt; as key derivation function instead
of the more secure and recommended &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Argon2id&lt;/code&gt;) and a key protection
mechanism that can store secrets in devices like the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;tpm2&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Explaining how &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; works in detail is a topic for another post, but
for now we can think of it as a crypto device that be used to unlock
secrets only when certain conditions related to the state of the
system are met.  The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; will unlock the secret if the system is in
a healthy state.&lt;/p&gt;

&lt;p&gt;This term is a technical one, and is related to assert that the system
is in a &lt;strong&gt;known&lt;/strong&gt; good state.  In other words, we know for sure that
the firmware has not been tampered with, the boot loader is the one
that we installed and has not been replaced, that the kernel is
exactly the one that comes from the distribution, that the kernel
command line is the one that we expect, and that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; that we
used does not contain any extra binary that we do not control.&lt;/p&gt;

&lt;p&gt;Internally the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; has some registers, known as platform
configuration register (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;).  In the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; specification there are
24 of them and the size of one is enough to store the value of a hash
function, like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SHA1&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SHA256&lt;/code&gt;.  They are separated by banks: one
per supported hash function, but this is too much detail for now.&lt;/p&gt;

&lt;p&gt;Those registers are kind of special.  We can reset them, usually
setting the value to 0.  We can read the value, or we can “extend”
them.  The write operation is designed in a way that we cannot set any
random value in the register, except the result of the associated hash
function concatenating the current &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; value and a new value
provided by the user.&lt;/p&gt;

&lt;p&gt;The current value of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; can only be produced by extending this
register using exactly the same sequence of values.  If we change even
one bit of one of the values, we will produce a wildly different final
result for the same &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This feature is used in a process known as &lt;a href=&quot;https://en.opensuse.org/Portal:MicroOS/RemoteAttestation#Measured_boot&quot;&gt;“measured boot”&lt;/a&gt;, where
each stage in the boot chain is measured before it is executed.  This
means that before the initial stages of the firmware are running,
there is a process that will calculate the hash of the code in memory,
and extend one of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s using this value.  This is repeated until
the very end of the boot sequence: the kernel and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When measured boot is in place, the final values of the first 10
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s will contain values than can only be predicted if the machine
is using a well known version of firmware, boot loader and kernel,
together with the associated data like certificates, configuration
files, or kernel parameters.  If one of those elements change (for
example, by using a different secure boot certificate), it will
generate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; values different from the ones that we expect.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; chips are very interesting devices, and the set of features go
far beyond measured boot.  If you want to learn more I recommend
resources like &lt;a href=&quot;https://developers.tpm.dev/&quot;&gt;this&lt;/a&gt; or &lt;a href=&quot;https://trustedcomputinggroup.org/resource/a-practical-guide-to-tpm-2-0/&quot;&gt;this&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;tpm2-for-fde&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FDE&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Anyway, the gist here is that we can create a “policy” that can
instruct the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; to decrypt a secret only if certain &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s
contains the expected values.  The details are a bit different, but
for now lets use this model as a good first approximation.&lt;/p&gt;

&lt;p&gt;The idea is that we can encrypt a password with the values of certain
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; registers, so &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; can later attach the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt; device if the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; can recover the password, validating the health of the system
until this point.  If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; fails to decrypt it, that would mean
that some &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; has not the expected value and some stage in the boot
process changed.  In this situation &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; will ask the password from
the user to continue loading the kernel and the rest of the system. It
delegates the trust about the new state to the user.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; also provides a tool to seal secrets under the current values
of a subset of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s.  This is nice but also presents several
problems.  One is that maybe we are setting the system up in a way
that we know the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s values will change during the next boot (for
example, during the first installation, a boot loader upgrade or a
firmware update).  In this case sealing the password using the current
register values is useless: we need to be able to predict the new ones
and use those hypothetical values to do the sealing.&lt;/p&gt;

&lt;p&gt;The other problem is more insidious and will become critical later.
The expected values can change frequently and can not be unique.
Maybe there is a set of valid ones.  We can choose to boot from a
different kernel or from a different snapshot.  The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; provides a
solution for this using something known as authorized policies.  They
are a way of creating policies that can change, but they are validated
by a signature.  In essence, we create a public and a private key, and
we create multiple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; policies that are signed using the private
key.  Now the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; can validate the signature using the public part,
and unseal the secret using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s values stored in the new
policy.&lt;/p&gt;

&lt;p&gt;Since early 2023 openSUSE provides the &lt;a href=&quot;https://github.com/okirch/pcr-oracle&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcr-oracle&lt;/code&gt;&lt;/a&gt; tool to help
with the prediction of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; registers, and encrypt a key under
those values using both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; policies or authorized policies.  Using
this tool we can now seal a secret under a set of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s values that
can change!&lt;/p&gt;

&lt;p&gt;In the &lt;a href=&quot;https://en.opensuse.org/SDB:Encrypted_root_file_system&quot;&gt;openSUSE wiki&lt;/a&gt; we can find more documentation about those
topics, including instructions about how to use it in our
installation.&lt;/p&gt;

&lt;h2 id=&quot;using-systemd-for-disk-encryption&quot;&gt;Using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; for disk encryption&lt;/h2&gt;

&lt;p&gt;With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FDE&lt;/code&gt; is working properly, so why look for something
else?  One reason is very evident: this architecture can only work
… well … only if our openSUSE &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; version is used.  It will
not work for other boot loaders like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt;.  In fact it will
not work with the the upstream version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; itself.&lt;/p&gt;

&lt;p&gt;But there is a second reason: we can argue that there is not a full
measured boot in place with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt;.  If the boot loader needs to
unlock the device &lt;strong&gt;before&lt;/strong&gt; it can load the kernel, is natural that
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; policies that will evaluate the health of the system cannot
make asserts on the kernel, command line or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; that will be
used.  Those will be loaded after the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt; device has been opened.&lt;/p&gt;

&lt;p&gt;The use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt; gives us an alternative architecture for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FDE&lt;/code&gt; that can work properly with any boot loader that follows the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BLS&lt;/code&gt; (remember, there is a patch for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; to support it somewhere,
so it is not excluded &lt;em&gt;a priori&lt;/em&gt;), and provides the chance to do a
full measured boot attestation before unlocking the device.&lt;/p&gt;

&lt;p&gt;One difference is that the kernel and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; will be placed in
the unencrypted &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt;, and the unlock of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysroot&lt;/code&gt; will be done
from inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; using the different options that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptsetup&lt;/code&gt; offers.  Currently it can unlock the device using
a normal password, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; with authorized policies (with optionally
a PIN that must be entered by the user) or a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIDO2&lt;/code&gt; key device.  In
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/crypttab&lt;/code&gt; file we need to &lt;a href=&quot;https://www.freedesktop.org/software/systemd/man/latest/crypttab.html&quot;&gt;describe&lt;/a&gt; the unlocking
mechanism.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcr-oracle&lt;/code&gt; has been extended to support the creation of authorized
policies that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; can understand.  They are stored in a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JSON&lt;/code&gt;
file that contains multiple predictions, each one of them indicating
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s involved, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; policy hash, the fingerprint of the
public key and the signature of the policy.  This, together with the
public key &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PEM&lt;/code&gt; file, composes all the data required for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptsetup&lt;/code&gt; to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; for the unseal of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt;
key.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RSA&lt;/code&gt; 2048 key used to sign the policy can be created with
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openssl&lt;/code&gt; or with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcr-oracle&lt;/code&gt; itself.  A note of caution: if the
private key gets leaked, this is a game over for the expected security
that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; could provide.  Luckily the solution is cheap in this
case: generate a new key, re-register the key in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt; key slot
with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptenroll&lt;/code&gt; and use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil&lt;/code&gt; to regenerate the
predictions for each boot entry.  Yeah … we will document all the
process in the &lt;a href=&quot;https://en.opensuse.org/Systemd-fde&quot;&gt;“systemd-fde” wiki page&lt;/a&gt; and provide better tools,
but trust me, it is indeed a cheap operation.&lt;/p&gt;

&lt;p&gt;openSUSE is providing a &lt;a href=&quot;https://build.opensuse.org/package/show/devel:microos:images/openSUSE-MicroOS&quot;&gt;MicroOS image&lt;/a&gt; named
&lt;a href=&quot;http://download.opensuse.org/tumbleweed/appliances/openSUSE-MicroOS.x86_64-kvm-and-xen-sdboot.qcow2&quot;&gt;kvm-and-xen-sdboot&lt;/a&gt; that shows how all of this is working.  This
image contains some of the already mentioned tools integrated and some
other new ones:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt;: Boot loader used instead of the default &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil&lt;/code&gt;: Helper scripts to synchronize the boot entries of
the system&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcr-oracle&lt;/code&gt;: Predict the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s values for the next boot, and
creates the authorized policies for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disk-encryption-tool&lt;/code&gt;: Encrypt the device where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysroot&lt;/code&gt; is
located on the first boot&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dracut-pcr-signature&lt;/code&gt;: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dracut&lt;/code&gt; module that will load the
predictions into the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those tools are designed to work together for this new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FDE&lt;/code&gt;
architecture.  What follows is a brief description on how all is
connected.&lt;/p&gt;

&lt;p&gt;Once we get the new MicroOS &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qcow2&lt;/code&gt; image and we setup the VM, we can
proceed with the boot process.  If the VM has a virtual &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; device
it will start measuring the executed code and data, extending the
corresponding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s. Once &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt; has been reached, it will
find the correct boot entry for this session and will read the
corresponding kernel and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; from it.&lt;/p&gt;

&lt;p&gt;At this moment the image is not encrypted.  Inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; that
is used during this first boot, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disk-encryption-tool&lt;/code&gt; script will
be called.  Using some heuristics it will find the partition that
belongs to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysroot&lt;/code&gt; (where the system is located), and will resize it
to reserve 32MB for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt; header.  After that it will use all
the magic that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cryptsetup&lt;/code&gt; provides to re-encrypt the device using a
locally generated password.  This password, as of today, corresponds
to the recovery key that will be presented to the user at the end and
the user should take note and keep it safe.&lt;/p&gt;

&lt;p&gt;After the re-encryption, the system &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/crypttab&lt;/code&gt; will be updated to
communicate that this device is now encrypted and should be managed
with different tools later.&lt;/p&gt;

&lt;p&gt;At the end of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; we switch to the new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysroot&lt;/code&gt;, now finally
located in an encrypted device.  The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disk-encryption-tool&lt;/code&gt; script
already did its main job, but it installed two modules for
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jeos-firstboot&lt;/code&gt;, that will be executed on the first boot of the
system, which is currently happening!&lt;/p&gt;

&lt;p&gt;The first module, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;enroll&lt;/code&gt;, will detect if there is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIDO2&lt;/code&gt; key
inserted and a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; available.  If so it will present a dialog
asking what do you want to use to unlock the system. The second module
will ask the user if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;root&lt;/code&gt; password will also be enrolled in the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt; header as a new key, and will show the recovery key generated
earlier.&lt;/p&gt;

&lt;p&gt;As of today it is not advisable to register both.  As we described
earlier the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIDO2&lt;/code&gt; key will make more sense if we are using a laptop
or a desktop machine and we want unlock the encrypted device with
proof of a token that we own.  This is an interactive process.  The
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; makes more sense on situations where we do not want to interact
with the system, and we want to automatically unlock the device only
if we can assert the health of the system (no tamper occured in the
boot chain).&lt;/p&gt;

&lt;p&gt;If we register the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIDO2&lt;/code&gt; key, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptenroll&lt;/code&gt; will be called
and we will be asked to press the button two times and the
installation process will be over. At the next boot we will be
required to present the key, and if the key is missing, the recovery
password will be asked.&lt;/p&gt;

&lt;p&gt;If we register the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; device, a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RSA&lt;/code&gt; 2048 key gets generated
and stored (the public and private parts) in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/systemd&lt;/code&gt; and
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptenroll&lt;/code&gt; will be used to enroll the public key and to
annotate the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s that are used in the sealing of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt; key.
By default we will be using 0, 2, 4, 7, and 9.  You can check the
meaning in &lt;a href=&quot;https://uapi-group.org/specifications/specs/linux_tpm_pcr_registry/&quot;&gt;this reference&lt;/a&gt;.  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s 0 and 2 will measure all the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UEFI&lt;/code&gt; firmware code.  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; 4 will measure the boot loader
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt;) and the kernel (also UEFI binaries).  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; 7 will
register all the secure boot certificates, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; 9 will be used by
the kernel to measure the command line and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This covers pretty much all that can make sense, but it is the user
who has the final word on what to measure.  The reason is that the
predictions are done inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil&lt;/code&gt; that, remember, will be
automatically executed after each change in the system (updates,
package removal, snapshots management, etc), and this tool will
produce predictions only for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s registered in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt;
header.&lt;/p&gt;

&lt;p&gt;Regardless of the selected unlocking mechanism, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/etc/crypttab&lt;/code&gt;
file will be updated with this selection and a new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; will be
generated to contain this information for the next boot.&lt;/p&gt;

&lt;p&gt;Finally, the last component, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dracut-pcr-signature&lt;/code&gt; will be
responsible that during the subsequent boots all the information that
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptsetup&lt;/code&gt; requires for the unlock will be present
“on-the-fly” inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;. It should be noted that the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;
will require the JSON file with the policies and the key, but those
cannot be included in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;!  The moment that we make a
prediction of a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; that is extended with the hash of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt;,
that is all, and we cannot touch the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;initrd&lt;/code&gt; anymore as this would
produce a new hash and automatically will invalidate the prediction.&lt;/p&gt;

&lt;p&gt;This &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dracut&lt;/code&gt; module will be executed before the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-cryptsetup&lt;/code&gt;
generator for any encrypted devices has started, and will search in
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ESP&lt;/code&gt; partition for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;tpm2-pcr-signature.json&lt;/code&gt; file, that
contains all the valid prediction for the current boot.  Once this
file is in place, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-crypsetup&lt;/code&gt; will be able to assert the
device in the current state is the expected one and the boot process
can continue until the end.&lt;/p&gt;

&lt;h2 id=&quot;future&quot;&gt;Future&lt;/h2&gt;

&lt;p&gt;The image is here, and is a sound PoC.  It provides a much more simple
architecture and will place some components in the correct place.
This will help a lot in the next stages, as there are some other
things that we want to do with the distribution in relation to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FDE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One pretty clear &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;disk-encryption-tool&lt;/code&gt; has limited use outside image
based installation.  Part of this code should be living in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;YaST&lt;/code&gt; and
in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Agama&lt;/code&gt;.  The installer is already creating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt; devices, so it
should be “easy” to extend it in a way that works for us.&lt;/p&gt;

&lt;p&gt;Ideally, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jeos-firstboot&lt;/code&gt; modules should also live in the
installer, but somehow they make sense here too.  In any case the
functionality should not be separated, and both should be merged.&lt;/p&gt;

&lt;p&gt;The encryption tool is doing something right from the very start: the
master key, together with all the user keys are generated during
installation time, but one possible improvement is generating the
recovery key a bit later using the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; tools.  It is a small
detail, but separating system keys from users keys can simplify the
architecture.&lt;/p&gt;

&lt;p&gt;Another aspect to improve is that the user may want to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt;
and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIDO2&lt;/code&gt; key at the same time.  For example, by default the
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; is used, and if the stage changed in a way that fails the
prediction (or there is a security breach that has been detected), the
user can delegate the unlock to the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FIDO2&lt;/code&gt; key, instead of using a
password.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sdbootutil&lt;/code&gt; script contains a bunch of features that should be
also living in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt;. Working with upstream will make this tool
obsolete with time, which would be more good news.&lt;/p&gt;

&lt;p&gt;Another improvement that we can help with in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; is to improve
the diagnosis about the reasons making the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TPM2&lt;/code&gt; reject the unseal of
the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LUKS2&lt;/code&gt; key.  Today we have a general fail message without
reporting what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; or what measured component inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; is
reporting a different hash than the one predicted.  This will help a
lot understating what did go wrong.  Was the boot loader changed?  Or
something in the firmware?&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcr-oracle&lt;/code&gt; is a very good tool for predicting the next &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; values.
It was very easy to extend to parse the new events in the log related
with the full measured boot process, including the kernel,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-boot&lt;/code&gt; extensions on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; 12, or generating the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JSON&lt;/code&gt;
document required by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt;.  The new &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd&lt;/code&gt; 255 (released a
week ago from the time of writing this) includes a similar tool named
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;systemd-pcrlock&lt;/code&gt; that can help us in providing the improved diagnosis
that we are looking for.  Evaluating this tool to do the predictions
will be done soon too.&lt;/p&gt;

&lt;p&gt;As today Type#1 and Type#2 entries from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BLS&lt;/code&gt; are not isomorphic.
There are sections in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EFI&lt;/code&gt; file of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UKI&lt;/code&gt; format that do not
exist in the text representation.  Maybe we will decide to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UKI&lt;/code&gt;s
in the future, or maybe not.  So a good improvement is working on
helping with this unification, that will (among other things) provide
a standard way of splitting the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JSON&lt;/code&gt; file and associating the
predictions to each boot loader entry.&lt;/p&gt;

&lt;p&gt;Generating and registering a new key, or selecting a different set of
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;s is today a manual process.  The current tools can be extended
to help in those processes, or better documentation could be provided.&lt;/p&gt;

&lt;p&gt;The new approach for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FDE&lt;/code&gt; is not about excluding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; from the
equation. It is about providing a chance of using different boot
loaders that follows the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BLS&lt;/code&gt;.  Validating that a proper patched
(duh!) &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GRUB2&lt;/code&gt; can work with all this is still something to be done.&lt;/p&gt;

&lt;p&gt;Also, another thing that needs to be validated and improved are
installations with multiple encrypted disks.  In principle the design
and the code is supporting it (even when the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt; registers per
volume are different).  &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;openQA&lt;/code&gt; will do wonders here.&lt;/p&gt;

&lt;p&gt;And finally, we should rethink if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UKI&lt;/code&gt;s do make sense for
openSUSE or not.  If we go in that direction, the private key used for
signing the policies will be kept in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;OBS&lt;/code&gt; and those policies will
also be generated in the build service, using a different set of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PCR&lt;/code&gt;
values.&lt;/p&gt;

&lt;p&gt;In any case, there is a bunch of work ahead of us.&lt;/p&gt;</content><author><name>Alberto Planas</name></author><category term="blog" /><category term="Announcements" /><category term="openSUSE" /><category term="openSUSE" /><category term="Community" /><category term="Security" /><category term="Full Disk Encryption" /><category term="FDE" /><category term="MicroOS" /><category term="Tumbleweed" /><category term="Rolling Release" /><category term="systemd" /><summary type="html">Systemd-boot and Full Disk Encryption in Tumbleweed and MicroOS</summary></entry></feed>