Skip to content

Commit

Permalink
install: tpm2-luks: Do not bind to any PCRs with cryptenroll
Browse files Browse the repository at this point in the history
The default binding to PCR7 just causes problems without adding
much value in reality.  With a generic OS/distribution being installed
(i.e. no custom Secure Boot chain) a malicious actor who managers to
get access to a disk outside of a machine can usually arrange to
boot using the same PCR7 state.

The problem it causes is it creates a hard version locking
requirement between the host system running `bootc install`
and the target OS.

A related, but opposite problem in a way is that today
we don't update shim by default, except when opted-in via
`bootupctl update`; to do so while doing PCR 7 locking will
require e.g. bootupd to learn how to re-enroll with
new shim's PCR7 state.

Signed-off-by: Colin Walters <[email protected]>
  • Loading branch information
cgwalters committed Apr 25, 2024
1 parent 03d1a06 commit eed20cf
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 3 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,29 @@ jobs:
truncate -s 20G ${tmpdisk}
sudo podman run --rm -ti --privileged --env RUST_LOG=debug -v /dev:/dev -v /:/target -v /var/lib/containers:/var/lib/containers -v ./usr/bin/bootc:/usr/bin/bootc --pid=host --security-opt label=disable \
-v ${tmpdisk}:/disk ${image} bootc install to-disk --via-loopback /disk
install-tpm2-luks:
name: "Test install to-disk --via-loopback tpm2-luks"
needs: [build-c9s]
runs-on: ubuntu-latest
steps:
- name: Download
uses: actions/download-artifact@v4
with:
name: bootc-c9s.tar.zst
- name: Install
run: tar -xvf bootc.tar.zst
- name: Checkout repository
uses: actions/checkout@v4
- name: Integration tests
run: |
set -xeuo pipefail
cat > Containerfile << 'EOF'
FROM quay.io/centos-bootc/centos-bootc-dev:stream9
COPY tests/50-enable-tpm2-luks.toml /usr/lib/bootc/install
EOF
image=localhost/test
sudo podman build -t "${image}" .
tmpdisk=$(mktemp -p /var/tmp)
truncate -s 20G ${tmpdisk}
sudo podman run --rm -ti --privileged --env RUST_LOG=debug -v /dev:/dev -v /:/target -v /var/lib/containers:/var/lib/containers -v ./usr/bin/bootc:/usr/bin/bootc --pid=host --security-opt label=disable \
-v ${tmpdisk}:/disk ${image} bootc install to-disk --block-setup tpm2-luks --via-loopback /disk
16 changes: 16 additions & 0 deletions docs/src/man-md/bootc-install-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,22 @@ The `install`` section supports two subfields:
- `filesystem`: See below.
- `kargs`: An array of strings; this will be appended to the set of kernel arguments.

## block: direct

This configuration will use a "plain" layout with the default filesystem configured
in the image for `/`, alongside a separate `/boot` partition and other platform
state such as an EFI System Partition (if applicable), etc.

## block: tpm2-luks

Bind unlock of filesystem to presence of the default TPM2 device.
This is implemented using a hardcoded invocation of `systemd-cryptenroll`
that does not do any PCR binding, and does not enable a password or recovery
key. This is suitable as a basic default for for e.g. headless cloud environments.
More sophisticated use cases will currently most likely want to use `bootc install to-filesystem`
and explicitly invoke `systemd-cryptenroll` or other tools to set up
the desired encryption state.

# filesystem

There is one valid field:
Expand Down
20 changes: 17 additions & 3 deletions lib/src/install/baseline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,17 @@ pub(crate) struct InstallBlockDeviceOpts {

/// Target root block device setup.
///
/// direct: Filesystem written directly to block device
/// tpm2-luks: Bind unlock of filesystem to presence of the default tpm2 device.
/// - direct: Filesystem written directly to block device
/// - tpm2-luks: Bind unlock of filesystem to presence of the default TPM2 device.
/// This is implemented using a hardcoded invocation of `systemd-cryptenroll`
/// that does not do any PCR binding, and does not enable a password or recovery
/// key. Effectively this just guards the encryption state to the disk being "physically"
/// connected to the same machine. This is a very simple model
/// that can serve as a basic default for for e.g. headless cloud environments.
/// More sophisticated use cases will most likely want to use `bootc install to-filesystem`
/// and explicitly invoke `systemd-cryptenroll` or other tools to set up
/// the desired encryption state.
///
#[clap(long, value_enum)]
pub(crate) block_setup: Option<BlockSetup>,

Expand Down Expand Up @@ -336,7 +345,12 @@ pub(crate) fn install_create_rootfs(
.run()?;
// The --wipe-slot=all removes our temporary passphrase, and binds to the local TPM device.
Task::new("Enrolling root device with TPM", "systemd-cryptenroll")
.args(["--wipe-slot=all", "--tpm2-device=auto", "--unlock-key-file"])
.args([
"--wipe-slot=all",
"--tpm2-pcrs=",
"--tpm2-device=auto",
"--unlock-key-file",
])
.args([tmp_keyfile])
.args([base_rootdev.as_str()])
.run_with_stdin_buf(dummy_passphrase_input)?;
Expand Down
2 changes: 2 additions & 0 deletions tests/50-enable-tpm2-luks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[install]
block = ["direct", "tpm2-luks"]

0 comments on commit eed20cf

Please sign in to comment.