Skip to content

Instantly share code, notes, and snippets.

@chenxiaolong
Created December 6, 2017 02:45
Show Gist options
  • Save chenxiaolong/520914b191f17194a0acdc0e03122e63 to your computer and use it in GitHub Desktop.
Save chenxiaolong/520914b191f17194a0acdc0e03122e63 to your computer and use it in GitHub Desktop.

Building Fedora RPMs that use pesign

This guide describes how to build RPMs that use pesign. Pesign is used for signing PE/COFF EFI executables so that they can be used with UEFI secure boot. Enrolling DB or MOK keys and signing kernel modules is beyond the scope of this guide.

Preparation

  1. Install pesign.

    sudo dnf install pesign
  2. Create a directory to hold the secure boot signing keys and the NSS database.

    KEY_DIR=/path/to/keys
    sudo mkdir -m 700 "${KEY_DIR}"
  3. Create an RSA keypair. This will be used for signing the kernel, kernel modules, and other EFI executables.

    sudo openssl req \
        -new \
        -x509 \
        -newkey rsa:2048 \
        -sha256 \
        -keyout "${KEY_DIR}/key.pem" \
        -out "${KEY_DIR}/cert.pem" \
        -days 3650 \
        -subj "/CN=Secure Boot Signing Key/"
  4. Export the keypair as PKCS#12 so that it can be imported into an NSS database.

    sudo openssl pkcs12 \
        -export \
        -inkey "${KEY_DIR}/key.pem" \
        -in "${KEY_DIR}/cert.pem" \
        -name secure_boot \
        -out "${KEY_DIR}/secure_boot.p12"
  5. Create an NSS database. I prefer to use a different NSS database, but the default /etc/pki/pesign path also can be used. Note that /etc/pki/pesign has no password by default, so anyone listed in /etc/pesign/groups or /etc/pesign/users can read private keys from that database. (Using smart cards is beyond the scope of this answer. There's an example in the Fedora infrastructure Ansible scripts.)

    sudo certutil -d "${KEY_DIR}/nss_db" -N
  6. Import the private key and certificate into database:

    sudo pk12util -d "${KEY_DIR}/nss_db" -i "${KEY_DIR}/secure_boot.p12"
  7. Ensure that only root can access the keys and that the NSS database has the correct SELinux label.

    sudo chmod -R 'go-rwx' "${KEY_DIR}"
    sudo chcon --reference=/etc/pki/pesign -R "${KEY_DIR}/nss_db"
  8. If you are not using /etc/pki/pesign for the NSS database, configure the pesign service to point to the proper path.

    sudo mkdir /etc/systemd/system/pesign.service.d/
    sudo tee /etc/systemd/system/pesign.service.d/custom_dir.conf << EOF
    [Service]
    ExecStart=
    ExecStart=/usr/bin/pesign --daemonize -n ${KEY_DIR}/nss_db
    EOF
    sudo systemctl daemon-reload

    The changes should appear in the output of the following command.

    sudo systemctl cat pesign
  9. Add your user or a group to the pesign ACLs. This will give the specified users or groups access to the pesign daemon as well as /etc/pki/pesign.

    # To add the current user
    whoami | sudo tee -a /etc/pesign/users
    # To add a group
    sudo tee -a /etc/pesign/groups <<< 'group_name'

    NOTE: You must make sure that the NSS database path is readable by root. SELinux does not give the pesign_t type dac_read_search and dac_override permissions, so pesign cannot bypass the Unix permission model, despite running as root. If you use /etc/pki/pesign, then add root to /etc/pesign/users or else pesign won't be able to read the files in the directory.

  10. Apply the ACL changes.

    sudo /usr/libexec/pesign/pesign-authorize
  11. Start the pesign daemon.

    sudo systemctl start pesign
    # Optionally, enable to start pesign at boot
    sudo systemctl enable pesign
  12. Set the pesign_t SELinux type to permissive. The current SELinux policy doesn't seem to allow the pesign daemon to do anything useful. For example, a spec file that tries to use the %pesign macro will result in the following AVC denial.

    Dec 05 20:19:19 cxl-laptop-1 audit[6132]: AVC avc:  denied  { read } for  pid=6132 comm="pesignd" path="/var/lib/mock/chenxiaolong-fedora-27-x86_64/root/builddir/build/BUILD/shim-signed-13/shimia32-unsigned.efi" dev="dm-1" ino=1711111 scontext=system_u:system_r:pesign_t:s0 tcontext=unconfined_u:object_r:mock_var_lib_t:s0 tclass=file permissive=0
    

    To work around this, make pesign_t permissive. It's not the best solution, but at least SELinux doesn't need to be set to permissive globally.

    sudo semanage permissive -a pesign_t
  13. Check if the NSS token is unlocked.

    pesign-client -q

    If the NSS token is locked, unlock it using the passphrase you used when creating the NSS database.

    pesign-client -u

Building package with rpmbuild

To build a package that uses pesign with rpmbuild, just define the pe_signing_token and pe_signing_cert macros. For example:

rpmbuild -bb -D 'pe_signing_token NSS Certificate DB' -D 'pe_signing_cert secure_boot' shim-signed.spec

Note that there's currently a typo (RHBZ#1508094) that prevents self-signing from working. This can be fixed by editing /usr/lib/rpm/macros.d/macros.pesign manually or using a patched pesign package from my repo: https://copr.fedorainfracloud.org/coprs/chenxiaolong/rhbz1508094-fix/.

Building package with mock

To build a package with mock, /var/run/pesign needs to be bind mounted into the chroot so that processes inside the chroot can talk to the pesign daemon. To do that, add the following to either /etc/mock/site-defaults.cfg or ~/.config/mock.cfg.

config_opts['plugin_conf']['bind_mount_opts']['dirs'].append(('/var/run/pesign', '/var/run/pesign'))

To build a package, define the pe_signing_token and pe_signing_cert macros. Due to an issue with mock and systemd-nspawn, --old-chroot is also required.

For example:

mock --rebuild shim-signed-13-0.7.src.rpm -D 'pe_signing_token NSS Certificate DB' -D 'pe_signing_cert secure_boot' --old-chroot 

Note that there's currently a typo (RHBZ#1508094) that prevents self-signing from working. Unlike with rpmbuild, this can't be fixed by editing /usr/lib/rpm/macros.d/macros.pesign because the chroot has its own copy of the file. The easiest way to fix this is to add my repo with a patched pesign package to the mock configuration: https://copr.fedorainfracloud.org/coprs/chenxiaolong/rhbz1508094-fix/.

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment