Hello people. I need some help from the good folks who maintain the Fedora servers
responsible for building a bootchain securely, i.e. GRUB2 or the kernel. For instance, the
bkernel01.iad2.fedoraproject.org server.
Let's take a look at the build logs of a recent GRUB2 build
(
https://koji.fedoraproject.org/koji/buildinfo?buildID=2185557) here:
https://kojipkgs.fedoraproject.org//packages/grub2/2.06/95.fc38/data/logs...
As far as I can see, this server has a smart-card with a private key attached and during
the building procedure, the critical components are being signed with Red Hat Bootloader
Team's `pesign` software (version +115) running in client-server mode rather than
standalone mode. By this I mean e.g. line number 7074 from the log file:
```
+ /usr/bin/pesign-client -t 'OpenSC Card (Fedora Signer)' -c '/CN=Fedora
Secure Boot Signer' -s -i grubx64.efi.orig -o grubx64.efi.onesig
```
I'd like to replicate the setup Fedora has to rebuild bootchain components on my own.
My question is: how did you make `pesign-client` work fine? Is there a procedure of some
sort that works just fine that I don't know about?
Here's what I attempted on a Fedora 38 machine:
- ensured that I have a recent version of `pesign` that Fedora Project ships:
```
$ rpm -qa --qf '%{NEVRA}\n' pesign
pesign-116-2.fc38.x86_64
```
- added myself to the `pesign` Unix group and rebooted the machine just to be sure
it's there alright:
```
$ usermod -a -G pesign user
```
- created a DNSSEC's SoftHSM token:
```
$ mkdir -p $HOME/.config/softhsm2/tokens
$ echo "directories.tokendir = $HOME/.config/softhsm2/tokens" >
$HOME/.config/softhsm2/softhsm2.conf
$ softhsm2-util --init-token --label HSM --so-pin Secret.123 --pin Secret.123 --free
```
- generated a key to be used with `pesign`:
```
$ efikeygen -d /etc/pki/pesign -n example --self-sign --common-name
"CN=example,OU=example,O=example" --kernel
```
- exported the key to a .pk12 file:
```
$ pk12util -d /etc/pki/pesign -o my-ca.pk12 -n example
Enter password for PKCS12 file:
Re-enter password:
pk12util: PKCS12 EXPORT SUCCESSFUL
```
- imported the file to a SoftHSM token:
```
$ pk12util -i my-ca.pk12 -d /etc/pki/pesign -h HSM
Enter Password or Pin for "HSM": Secret.123
Enter password for PKCS12 file:
pk12util: PKCS12 IMPORT SUCCESSFUL
```
- verified that the operation succeeded:
```
$ pkcs11-tool --module p11-kit-proxy.so -l --pin Secret.123 -O
Using slot 0 with a present token (0x11)
Public Key Object; RSA 2048 bits
label:
ID: 3b378e192bb341ca96c2254e30948f55fe3285d0
Usage: encrypt, verify, wrap
Access: none
Certificate Object; type = X.509 cert
label: example
subject: DN: O=example, OU=example, CN=example
serial: 2BE5E980432B464C8EE366B3F76914A4
ID: 3b378e192bb341ca96c2254e30948f55fe3285d0
Private Key Object; RSA
label: example
ID: 3b378e192bb341ca96c2254e30948f55fe3285d0
Usage: decrypt, sign, unwrap
Access: sensitive
Public Key Object; RSA 2048 bits
label:
ID: 3b378e192bb341ca96c2254e30948f55fe3285d0
Usage: encrypt, verify, wrap
Access: none
$ certutil -d /etc/pki/pesign -L -h HSM
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
Enter Password or Pin for "HSM":
HSM:example u,u,u
```
- removed `example` from NSS database:
```
$ certutil -d /etc/pki/pesign -D -n example
```
- ensured the building process will be using `pesign` in client-server mode rather than
standalone:
```
$ sudo systemctl enable pesign --now
Created symlink /etc/systemd/system/multi-user.target.wants/pesign.service →
/usr/lib/systemd/system/pesign.service.
```
- and at last attempted to rebuild a bootchain component like GRUB2:
```
$ dnf download --source grub2
$ rpmdev-setuptree
$ rpmdev-extract -C ~/rpmbuild/SOURCES/ grub2-2.06-95.fc38.src.rpm
[...]
$ cd ~/rpmbuild/SOURCES/ && mv */* .
$ rpmbuild -bb -D 'pe_signing_token HSM' -D 'pe_signing_cert example'
*.spec
[...]
+ /usr/bin/pesign-client -t HSM -c example -s -i grubx64.efi.orig -o grubx64.efi.onesig
pesign-client: signing failed: "pesignd starting (pid 1806)"
error: Bad exit status from /var/tmp/rpm-tmp.hha8Hd (%build)
```
So it looks like there is an error of some kind on my Fedora 38 machine. Let's try
unlocking some tokens:
```
$ pesign-client --unlock --token "NSS Certificate DB"
Enter passphrase for private key:
$ pesign-client --is-unlocked --token "NSS Certificate DB"
token "NSS Certificate DB" is unlocked
```
Good. Let's try the same with SoftHSM:
```
$ pesign-client --unlock --token "HSM"
Enter passphrase for private key: Secret.123
pesign-client: pesignd starting (pid 1806)
$ pesign-client --is-unlocked --token "HSM"
token "HSM" is locked
```
Why? Just why?
On the other hand, the **only** configuration of building GRUB2 and the kernel that worked
for me was with pesign 113 in standalone mode and only when typing the password manually
(this was some time ago on Fedora 35).
Yes, there's an issue with version +114, which I filed at
https://github.com/rhboot/pesign/issues/105, but this doesn't prevent the software
being used in noninteractive mode (by specifying the password in a `--pinfile
<FILE>` option). However, I don't know, how to accomplish this in a stock
configuration of performing a build with rpmbuild -bb -D 'pe_signing_token HSM' -D
'pe_signing_cert example' *.spec - I don't think I'm supposed to write
custom RPM macros for this. There has to be a more obvious solution.
Please, give me a helping hand with this. What procedure do I have to follow to replicate
what's on Fedora Koji instances? What is there that I'm missing?