rhboot / pesign

Linux tools for signed PE-COFF binaries
GNU General Public License v2.0
111 stars 51 forks source link

Regression: pesign fails rather than asking for token's password #105

Open aronowski opened 1 year ago

aronowski commented 1 year ago

The commit 12f16710ee44ef64ddb044a3523c3c4c4d90039a introduced a regression that makes pesign fail instantly instead of asking for a token's password.

Please perform the following steps to verify the behavior on Red Hat Enterprise Linux 9.1:

Install the prerequisites:

$ sudo dnf install -y git rpmdevtools softhsm nss-tools pesign

Initialize a 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

Create a .p12 file and import it to the token:

$ git clone https://github.com/rhboot/shim.git
$ cd shim/
$ ./make-certs example
$ mkdir ~/.nssdb
$ pk12util -i example.p12 -d ~/.nssdb/ -h HSM
Enter Password or Pin for "HSM": Secret.123
Enter password for PKCS12 file: 
pk12util: PKCS12 IMPORT SUCCESSFUL
$ cd

Get a binary that will be used for testing with pesign - I chose shim in this example:

$ dnf download shim
$ rpmdev-extract shim-x64-*.x86_64.rpm
$ cd shim-x64-*.x86_64/boot/efi/EFI/redhat/
$ pesign --show-signature --in=shimx64.efi
---------------------------------------------
certificate address is 0x7f911f925cc8
Content was not encrypted.
Content is detached; signature cannot be verified.
The signer's common name is Microsoft Windows UEFI Driver Publisher
No signer email address.
No signing time included.
There were certs or crls included.
---------------------------------------------
$ pesign --remove-signature --signature-number=0 --in=shimx64.efi --out=shimx64.efi.unsigned
$ pesign --show-signature --in=shimx64.efi.unsigned
No signatures found.
$ cd

Install the packages required to build the good and bad pesigns:

$ dnf download --source pesign-113-21.el9
$ rpmdev-extract pesign-113-21.el9.src.rpm
$ cd pesign-113-21.el9.src/
$ sudo subscription-manager repos --enable codeready-builder-for-rhel-9-x86_64-rpms
$ sudo dnf builddep -y *.spec
$ cd

Witness the good and bad behavior yourself:

$ git clone https://github.com/rhboot/pesign.git
$ cd pesign
$ git checkout 12f16710ee44ef64ddb044a3523c3c4c4d90039a
$ make
$ ./src/pesign -t HSM -n ~/.nssdb -c example -i ~/shim-x64-*.x86_64/boot/efi/EFI/redhat/shimx64.efi.unsigned -o ~/shimx64.efi.example -s
authentication failed for token "HSM"
pesign: Could not find certificate example

$ git checkout 12f16710ee44ef64ddb044a3523c3c4c4d90039a~1
$ git clean -dxf && make
$ ./src/pesign -t HSM -n ~/.nssdb -c example -i ~/shim-x64-*.x86_64/boot/efi/EFI/redhat/shimx64.efi.unsigned -o ~/shimx64.efi.example -s
Enter Password or Pin for "HSM": Secret.123
$ pesign --show-signature --in=$HOME/shimx64.efi.example
---------------------------------------------
certificate address is 0x7f7432236cc8
Content was not encrypted.
Content is detached; signature cannot be verified.
The signer's common name is example
No signer email address.
Signing time: Mon Mar 27, 2023
There were certs or crls included.
---------------------------------------------

This report mentions Red Hat Enterprise Linux 9.1 and shim for a good reason. To sum it up: the entities that sign their shims with hardware tokens on RHEL and its replicas need to either:

The latter can be realized fairly easy in some cases like mine, e.g. having only a limited number of trusted individuals being able to access the machine that performs the signing so no one would utilize this CVE.

jcpunk commented 1 year ago

I think I'm hitting this too...

wynnfeng commented 1 year ago

I also encountered a similar problem ,maybe you can solve like this echo "passwd" > pinfile pesign -t HSM -n ~/.nssdb -c example -i ~/shim-x64-*.x86_64/boot/efi/EFI/redhat/shimx64.efi.unsigned -o ~/shimx64.efi.example -s --pinfile=pinfile

aronowski commented 1 year ago

@wynnfeng, This works fine for a usage, e.g., directly from an interactive shell, but I'm more concerned about the process, where rpmbuild does its magic. In that case, I would have to at the very least rewrite some macros that handle all the stuff, e.g. determining whether to use pesign or pesign-client.

I tried my best, and if this was that simple, I could well have used a Process Substitution Bashism or export the PESIGN_TOKEN_PIN shell variable - if only this worked as an rpmbuild invocation...

In regard to the aforementioned variable, AFAIK it's undocumented in the official manuals, so I created a PR for this, but I wish this was already written officially. I guess we'll have to wait and rely on less-than-official community guides. Not that I'm blaming the pesign developers for this, because most likely their managers consider this to not be a priority during working hours.

Or I could use the client-server mode, that is, the pesign-client binary, if not for the fact that it can't unlock my token on a RHEL 8/9 environment. If you want and have Vagrant in your toolbox, you can fork this repository I created and play around with the pesign utility on your own. Who knows, maybe you'll discover a breakthrough that makes this tool work as intended on the system it was intended to run on in the first place.