Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Document the preference of using HSMs than other forms of securing private keys #448

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion docs/submitting.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,20 @@ There are strong recommendations on the types of certificates that
should be used in shim, and also on how keys should be managed for
security. See the 12th bullet in [Microsoft UEFI Signing
Requirements](https://techcommunity.microsoft.com/t5/hardware-dev-center/updated-uefi-signing-requirements/ba-p/1062916)
for tips on this, and also some sugested schems for key and certificate
for tips on this, and also some suggested schems for key and certificate
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"schemes" maybe?

management.

The recommendation of using HSMs is worth mentioning here in particular. To
ensure reasonable security, the keys should be generated directly in your HSM
and the private part should never leave it. All the signing shall be done by
delegating the cryptographic operations to your HSM in order to prevent a
malicious actor from copying the private part.
When asked about the security strategy used for the protection of your keys,
and you indeed do use an HSM, tell us the story of setting up your signing
infrastructure - showcase us, with utter pride, how prioritized the signing
security is in your organization!
If possible, help the community by submitting an HCL (Hardware Compatibility List) entry, presenting what HSM you use, and what processes have been performed to make it work inside your infrastructure - see the [`hcl` directory](../hcl) for existing submissions.

### 3.3 Reproducible build

Reviewers will need to validate that they can reproduce your shim
Expand Down
5 changes: 5 additions & 0 deletions hcl/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# HSM Hardware Compatibility List

This directory is meant to be a community-backed registry of HSMs proven to work well for signing bootloader components, along with the infrastructure setup workarounds that are required for certain problematic tokens.

This venue is **not** meant to act as any form of endorsement or advertisement for the aforementioned tokens and their vendors.
13 changes: 13 additions & 0 deletions hcl/softhsm-fc38-rocky9/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# shim-review HCL demo submission - SoftHSM

This is a demonstration of an HCL submission where SoftHSM is used on a Fedora 38 machine to build and sign Rocky Linux 9 bootloader components (GRUB2 only to keep it more simple), with pesign running in client-server mode in a mock environment.

It's purpose is to showcase, what kind of assumptions need to be met, what package versions (shipped by their respective vendors) have been used and what workarounds were needed to make the token work well, e.g. disabling SELinux, changing file permissions, generating test certificates, among others.

Naturally this is just a demonstration meant to be run in a laboratory/test environment to grasp the ideas in an easy-to-follow way. Hence why certain simplifications have been made, like generating keys and certificates outside a token, or how that token can be easily copied and provides no hardware protection. When submitting your own HCL entry, showcase the community the power of your hardware token's security!

Run the test environment:

```
$ vagrant destroy -f ; vagrant up --provision ; sleep 60 ; vagrant up --provision
```
13 changes: 13 additions & 0 deletions hcl/softhsm-fc38-rocky9/Vagrantfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Vagrant.configure("2") do |config|
config.vm.box = "fedora/38-cloud-base"
config.vm.box_version = "38.20230413.1"

["virtualbox", "libvirt"].each do |provider|
config.vm.provider provider do |v|
v.memory = 4096
v.cpus = 2
end
end

config.vm.provision "shell", inline: "cd /vagrant/files/ && bash ./softhsm-node.sh"
end
6 changes: 6 additions & 0 deletions hcl/softhsm-fc38-rocky9/files/rocky-9-softhsm-x86_64.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
include('templates/rocky-9-softhsm.tpl')

config_opts['root'] = 'rocky-9-softhsm-x86_64'
config_opts['description'] = 'Rocky Linux 9'
config_opts['target_arch'] = 'x86_64'
config_opts['legal_host_arches'] = ('x86_64',)
77 changes: 77 additions & 0 deletions hcl/softhsm-fc38-rocky9/files/rocky-9-softhsm.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
config_opts['chroot_setup_cmd'] = 'install autoconf automake bash bash-completion bison bpftool bzip2 bzip2-devel cairo-devel cairo-gobject-devel cmake-filesystem coreutils cpio dejavu-sans-fonts device-mapper-devel diffutils dmidecode dwarves efivar-devel elfutils-devel elfutils-libelf-devel findutils flashrom flashrom-devel flex fontconfig fontconfig-devel freetype freetype-devel fribidi-devel fuse-devel gawk gcc gcc-c++ gcc-plugin-devel gettext gettext-devel git-core glib2-devel glibc-static gnu-efi gnu-efi-compat gnu-efi-devel gnutls-c++ gnutls-dane gnutls-devel gnutls-utils gobject-introspection-devel google-noto-cjk-fonts-common google-noto-sans-cjk-ttc-fonts grep gzip help2man info json-c-devel json-glib-devel kernel-rpm-macros libX11-devel libXau-devel libXext-devel libXft-devel libXrender-devel libarchive-devel libcurl-devel libdatrie-devel libdrm-devel libgudev-devel libgusb-devel libidn2-devel libjcat libjcat-devel libpciaccess-devel libtasn1-devel libtasn1-tools libthai-devel libtool libvala libxcb-devel libxml2-devel libxmlb libxmlb-devel make meson ncurses-devel nettle-devel ninja-build openssl openssl-devel p11-kit-devel pango-devel patch perl-devel perl-generators pesign pixman-devel polkit-devel polkit-docs protobuf-c python3 python3-cairo python3-devel python3-gobject python3-gobject-base python3-gobject-base-noarch python3-jinja2 python3-mako python3-markdown redhat-release redhat-rpm-config rpm-build rpm-devel rpmdevtools sed shadow-utils softhsm sqlite sqlite-devel squashfs-tools systemd systemd-boot-unsigned systemd-devel tar texinfo tpm2-tss-devel unbound-libs unzip util-linux vala valgrind valgrind-devel vim which xorg-x11-proto-devel xz xz-devel'
config_opts['dist'] = 'el9' # only useful for --resultdir variable subst
config_opts['releasever'] = '9'
config_opts['package_manager'] = 'dnf'
config_opts['extra_chroot_dirs'] = [ '/run/lock', ]
config_opts['bootstrap_image'] = 'quay.io/rockylinux/rockylinux:9'

config_opts['plugin_conf']['bind_mount_enable'] = True
config_opts['plugin_conf']['bind_mount_opts']['dirs'].append(('/etc/pki/pesign', '/etc/pki/pesign' ))
config_opts['plugin_conf']['bind_mount_opts']['dirs'].append(('/usr/libexec/pesign', '/usr/libexec/pesign' ))
config_opts['plugin_conf']['bind_mount_opts']['dirs'].append(('/var/run/pesign', '/var/run/pesign' ))
config_opts['plugin_conf']['bind_mount_opts']['dirs'].append(('/var/lib/softhsm', '/var/lib/softhsm' ))
config_opts['nspawn_args'] += ['--bind=/etc/pki/pesign']
config_opts['nspawn_args'] += ['--bind=/usr/libexec/pesign']
config_opts['nspawn_args'] += ['--bind=/var/lib/softhsm']
config_opts['nspawn_args'] += ['--bind=/var/run/pesign']

config_opts['dnf.conf'] = """
[main]
keepcache=1
debuglevel=2
reposdir=/dev/null
logfile=/var/log/yum.log
retries=20
obsoletes=1
gpgcheck=0
assumeyes=1
syslog_ident=mock
syslog_device=
metadata_expire=0
mdpolicy=group:primary
best=1
install_weak_deps=0
protected_packages=
module_platform_id=platform:el9
user_agent={{ user_agent }}


[baseos]
name=Rocky Linux $releasever - BaseOS
baseurl=http://dl.rockylinux.org/pub/rocky/$releasever/BaseOS/$basearch/os/
gpgcheck=1
enabled=1
metadata_expire=6h
gpgkey=file:///usr/share/distribution-gpg-keys/rocky/RPM-GPG-KEY-Rocky-9

[appstream]
name=Rocky Linux $releasever - AppStream
baseurl=http://dl.rockylinux.org/pub/rocky/$releasever/AppStream/$basearch/os/
gpgcheck=1
enabled=1
metadata_expire=6h
gpgkey=file:///usr/share/distribution-gpg-keys/rocky/RPM-GPG-KEY-Rocky-9

[crb]
name=Rocky Linux $releasever - CRB
baseurl=http://dl.rockylinux.org/pub/rocky/$releasever/CRB/$basearch/os/
gpgcheck=1
enabled=1
metadata_expire=6h
gpgkey=file:///usr/share/distribution-gpg-keys/rocky/RPM-GPG-KEY-Rocky-9

[extras]
name=Rocky Linux $releasever - Extras
baseurl=http://dl.rockylinux.org/pub/rocky/$releasever/extras/$basearch/os/
gpgcheck=1
enabled=1
metadata_expire=6h
gpgkey=file:///usr/share/distribution-gpg-keys/rocky/RPM-GPG-KEY-Rocky-9

[devel]
name=Rocky Linux $releasever - Devel WARNING! FOR BUILDROOT ONLY DO NOT LEAVE ENABLED
baseurl=http://dl.rockylinux.org/pub/rocky/$releasever/devel/$basearch/os/
gpgcheck=1
enabled=1
gpgkey=file:///usr/share/distribution-gpg-keys/rocky/RPM-GPG-KEY-Rocky-9
"""
78 changes: 78 additions & 0 deletions hcl/softhsm-fc38-rocky9/files/softhsm-node.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/bin/bash

set -euo pipefail

if test ! $(rpm --eval %fedora) = "38"; then
echo "The script is meant to run on Fedora 38 only, terminating."
exit 1
fi

sudo dnf install -y git grubby openssl pesign softhsm mock wget

sudo setenforce 0 || true
sudo grubby --update-kernel ALL --args selinux=0

sudo cp -n rocky-9-softhsm-x86_64.cfg /etc/mock/
sudo cp -n rocky-9-softhsm.tpl /etc/mock/templates/
sudo usermod -a -G mock,ods,pesign $USER

# The file "/etc/profile.d/softhsm-node-for-pesign.sh" will act as a flag indicating that the earlier tasks have succeeded - no need for multiple reboots
if test ! -f /etc/profile.d/softhsm-node-for-pesign.sh; then
sudo bash -c 'echo "export PESIGN_TOKEN_PIN=\"Secret.123\"" > /etc/profile.d/softhsm-node-for-pesign.sh'
echo "
---
Rebooting the machine for the changes to take place.
"
sudo reboot
fi

if test ! -v PESIGN_TOKEN_PIN; then
echo "PESIGN_TOKEN_PIN not set correctly, terminating."
exit 1
fi

YOUR_UNIX_ACCOUNT_GROUPS="$(id -Gn $USER)"

if ! grep -q "mock pesign ods" <<< "${YOUR_UNIX_ACCOUNT_GROUPS}"; then
echo "
Expected your Unix account to be in the groups:
\"mock pesign ods\"
but got:
\"${YOUR_UNIX_ACCOUNT_GROUPS}\",
terminating.
"
exit 1
fi

# Initializations
mock -r rocky-9-softhsm-x86_64 --init
softhsm2-util --init-token --label HSM --so-pin ${PESIGN_TOKEN_PIN} --pin ${PESIGN_TOKEN_PIN} --free

# Example p12 generation and import
git clone https://github.com/rhboot/shim.git --depth 1
pushd shim
./make-certs example
pk12util -k <(echo "${PESIGN_TOKEN_PIN}") -w /dev/zero -i example.p12 -d /etc/pki/pesign -h HSM
popd

# Workarounds related to permissions
sudo chmod -R 777 /var/lib/softhsm/
sudo /usr/libexec/pesign/pesign-authorize
sudo chmod -R 777 /var/lib/softhsm/
sudo chmod -R 777 /etc/pki/pesign/
sudo systemctl enable pesign --now
sudo chmod -R 777 /var/run/pesign*

# Unlock the token in client-server mode
pesign-client -u -t HSM
pesign-client --is-unlocked --token HSM

# Example rebuild as a proof that it works
wget http://dl.rockylinux.org/vault/rocky/9.4/BaseOS/source/tree/Packages/g/grub2-2.06-82.el9_4.src.rpm
echo "ee074f84382f92401bc85cdac2942e3c0da928aa56329afe29b058db63857d99 *grub2-2.06-82.el9_4.src.rpm" | sha256sum -c
mock -r rocky-9-softhsm-x86_64 --define "pe_signing_token HSM" --define "pe_signing_cert example" --rebuild grub2-2.06-82.el9_4.src.rpm

echo "
---
It works alright.
"