Giter Site home page Giter Site logo

pesign's People

Contributors

anthonysquires avatar aronowski avatar belegdol avatar blarse avatar bmwiedemann avatar cicku avatar damarlin avatar dm0- avatar dsd avatar fpmurphy avatar frozencemetery avatar gregkh avatar hustliyilin avatar jcpunk avatar jcristau avatar jeremycline avatar lcp avatar ldv-alt avatar mirco avatar mjg59 avatar mscherer avatar nfrayer avatar nicholasbishop avatar nwnk avatar rattacresh avatar rhvgoyal avatar sgallagher avatar vathpela avatar vcharak avatar vhankala avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pesign's Issues

[RFE] pesign show certificates

Can pesign be extended to show which certificates are in the --certdir?

The ability to show which certs are in the dir will help dramatically with setting -c and -t.

[RFE] Implement timestamped signing

Microsoft signtool allows timestamped signing (/t URL and /tr URL), so that signed file remains valid even after original certificate expires. In Linux world one can sign+timestamp PE files using osslsigncode tool, but it does not support working with PKCS11 databases (and therefore with hardware tokens). It would be nice if pesign supported timestamping as well.

[RFE] Certificate selection with identical nicknames

I'm in the unfortunate position of having a token with two certificates that share the same nickname. Is there an existing way to disambiguate which certificate I want to use when invoking pesign? If not, I'd be interested in contributing some code to do that (perhaps by specifying the fingerprint?), but I'm not well-versed in NSS so I'd need some pointers.

For now I have a hack that seems to work:

diff --git a/src/cms_common.c b/src/cms_common.c
index 2df2cfe..e296886 100644
--- a/src/cms_common.c
+++ b/src/cms_common.c
@@ -291,6 +291,13 @@ is_valid_cert(CERTCertificate *cert, void *data)
 	PK11SlotInfo *slot = cbdata->psle->slot;
 	void *pwdata = cbdata->pwdata;
 
+	static int first = 1;
+	if (first) {
+	  first = 0;
+	} else {
+	  return SECFailure;
+	}
+
 	SECKEYPrivateKey *privkey = NULL;
 	privkey = PK11_FindPrivateKeyFromCert(slot, cert, pwdata);
 	if (privkey != NULL) {

pesign uses older dbm format nssdb

pesign currently ships with an old format nssdb.

it can convert to the newer format with:

certutil -K -d sql:etc/pki/pesign -X

and the source code should probably be changed to something like:

- char *certdir = "/etc/pki/pesign"
+ char *certdir = "sql:/etc/pki/pesign"

(or set NSS_DEFAULT_DB_TYPE=sql in environment)

pesign macros nssdir

--- macros.pesign.orig  2018-05-02 10:02:23.487822776 -0500
+++ macros.pesign   2018-05-02 09:11:54.067923662 -0500
@@ -8,6 +8,7 @@

 %__pesign_token %{nil}%{?pe_signing_token:-t "%{pe_signing_token}"}
 %__pesign_cert %{!?pe_signing_cert:-c "Red Hat Test Certificate"}%{?pe_signing_cert:-c "%{pe_signing_cert}"}
+%__pesign_nssdir %{nil}%{?pe_signing_dir:--certdir "%{pe_signing_dir}"}

 %_pesign /usr/bin/pesign
 %_pesign_client /usr/bin/pesign-client
@@ -42,6 +43,7 @@
                         %{-i} %{-o} %{-e} %{-s} %{-C}          \
     else                               \
       %{_pesign} %{__pesign_token} %{__pesign_cert}            \\\
+        %{__pesign_nssdir}                 \\\
                  %{-i} %{-o} %{-e} %{-s} %{-C}             \
     fi                                 \
   else

Used this to use an alternative cert dir than the /etc/pki/pesign. Or I guess I could just add my certs to the that directory, but those files are owned by the RPM. In the more recent macros the certdir is only internally set.

build of 0.111 fails with undefined reference to symbol pthread_rwlock_rwlock

Hey. Building 0.111 on arch-linux fails with the following message:

/usr/bin/gcc pesigcheck.o pesigcheck_context.o certdb.o cms_common.o content_info.o oid.o password.o signed_data.o signer_info.o wincert.o ucs2.o /home/mirco/build/build/pesign/src/pesign-0.111/libdpe/libdpe.a -lefivar -lssl3 -lsmime3 -lnss3 -lnssutil3 -lplds4 -lplc4 -lnspr4 -lpopt -o pesigcheck
/usr/bin/ld: /tmp/cc6kuUCi.ltrans1.ltrans.o: undefined reference to symbol 'pthread_rwlock_wrlock@@GLIBC_2.2.5'
/usr/lib/libpthread.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
: recipe for target 'pesigcheck' failed
make[1]: *** [pesigcheck] Error 1

So for some reason -lpthread is missing. I can't figure out your makefiles though so I need your help to fix this ;)
Thanks

pesigcheck fails to verify signature of official Fedora binaries

pesigcheck is currently not able to verify the signature of any EFI binary I've tested.

For example, trying to verify the kernel signature against the Fedora CA cert:

$ pesigcheck -i /boot/vmlinuz-4.14.5-300.fc27.x86_64 -n 0 -c /tmp/shim-unsigned-x64/fedora-ca.cer
Searching db fedora-ca.cer
Searching db fedora-ca.cer
Peer's Certificate issuer is not recognized.
pesigcheck: "/boot/vmlinuz-4.14.5-300.fc27.x86_64" is invalid.

or trying to verify the shim signature against the Microsoft CA cert:

$ sudo pesigcheck -i /boot/efi/EFI/Fedora/shimx64.efi -n 0 -c /tmp/MicCorUEFCA2011_2011-06-27.crt 
Searching db MicCorUEFCA2011_2011-06-27.crt
Searching db MicCorUEFCA2011_2011-06-27.crt
Issuer certificate is invalid.
pesigcheck: "/boot/efi/EFI/Fedora/shimx64.efi" is invalid.

Any ideas what might cause this?

error: implicit conversion from 'enum <anonymous>' to 'enum <anonymous>' [-Werror=enum-conversion] with GCC10

Hello.

I see the following issue with GCC 10 that has a new warning:

$ gcc -O2 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables -fstack-clash-protection -Werror=return-type -flto=auto -fcommon -g  -Wall -Wextra -Wsign-compare -Wno-unused-result -Wno-unused-function -Wno-missing-field-initializers -Werror -Wno-error=cpp -std=gnu11 -fshort-wchar -fPIC -fno-strict-aliasing -D_GNU_SOURCE -DCONFIG_x86_64 -I/home/abuild/rpmbuild/BUILD/pesign-113/include   -Wmaybe-uninitialized -grecord-gcc-switches -flto -I/usr/include/efivar -I/usr/include/nss3 -I/usr/include/nspr4   -c -o pesigcheck.o pesigcheck.c
$ [    7s] pesigcheck.c: In function 'check_signature':
[    7s] pesigcheck.c:321:17: error: implicit conversion from 'enum <anonymous>' to 'enum <anonymous>' [-Werror=enum-conversion]
[    7s]   321 |    reason->type = siBuffer;
[    7s]       |                 ^
[    7s] pesigcheck.c:333:17: error: implicit conversion from 'enum <anonymous>' to 'enum <anonymous>' [-Werror=enum-conversion]
[    7s]   333 |    reason->type = siBuffer;
[    7s]       |                 ^

The warning seems correct to me, both enums are anonymous.

Unable to sign files with YubiHSM

Hello.

We're unable to utilize Yubico's YubiHSM2 FIPS for signing binaries.

pesign claims it could not find our certificate:

[pesign@hsm ~]$ pesign -t "YubiHSM" -n /etc/pki/pesign/ -c CompanyX --sign -i /grubx64.efi.empty -o /pesign-writable/grubx64.efi
Enter Password or Pin for "YubiHSM":
cms_common.c:find_certificate:470: could not find certificate in list:
Unrecognized Object Identifier.
pesign: Could not find certificate CompanyX

While the certificate is clearly present in the HSM:

[pesign@hsm ~]$ p11tool --provider /usr/lib64/pkcs11/yubihsm_pkcs11.so --login  --list-all "pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=[...];token=YubiHSM"
Token 'YubiHSM' with URL 'pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=[...];token=YubiHSM' requires user PIN
Enter PIN:
[...]
Object 2:
        URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=[...];token=YubiHSM;id=%00%05;object=CompanyX;type=private
        Type: Private key (RSA-2048)
        Label: CompanyX
        Flags: CKA_PRIVATE; CKA_EXTRACTABLE; CKA_SENSITIVE;
        ID: 00:05

Object 3:
        URL: pkcs11:model=YubiHSM;manufacturer=Yubico%20%28www.yubico.com%29;serial=[...];token=YubiHSM;id=%00%05;object=CompanyX;type=public
        Type: Public key (RSA-2048)
        Label: CompanyX
        Flags: CKA_EXTRACTABLE;
        ID: 00:05
[...]

I'll also attach its objectinfo:

yubihsm> get objectinfo 0 0x0005 asymmetric-key
id: 0x0005, type: asymmetric-key, algorithm: rsa2048, label: "CompanyX", length: 896, domains: 1, sequence: 1, origin: imported, capabilities: exportable-under-wrap:sign-pkcs

I was using a 'Master Key' with all capabilities there are for this attempt so capabilities should not be the problematic thing.

What could possibly be going on here?

[RFE] pesign-daemon: use an anonymous socket.

It'd be good to have something like:
pesign -D --socket-name jdfljdskljf
and
pesign-client --socket-name jdfljdskljf
and have them use abstract unix sockets, so that the daemon doesn't have to rely on a bind mount of /var/run/ to work in a chroot.

Compilation error with gcc 10, -Werror=array-bounds and -O2 or higher

gcc -O2 -g -Wall -Werror=array-bounds  -Wall -Wextra -Wsign-compare -Wno-unused-result -Wno-unused-function -Wno-missing-field-initializers -Werror -Wno-error=cpp -std=gnu11 -fshort-wchar -fPIC -fno-strict-aliasing -D_GNU_SOURCE -DCONFIG_x86_64 -I/home/stefan/projects/pesign/include   -Wmaybe-uninitialized -grecord-gcc-switches -flto     -fno-merge-constants -fvar-tracking -fvar-tracking-assignments -fkeep-inline-functions -Wl,--fatal-warnings,--no-allow-shlib-undefined,--default-symver -Wl,-O2 -Wl,--no-undefined-version -Wl,-z,relro,-z,now -Wl,--no-add-needed,--no-copy-dt-needed-entries,--as-needed   -shared \
        -Wl,-soname,libdpe.so.0.113 \
        -o libdpe.so libdpe.o pe_addcert.o pe_allocspace.o pe_begin.o pe_end.o pe_error.o pe_getdatadir.o pe_getpehdr.o pe_getscn.o pe_getshdr.o pe_nextscn.o pe_opthdr.o pe_rawfile.o pe_readall.o
pe_update.o pe_updatefile.o pe_updatenull.o -lpthread
pe_begin.c: In function ‘read_file.constprop’:
common.h:107:11: error: array subscript 1 is outside array bounds of ‘union [1]’ [-Werror=array-bounds]
  107 |   switch (le16_to_cpu(peo->magic)) {
      |           ^
pe_begin.c:176:4: note: while referencing ‘mem’
  176 |  } mem;
      |    ^
lto1: all warnings being treated as errors
lto-wrapper: fatal error: gcc returned 1 exit status
compilation terminated.
/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/../../../../x86_64-pc-linux-gnu/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status

See also: https://bugs.gentoo.org/721934
I have reproduced this error with the latest source from the master branch. It does not reproduce with gcc 9, or gcc 10 with -O{0,1}.

pesign fails to build with standard Fedora flags

pe_updatefile.c: In function '__pe_updatemmap':
pe_updatefile.c:135:3: error: #warning this is not done yet. [-Werror=cpp]
#warning this is not done yet.
^~~~~~~
cc1: all warnings being treated as errors

efisiglist compile error

During compilation, I get the following error, that I am unable to resolve on my own. I did note that you made a fix in 727f93f for a similar type of issue with cms_common.c, but I was unable to apply the same kind of fix without getting some new errors :).

/usr/bin/gcc -I/ts/ports/components/pesign/work/src/pesign/include -I/usr/include/nspr -g -O0 -Wall -fshort-wchar -fno-strict-aliasing -fno-merge-constants --std=gnu99 -D_GNU_SOURCE -Wno-unused-result -Wno-unused-function -I../include/ -I/usr/include/nss -Werror -fPIE -DCONFIG_ia32 -c efisiglist.c -o efisiglist.o
efisiglist.c:41:3: error: initialization discards 'const' qualifier from pointer target type [-Werror]
.guid = &efi_guid_sha256,
^
efisiglist.c:45:3: error: initialization discards 'const' qualifier from pointer target type [-Werror]
.guid = &efi_guid_sha1,
^
cc1: all warnings being treated as errors
/ts/ports/components/pesign/work/src/pesign/Make.rules:11: recipe for target 'efisiglist.o' failed
make[1]: *** [efisiglist.o] Error 1
make[1]: Leaving directory '/ts/ports/components/pesign/work/src/pesign/src'
Makefile:12: recipe for target 'src' failed
make: *** [src] Error 2

unrecognized options with gcc 4.8.5

When make the pesign, there are many gcc errors like the following:

# make
make[1]: Entering directory `/root/pesign/include'
make[1]: Nothing to be done for `deps'.
make[1]: Leaving directory `/root/pesign/include'
make[1]: Entering directory `/root/pesign/libdpe'
make -f /root/pesign/Make.deps deps SOURCES="libdpe.c pe_addcert.c pe_allocspace.c pe_begin.c pe_end.c pe_error.c pe_getdatadir.c pe_getpehdr.c pe_getscn.c pe_getshdr.c pe_nextscn.c pe_opthdr.c pe_rawfile.c pe_readall.c pe_update.c pe_updatefile.c pe_updatenull.c"
make[2]: Entering directory `/root/pesign/libdpe'
gcc -O2 -g3 -pipe -fPIE -fstack-protector-all -fstack-clash-protection -fcf-protection=full  -Wall -Wextra -Wsign-compare -Wno-unused-result -Wno-unused-function -Wno-missing-field-initializers -Wno-analyzer-malloc-leak -Werror -Wno-error=cpp -Wno-free-nonheap-object -std=gnu11 -fshort-wchar -fPIC -fno-strict-aliasing -D_GNU_SOURCE -DCONFIG_x86_64 -I/root/pesign/include '-DRUNDIR="/run/"'   -Wmaybe-uninitialized -grecord-gcc-switches -fplugin=annobin  -fmessage-length=0 -fdiagnostics-color=always -fdiagnostics-format=text -fdiagnostics-show-cwe -fanalyzer  -I/usr/include/efivar -I/usr/include/nspr4 -I/usr/include/nss3 -I/usr/include/uuid   -D_FORTIFY_SOURCE=2 -MM -MG -MF .libdpe.d libdpe.c
gcc: error: unrecognized command line option '-fcf-protection=full'
gcc: error: unrecognized command line option '-fdiagnostics-format=text'
gcc: error: unrecognized command line option '-fdiagnostics-show-cwe'
gcc: error: unrecognized command line option '-fanalyzer'

The gcc version is

# gcc --version
gcc (GCC) 4.8.5 20150623 (Anolis 4.8.5-44.0.1)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Could you help me?

pesign: could not parse signature list in EFI binary

Hello, everyone
When I use pesign to get the hash of kernel, the command always returns an error:
centos8.3
[root@localhost ~]# pesign -P -h -i /boot/vmlinuz-4.18.0-240.el8.aarch64
pesign: could not parse signature list in EFI binary
centos8.1
[root@node-56689-98457 ~]# pesign -P -h -i /boot/vmlinuz-4.18.0-147.24.2.el8.aarch64
pesign: could not parse signature list in EFI binary
[root@node-56689-98457 ~]# pesign -P -h -i /boot/efi/EFI/centos/grubaa64.efi
/boot/efi/EFI/centos/grubaa64.efi bd5ee4cc64d605ad36f4259daf36de27c05c2616cd84b48055ccd252c7532962
[root@node-56689-98457 ~]# pesign -P -h -i /boot/efi/EFI/centos/shimaa64.efi
/boot/efi/EFI/centos/shimaa64.efi 2dff74e3d3f9b4a67d3287d3df9806f62e8aac5790d650917d4e58f01d8b8b79
I used the ARM server,how to solve this problem?

115: build fails with gcc 12.0.1

Look slike build fails with latest gcc.

+ cd pesign-115
+ CFLAGS='-O2 -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fdata-sections -ffunction-sections -flto=auto -flto-partition=none -Os'
+ CXXFLAGS='-O2 -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fdata-sections -ffunction-sections -flto=auto -flto-partition=none'
+ FFLAGS='-O2 -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fdata-sections -ffunction-sections -flto=auto -flto-partition=none -I/usr/lib64/gfortran/modules'
+ FCFLAGS='-O2 -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fdata-sections -ffunction-sections -flto=auto -flto-partition=none -I/usr/lib64/gfortran/modules'
+ LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,--gc-sections -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -flto=auto -flto-partition=none -fuse-linker-plugin -Wl,--build-id=sha1'
+ CC=/usr/bin/gcc
+ CXX=/usr/bin/g++
+ FC=/usr/bin/gfortran
+ AR=/usr/bin/gcc-ar
+ NM=/usr/bin/gcc-nm
+ RANLIB=/usr/bin/gcc-ranlib
+ export CFLAGS CXXFLAGS FFLAGS FCFLAGS LDFLAGS CC CXX FC AR NM RANLIB
+ /usr/bin/make -O -j48 V=1 VERBOSE=1 PREFIX=/usr LIBDIR=/usr/lib64
make[1]: Entering directory '/home/tkloczko/rpmbuild/BUILD/pesign-115/include'
make[1]: warning: jobserver unavailable: using -j1.  Add '+' to parent make rule.
make[1]: Leaving directory '/home/tkloczko/rpmbuild/BUILD/pesign-115/include'
make[1]: Entering directory '/home/tkloczko/rpmbuild/BUILD/pesign-115/include'
make[1]: Nothing to be done for 'deps'.

[..]

/usr/bin/gcc -O2 -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fdata-sections -ffunction-sections -flto=auto -flto-partition=none -Os  -Wall -Wextra -Wsign-compare -Wno-unused-result -Wno-unused-function -Wno-missing-field-initializers -Wno-analyzer-malloc-leak -Werror -Wno-error=cpp -Wno-free-nonheap-object -std=gnu11 -fshort-wchar -fPIC -fno-strict-aliasing -D_GNU_SOURCE -DCONFIG_x86_64 -I/home/tkloczko/rpmbuild/BUILD/pesign-115/include '-DRUNDIR="/run/"'     -I/usr/include/efivar -I/usr/include/nss3 -I/usr/include/nspr4  -D_FORTIFY_SOURCE=2 -c -o daemon.o daemon.c
daemon.c: In function 'handle_unlock_token':
daemon.c:224:13: error: the comparison will always evaluate as 'true' for the address of 'value' will never be NULL [-Werror=address]
  224 |         if (!tp->value)
      |             ^
In file included from pesign.h:23,
                 from daemon.c:29:
daemon.h:25:17: note: 'value' declared here
   25 |         uint8_t value[];
      |                 ^~~~~
cc1: all warnings being treated as errors
make[1]: *** [/home/tkloczko/rpmbuild/BUILD/pesign-115/Make.rules:34: daemon.o] Error 1

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

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:

  • patch the code that came in later themselves
  • use the pesign release 113-21 which comes with e.g. CVE-2022-3560 so they need to secure their environments on another layer

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.

authvar: 4-byte EFI var attrs header in output files

Hi,

authvar writes .auth files with 4-byte EFI var attrs header before the authenticated variable itself. This throws off the format (compared to sbsigntools sign-efi-sig-list), and firmware does not accept the file as valid. Removing the 4 bytes, the generated .auth file is equivalent to one generated by sbsigntools, which is accepted by my firmware setup screen. Is there a particular reason for the extra 4 bytes?

This code adds the attributes to the output file:

/* The attribute of the variable */
memcpy(ptr, &ctx->attr, sizeof(ctx->attr));
ptr += sizeof(ctx->attr);

My goal was to replace sign-efi-sig-list from sbsigntools with authvar to generate signed .auth files. For sbsigntools, I use:

cert-to-efi-sig-list -g $GUID PK.crt PK.esl
sign-efi-sig-list -t "$(date --date='1 second' +'%Y-%m-%d %H:%M:%S')" \
                  -k PK.key -c PK.crt PK PK.esl PK.auth

The authvar/efisecdb replacement is:

efisecdb -g "$GUID" -a -c PK.cer -o PK.esl
authvar -d "$nssdb" --set --valuefile PK.esl \
        --export PK.auth.tmp --sign "$signer" --name PK
dd if=PK.auth.tmp of=PK.auth bs=1 skip=4

116: is not gcc 14.x ready (buid fails with ` [-Werror=calloc-transposed-args]`)

Looks like last version build fails with latest gcc 14.x which is now used in fedora rawhide.

Build fails with
/usr/bin/gcc -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -O2 -g -grecord-gcc-switches -pipe -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer -fdata-sections -ffunction-sections -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -flto=auto -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -Wall -Werror=format-security -Os  -Wall -Wextra -Wsign-compare -Wno-unused-result -Wno-unused-function -Wno-missing-field-initializers  -Werror -Wno-error=cpp -Wno-free-nonheap-object -std=gnu11 -fshort-wchar -fPIC -fno-strict-aliasing -D_GNU_SOURCE -DCONFIG_x86_64 -I/home/tkloczko/rpmbuild/BUILD/pesign-116/include '-DRUNDIR="/run/"'     -I/usr/include/efivar -I/usr/include/nss3 -I/usr/include/nspr4 -D_FORTIFY_SOURCE=2 -D_GLIBCXX_ASSERTIONS -c -o pesigcheck.o pesigcheck.c
pesigcheck.c: In function ‘check_signature’:
pesigcheck.c:243:34: error: ‘calloc’ sizes specified with ‘sizeof’ in the earlier argument and not in the later argument [-Werror=calloc-transposed-args]
  243 |         reasonps = calloc(sizeof(struct reason), 512);
      |                                  ^~~~~~
pesigcheck.c:243:34: note: earlier argument should specify number of elements, later size of each element
pesigcheck.c:284:53: error: ‘calloc’ sizes specified with ‘sizeof’ in the earlier argument and not in the later argument [-Werror=calloc-transposed-args]
  284 |                         new_reasons = calloc(sizeof(struct reason), num_reasons);
      |                                                     ^~~~~~
pesigcheck.c:284:53: note: earlier argument should specify number of elements, later size of each element
cc1: all warnings being treated as errors

efikeygen --ca doesn't work

There are multiple problems after --kernel and --module were added.

First problem is that validating params fails. It looks like this change will fix that part:

-       if (modsign_only < 1 || modsign_only > 2)
-               errx(1, "either --kernel or --module must be used");
+       if ((modsign_only < 1 || modsign_only > 2) && is_ca < 1)
+               errx(1, "either --ca or --kernel or --module must be used");

But after that creating ca fails with:

efikeygen.c:add_extended_key_usage:262: could not encode extended key usage: Success
efikeygen.c:add_extensions_to_crq:339: could not generate certificate extensions: Success

I don't see is_ca handled at all in the code wich checks for modsign_only, I'd guess every where there should be check for is_ca too.

Compilation failure

pesign fails to compile on reasonably modern Linux

/usr/bin/gcc -O2 -g  -Wall -Werror -Wno-cpp  -Wsign-compare -Wno-unused-result -Wno-unused-function -std=gnu11 -fshort-wchar -fPIC -lto -fno-strict-aliasing -fno-merge-constants -D_GNU_SOURCE -DCONFIG_x86_64 -I/home/user/cvs/pesign/include      -Werror  -c -o pe_allocspace.o pe_allocspace.c
pe_allocspace.c: In function ‘pe_set_image_size’:
pe_allocspace.c:76:13: error: ‘shdr.virtual_address’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
  image_size = shdr.virtual_address - opthdr->image_base +
             ^
pe_allocspace.c:54:35: error: ‘shdr.virtual_size’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
 #define align(val, align) (((val) + (align) -1 ) & (- (align)))
                                   ^
pe_allocspace.c:64:24: note: ‘shdr.virtual_size’ was declared here
  struct section_header shdr, tmp_shdr;
                        ^
cc1: all warnings being treated as errors
make[1]: *** [pe_allocspace.o] Error 1

Certificate extension not found error

I'm trying to get pesign to sign using a key and cert I have on a yubikey, but it errors complaining about "Certificate extension not found":

$ /tmp/zz/pesign/src/pesign --certdir=$PWD -t "PIV_II (PIV Card Holder pin)" -c "/CN=Debian Test Secure Boot Signer" --sign -i /boot/efi/EFI/debian/grubx64.efi -o signed.efi
Enter Password or Pin for "PIV_II (PIV Card Holder pin)":
cms_common.c:find_certificate:470: could not find certificate in list: Certificate extension not found.
pesign: Could not find certificate /CN=Debian Test Secure Boot Signer

I followed the recipe from https://fedoraproject.org/wiki/User:Pjones/SecureBootSmartCardDeployment on how to generate the certs, and https://dennis.silvrback.com/openssl-ca-with-yubikey-neo for loading it onto the smart card.

What certificate extension is it looking for?

Fails to build against NSS 3.44

Regressed by Mozilla bug 1537927 (NS_CERT_TYPE_IPSEC). See error log.

GCC 8.3:

In file included from /usr/include/nss/cert.h:22,
                 from efikeygen.c:41:
efikeygen.c: In function 'add_cert_type':
/usr/include/nss/certt.h:445:5: error: unsigned conversion from 'int' to 'unsigned char' changes value from '496' to '240' [-Werror=overflow]
     (NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_SSL_SERVER | NS_CERT_TYPE_EMAIL | \
     ^
efikeygen.c:211:23: note: in expansion of macro 'NS_CERT_TYPE_APP'
  unsigned char type = NS_CERT_TYPE_APP;
                       ^~~~~~~~~~~~~~~~

Clang 8.0:

efikeygen.c:211:23: error: implicit conversion from 'int' to 'unsigned char' changes value from 496 to 240
      [-Werror,-Wconstant-conversion]
        unsigned char type = NS_CERT_TYPE_APP;
                      ~~~~   ^~~~~~~~~~~~~~~~
/usr/include/nss/certt.h:446:25: note: expanded from macro 'NS_CERT_TYPE_APP'
     NS_CERT_TYPE_IPSEC | NS_CERT_TYPE_OBJECT_SIGNING)
     ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

gcc-12 doesn't play nice

On Fedora rawhide, with 2b2ed4e we get:

...
gcc -O2 -g3 -pipe -fPIE -fstack-protector-all -fstack-clash-protection -fcf-protection=full  -Wall -Wextra -Wsign-compare -Wno-unused-result -Wno-unused-function -Wno-missing-field-initializers -Wno-analyzer-malloc-leak -Werror -Wno-error=cpp -Wno-free-nonheap-object -std=gnu11 -fshort-wchar -fPIC -fno-strict-aliasing -D_GNU_SOURCE -DCONFIG_x86_64 -I/root/pesign/include '-DRUNDIR="/run/"'   -Wmaybe-uninitialized -grecord-gcc-switches -fplugin=annobin  -fmessage-length=0 -fdiagnostics-color=always -fdiagnostics-format=text -fdiagnostics-show-cwe -fanalyzer  -I/usr/include/efivar -I/usr/include/nss3 -I/usr/include/nspr4  -D_FORTIFY_SOURCE=2 -c -o cms_common.o cms_common.c
In file included from util.h:22,
                 from pesign.h:18,
                 from cms_common.c:21:
cms_common.c: In function ‘cms_context_fini’:
compiler.h:77:77: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘-’ token
   77 |         _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1)
      |                                                                             ^
compiler.h:59:39: note: in definition of macro ‘__compiletime_assert’
   59 |                 extern void prefix ## suffix(void) __compiletime_error(msg); \
      |                                       ^~~~~~
compiler.h:77:9: note: in expansion of macro ‘_compiletime_assert’
   77 |         _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1)
      |         ^~~~~~~~~~~~~~~~~~~
compiler.h:86:37: note: in expansion of macro ‘compiletime_assert’
   86 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
      |                                     ^~~~~~~~~~~~~~~~~~
list.h:30:9: note: in expansion of macro ‘BUILD_BUG_ON_MSG’
   30 |         BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&   \
      |         ^~~~~~~~~~~~~~~~
list.h:458:9: note: in expansion of macro ‘container_of’
  458 |         container_of(ptr, type, member)
      |         ^~~~~~~~~~~~
cms_common.c:200:37: note: in expansion of macro ‘list_entry’
  200 |                 pk12_file_t *file = list_entry(pos, pk12_file_t, list);
      |                                     ^~~~~~~~~~
compiler.h:59:46: error: expected expression before ‘void’
   59 |                 extern void prefix ## suffix(void) __compiletime_error(msg); \
      |                                              ^~~~
compiler.h:65:9: note: in expansion of macro ‘__compiletime_assert’
   65 |         __compiletime_assert(condition, msg, prefix, suffix)
      |         ^~~~~~~~~~~~~~~~~~~~
compiler.h:77:9: note: in expansion of macro ‘_compiletime_assert’
   77 |         _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1)
      |         ^~~~~~~~~~~~~~~~~~~
compiler.h:86:37: note: in expansion of macro ‘compiletime_assert’
   86 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
      |                                     ^~~~~~~~~~~~~~~~~~
list.h:30:9: note: in expansion of macro ‘BUILD_BUG_ON_MSG’
   30 |         BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&   \
      |         ^~~~~~~~~~~~~~~~
list.h:458:9: note: in expansion of macro ‘container_of’
  458 |         container_of(ptr, type, member)
      |         ^~~~~~~~~~~~
cms_common.c:200:37: note: in expansion of macro ‘list_entry’
  200 |                 pk12_file_t *file = list_entry(pos, pk12_file_t, list);
      |                                     ^~~~~~~~~~
compiler.h:77:79: error: called object is not a function or function pointer
   77 |         _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1)
      |                                                                               ^
compiler.h:59:39: note: in definition of macro ‘__compiletime_assert’
   59 |                 extern void prefix ## suffix(void) __compiletime_error(msg); \
      |                                       ^~~~~~
compiler.h:77:9: note: in expansion of macro ‘_compiletime_assert’
   77 |         _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1)
      |         ^~~~~~~~~~~~~~~~~~~
compiler.h:86:37: note: in expansion of macro ‘compiletime_assert’
   86 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
      |                                     ^~~~~~~~~~~~~~~~~~
list.h:30:9: note: in expansion of macro ‘BUILD_BUG_ON_MSG’
   30 |         BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&   \
      |         ^~~~~~~~~~~~~~~~
list.h:458:9: note: in expansion of macro ‘container_of’
  458 |         container_of(ptr, type, member)
      |         ^~~~~~~~~~~~
cms_common.c:200:37: note: in expansion of macro ‘list_entry’
  200 |                 pk12_file_t *file = list_entry(pos, pk12_file_t, list);
      |                                     ^~~~~~~~~~
compiler.h:77:45: error: ‘__compiletime_assert_200’ undeclared (first use in this function); did you mean ‘_compiletime_assert’?
   77 |         _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1)
      |                                             ^~~~~~~~~~~~~~~~~~~~~
compiler.h:61:25: note: in definition of macro ‘__compiletime_assert’
   61 |                         prefix ## suffix();                             \
      |                         ^~~~~~
compiler.h:77:9: note: in expansion of macro ‘_compiletime_assert’
   77 |         _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1)
      |         ^~~~~~~~~~~~~~~~~~~
compiler.h:86:37: note: in expansion of macro ‘compiletime_assert’
   86 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
      |                                     ^~~~~~~~~~~~~~~~~~
list.h:30:9: note: in expansion of macro ‘BUILD_BUG_ON_MSG’
   30 |         BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&   \
      |         ^~~~~~~~~~~~~~~~
list.h:458:9: note: in expansion of macro ‘container_of’
  458 |         container_of(ptr, type, member)
      |         ^~~~~~~~~~~~
cms_common.c:200:37: note: in expansion of macro ‘list_entry’
  200 |                 pk12_file_t *file = list_entry(pos, pk12_file_t, list);
      |                                     ^~~~~~~~~~
compiler.h:77:45: note: each undeclared identifier is reported only once for each function it appears in
   77 |         _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1)
      |                                             ^~~~~~~~~~~~~~~~~~~~~
compiler.h:61:25: note: in definition of macro ‘__compiletime_assert’
   61 |                         prefix ## suffix();                             \
      |                         ^~~~~~
compiler.h:77:9: note: in expansion of macro ‘_compiletime_assert’
   77 |         _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1)
      |         ^~~~~~~~~~~~~~~~~~~
compiler.h:86:37: note: in expansion of macro ‘compiletime_assert’
   86 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
      |                                     ^~~~~~~~~~~~~~~~~~
list.h:30:9: note: in expansion of macro ‘BUILD_BUG_ON_MSG’
   30 |         BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&   \
      |         ^~~~~~~~~~~~~~~~
list.h:458:9: note: in expansion of macro ‘container_of’
  458 |         container_of(ptr, type, member)
      |         ^~~~~~~~~~~~
cms_common.c:200:37: note: in expansion of macro ‘list_entry’
  200 |                 pk12_file_t *file = list_entry(pos, pk12_file_t, list);
      |                                     ^~~~~~~~~~
compiler.h:77:79: error: called object is not a function or function pointer
   77 |         _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1)
      |                                                                               ^
compiler.h:61:35: note: in definition of macro ‘__compiletime_assert’
   61 |                         prefix ## suffix();                             \
      |                                   ^~~~~~
compiler.h:77:9: note: in expansion of macro ‘_compiletime_assert’
   77 |         _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__ - 1)
      |         ^~~~~~~~~~~~~~~~~~~
compiler.h:86:37: note: in expansion of macro ‘compiletime_assert’
   86 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
      |                                     ^~~~~~~~~~~~~~~~~~
list.h:30:9: note: in expansion of macro ‘BUILD_BUG_ON_MSG’
   30 |         BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) &&   \
      |         ^~~~~~~~~~~~~~~~
list.h:458:9: note: in expansion of macro ‘container_of’
  458 |         container_of(ptr, type, member)
      |         ^~~~~~~~~~~~
cms_common.c:200:37: note: in expansion of macro ‘list_entry’
  200 |                 pk12_file_t *file = list_entry(pos, pk12_file_t, list);
      |                                     ^~~~~~~~~~
make[1]: *** [/root/pesign/Make.rules:34: cms_common.o] Error 1
make[1]: Leaving directory '/root/pesign/src'
make: *** [Makefile:29: all] Error 2
[root@rawhide-efi pesign]# gcc --version
gcc (GCC) 12.0.1 20220118 (Red Hat 12.0.1-0)
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

[root@rawhide-efi pesign]# 

Failure to build with GCC 11

gcc -O2 -g3 -pipe -fPIE -fstack-protector-all -fstack-clash-protection -fcf-protection=full  -Wall -Wextra -Wsign-compare -Wno-unused-result -Wno-unused-function -Wno-missing-field-initializers -Wno-analyzer-malloc-leak -Werror -Wno-error=cpp -Wno-free-nonheap-object -std=gnu11 -fshort-wchar -fPIC -fno-strict-aliasing -D_GNU_SOURCE -DCONFIG_x86_64 -I/home/sam/git/pesign/include '-DRUNDIR="/run/"'   -Wmaybe-uninitialized -grecord-gcc-switches  -fmessage-length=0 -fdiagnostics-color=always -fdiagnostics-format=text -fdiagnostics-show-cwe -fanalyzer  -I/usr/include/efivar -I/usr/include/nss -I/usr/include/nspr  -D_FORTIFY_SOURCE=2 -c -o pesign.o pesign.c
gcc -O2 -g3 -pipe -fPIE -fstack-protector-all -fstack-clash-protection -fcf-protection=full  -Wall -Wextra -Wsign-compare -Wno-unused-result -Wno-unused-function -Wno-missing-field-initializers -Wno-analyzer-malloc-leak -Werror -Wno-error=cpp -Wno-free-nonheap-object -std=gnu11 -fshort-wchar -fPIC -fno-strict-aliasing -D_GNU_SOURCE -DCONFIG_x86_64 -I/home/sam/git/pesign/include '-DRUNDIR="/run/"'   -Wmaybe-uninitialized -grecord-gcc-switches  -fmessage-length=0 -fdiagnostics-color=always -fdiagnostics-format=text -fdiagnostics-show-cwe -fanalyzer  -I/usr/include/efivar -I/usr/include/nss -I/usr/include/nspr  -D_FORTIFY_SOURCE=2 -c -o daemon.o daemon.c
daemon.c:922:32: error: unknown option after ‘#pragma GCC diagnostic’ kind [-Werror=pragmas]
  922 | #pragma GCC diagnostic ignored "-Wanalyzer-use-of-uninitialized-value"
      |                                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
make[1]: *** [/home/sam/git/pesign/Make.rules:34: daemon.o] Error 1
make[1]: Leaving directory '/home/sam/git/pesign/src'
make: *** [Makefile:29: all] Error 2

Noticed when building on Gentoo Linux with gcc (Gentoo Hardened 11.2.1_p20220115 p4) 11.2.1 20220115. I'm guessing that maybe GCC 12 allows this but GCC 11 doesn't.

Full log: build.log

[RFE] pesign.service: run as separate user

Hi! I'm currently maintaining pesign for Arch Linux.

When taking over the package from my predecessor I started to wonder about the pesign.service setup.
In its current state it is not possible to enable the service (#50) and its stdout/stderr is not sent to the journal (#49).

More puzzling for me is the pesign-authorize script though, as it sets ACLs

update_subdir() {
subdir=$1 && shift
setfacl -bk "${subdir}"
setfacl "${dirusers[@]}" "${dirgroups[@]}" "${subdir}"
for x in "${subdir}"* ; do
if [ -d "${x}" ]; then
setfacl -bk ${x}
setfacl "${dirusers[@]}" "${dirgroups[@]}" ${x}
update_subdir "${x}/"
elif [ -e "${x}" ]; then
setfacl -bk ${x}
setfacl "${fileusers[@]}" "${filegroups[@]}" ${x}
else
:;
fi
done
}

for arbitrary users
for user in $(cat /etc/pesign/users); do

and groups
for group in $(cat /etc/pesign/groups); do

on the runtime dir and config dir
for x in /var/run/pesign/ /etc/pki/pesign*/ ; do
if [ -d "${x}" ]; then
update_subdir "${x}"
else
:;
fi

This introduces the two following culprits:

  • pesign.service can not be run as a non-root user
  • users (or users in specific groups) can add more users or groups to the allowed set of users or groups (due to the /etc/pki/pesign*/ match) (whoops, those are set in /etc/pesign/)

From a security perspective this is rather suboptimal.

Maybe I'm not understanding the specific use-cases that you had in mind when creating the service, but in its current state it does not make sense for me to package the configuration files or the service, but rather to create a service file myself.

When looking at this from a classic sysadmin perspective, I'd assume that I would create a system user/group that runs the service and that I then either add any user of a system to said group to have access to what the service creates and that I optionally have a socket unit, that gives access to the socket, that the service creates/uses if this is a requirement for e.g. pesign-client (the latter is seemingly discussed in another context in #35).

Any suggestions or explanations in regards to my assumptions would be highly appreciated! :)

pesign daemon treats stdin as a tty and crashes

Hi,

I'm trying to setup pesign with a yubikey. When using standalone pesign, interactively, things seem to work, but I want a noninteractive signing process, so was looking at the daemon/client stuff. Unfortunately, even after running pesign-client --unlock, pesign-client --sign causes the daemon side to die because sign_blob sets the password func to readpw, which assumes that stdin is a tty. Then calculate_signature_space calls exit(1) which kills the daemon.

It seems like in daemon mode, the pin passed to pesign-client --unlock should maybe be reused for signing? Or maybe --sign should accept the --pinfile/--pinfd options and use them?

Signed shim signature cannot be verified by UEFI BIOS

I used pesign for signing shim (https://github.com/rhboot/shim), new UEFI BIOS does not validate shim's signature. To verify whether I have signed properly, I signed a grubx64.efi image using the same process, grubx64.efi signature was successfully verified by UEFI BIOS. I used the following method to sign shim and grub

Generated keys (PK.crt (CA), db.key, db.crt, db.p12)
Create certificate db and add required certificates

mkdir certdb
certutil -N -d certdb
certutil -A -n 'PK' -d certdb -t CT,CT,CT -i ../keys/PK.crt #(Add PK.crt))
pk12util -d certdb -i db.p12 #(Add db.p12)
certutil -d certdb -A -i ../keys/db.crt -n "my Signature Database key" -t u #(Add db certificate)
Sign using pesign

pesign -n certdb -c "my Signature Database key" -s -i grubx64.efi -o grubx64_pesign_signed.efi
pesign -n certdb -c "my Signature Database key" -s -i shimx64.efi -o shimx64_pesign_signed.efi

To verify the signature I used sbverify tool (I could not find any other better tool)

sbverify --cert db,crt grubx64_pesign_signed.efi
Output: Signature verification OK

sbverify --cert db.crt shimx64_pesign_signed.efi
Output:
warning: data remaining[1124760 vs 1282576]: gaps between PE/COFF sections?
Signature verification OK

I think the warning might be the cause for signature verification failure?

Could you please advice on how to resolve this?

socket_get_fd() failing due to SCM_CREDENTIALS coming first

socket_get_fd() as currently implemented can receive only one ancilliary message of size 'int' (SCM_RIGHTS)

However, in daemon.c we do:

        int one = 1;                                                                                                                           
        int rc = setsockopt(sd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));                                                                   
        if (rc < 0) {                                                                                                                          
                ctx->backup_cms->log(ctx->backup_cms, ctx->priority|LOG_ERR,                                                                   
                        "unable to set socket options: %m");                                                                                   
                exit(1);                                                                                                                       
        }                                                                                                                                      

This appear to affect both "sides" of the socket (kernel 5.10.68), so the messages coming in from the client with the file descriptors attached have an SCM_CREDENTIALS message attached to them.

For some obscure reason, on my setup, that SCM_CREDENTIALS is the first ancilliary message though, and SCM_RIGHTS ends up being second. (They seem to get re-ordered, I assume by the kernel...).

strace thus shows this failure:

ppoll([{fd=45, events=POLLIN|POLLPRI|POLLHUP}], 1, NULL, NULL, 8) = 1 ([{fd=45, revents=POLLIN}])
accept(45, {sa_family=AF_UNIX}, [110->2]) = 46
recvmsg(46, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\313A\317\243\2\0\0\0$\0\0\0", iov_len=12}], msg_iovlen=1, msg_control=[{cmsg_len=28, cmsg_level=SOL_SOCKET, cmsg_type=SCM_CREDENTIALS, cmsg_data={pid=14966, uid=1000, gid=993}}], msg_controllen=32, msg_flags=0}, MSG_WAITALL) = 12
recvmsg(46, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\16\0\0\0test-sign-key\0\16\0\0\0test-sign-"..., iov_len=36}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CTRUNC}, MSG_WAITALL) = 36
recvmsg(46, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\0\0", iov_len=2}], msg_iovlen=1, msg_control=[{cmsg_len=24, cmsg_level=SOL_SOCKET, cmsg_type=SCM_CREDENTIALS}], msg_controllen=24, msg_flags=MSG_CTRUNC}, MSG_WAITALL) = 2

Followed by "unlock-token: invalid data"

You can see the last recvmsg has MSG_CTRUNC set, so we don't have enough buffer for everything. Now, if I arbitrarily increase the control buffer size as follow:

        size_t controllen = CMSG_SPACE(sizeof(int)) + 100;                                                                                     

Then the strace output becomes:

recvmsg(46, {msg_name=NULL, msg_namelen=0, msg_iov=[{iov_base="\0\0", iov_len=2}], msg_iovlen=1, msg_control=[{cmsg_len=28, cmsg_level=SOL_SOCKET, cmsg_type=SCM_CREDENTIALS, cmsg_data={pid=15059, uid=1000, gid=993}}, {cmsg_len=20, cmsg_level=SOL_SOCKET, cmsg_type=SCM_RIGHTS, cmsg_data=[47]}], msg_controllen=56, msg_flags=0}, MSG_WAITALL) = 2

As you can observe, SCM_RIGHTS is second.

My local workaround is to take out the setsockopt completely... why do we set SO_PASSCRED ? I can't see us actually using those credentials anywhere, or am I missing something ?

If we want to keep it, then we need to improve socket_get_fd() a bit to pass a buffer large enough, and iterate the CMSG HDR's ...

Happy to provide patches/pull requests on demand, based on what you think is the best approach

build fails with undefined reference to symbol pthread_rwlock_rwlock

Continuing from #15 since non-contributors cannot reopen a closed task and the thing still doesn't build. As mentioned in the last comment,

libdpe is using the function the linker is complaining about; see the calls to rwlock_wrlock() which are translated via preprocessor defines to pthread_rwlock_wrlock().

Indeed, libdpe/lock.h has this:

#define RWLOCK_CALL(call) \
    ({ int _err = pthread_rwlock_ ## call; assert_perror(_err); })
[...]
#define rwlock_wrlock(lock) RWLOCK_CALL(wrlock (&lock))

So it very much looks like pesign is trying to use the function directly, and so should -lpthread directly.

And yes, I see that libdpe/Makefile has LIBS=pthread. That seems to work fine for the shared library (libdpe.so), but pesign itself uses the static library (libdpe.a) and I don't believe static libs even have a place to record this kind of information?

[question] how to attach a signature?

Hi,

I generated a detached signature using the following arguments:

pesign -i bootx64.efi --export-signature bootx64.sig --sign -d sha256 -t "PIV_II (PIV Card Holder pin)" -c "Certificate for Digital Signature" -n $CERTDIR

Now how can I attach bootx64.sig with bootx64.efi ?

I tried with --import-raw-signature without success

Thanks for your help

pesigchek signature validation fails for binary signed by expired certificate

pesigcheck failed to validate signatures done by expired certificate.

Per my understanding validation supposed to work for test certificate in order to verify that signatures work with expired certificates in the hardware.

$ certutil -L -d pesign-test -n "Test Certificate" -r > ./pesign_test.der
$ openssl x509 -in pesign_test.der -inform DER -text | grep -A2 Validity
        Validity
            Not Before: Sep  7 23:00:00 2019 GMT
            Not After : Sep  7 23:00:00 2020 GMT
$ pesign -s -n pesign-test/ -c "Test Certificate" -i vmlinuz.unsigned -o vmlinuz.signed
$ pesign -S -i vmlinuz.signed
---------------------------------------------
certificate address is 0x7f52c47b9988
Content was not encrypted.
Content is detached; signature cannot be verified.
The signer's common name is Test Certificate
No signer email address.
Signing time: Thu Sep 17, 2020
There were certs or crls included.
---------------------------------------------
$ pesigcheck -n 0 -c pesign_test.der -i vmlinuz.signed -v
Searching db pesign_test.der
Searching db pesign_test.der
Signature has impossible time constraint: 1600385627 <= 1599519600
Peer's Certificate has expired.
No matching whitelist entry.
pesigcheck: "vmlinuz.signed" is invalid.

Please confirm that pesigcheck expected to validate signatures done with expired certificate. Based on implementation I came to conclusion it was presumed while there is a "atTime" calculation issue in the code.

pesign/src/certdb.c

Lines 369 to 391 in e0ea290

notBefore = earlyNow;
notAfter = lateNow;
find_cert_times(cinfo, &notBefore, &notAfter);
if (earlyNow < notBefore)
earlyNow = notBefore;
if (lateNow > notAfter)
lateNow = notAfter;
// atTime = determine_reasonable_time(cert);
eTime = SEC_PKCS7GetSigningTime(cinfo);
if (eTime != NULL) {
if (DER_DecodeTimeChoice (&atTime, eTime) == SECSuccess) {
if (earlyNow < atTime)
earlyNow = atTime;
if (lateNow > atTime)
lateNow = atTime;
}
}
if (lateNow < earlyNow)
printf("Signature has impossible time constraint: %lld <= %lld\n",
earlyNow / 1000000LL, lateNow / 1000000LL);
atTime = earlyNow / 2 + lateNow / 2;

Removing signature does not produce the original unsigned binary

Hi,

I've found a bug in signature remove code: pesign would exit before removing signature if you don't specify signum explicitly with -u option.

The patch is trivial:

diff --git a/src/file_pe.c b/src/file_pe.c
index 805e614..407d27d 100644
--- a/src/file_pe.c
+++ b/src/file_pe.c
@@ -231,6 +231,8 @@ pe_handle_action(pesign_context *ctxp, int action, int padding)
                        open_input(ctxp);
                        open_output(ctxp);
                        close_input(ctxp);
+                       if (ctxp->signum < 0)
+                               ctxp->signum = 0;
                        if(ctxp->signum < 0 ||
                           ctxp->signum >= ctxp->cms_ctx->num_signatures) {
                                warnx("Invalid signature number %d.",

By a lucky coincidence original code did exactly what was expected. open_output function created a copy of the input file and then did pe_clearcert after which pesign exited with error.

But fixing this bug uncovered that continuing REMOVE_SIGNATURE action calls close_output->finalize_signatures->implant_cert_list->pe_alloccert which populates Security Data Directory with zero size data:

dd->certs.virtual_address = compute_file_addr(pe, addr);
dd->certs.size += size;

I would assume that somewhere in this call chain should be a check for size == 0 but not sure exactly where.



The other issue is that removing signature does not produce the original file because of the alignment:

@@ -57558,5 +57558,5 @@
 000e32a0  00 6c 6f 61 64 5f 6f 70  74 69 6f 6e 73 00 50 4b  |.load_options.PK|
 000e32b0  45 59 5f 55 53 41 47 45  5f 50 45 52 49 4f 44 5f  |EY_USAGE_PERIOD_|
 000e32c0  69 74 00 58 35 30 39 5f  4e 41 4d 45 5f 45 4e 54  |it.X509_NAME_ENT|
-000e32d0  52 59 5f 69 74 00                                 |RY_it.|
-000e32d6
+000e32d0  52 59 5f 69 74 00 00 00                           |RY_it...|
+000e32d8

[RFE] Blockable hash list

It would be great if pesign could give an overview of all hashes that could be in the DBX database.
So, hash of the binary itself, hash of the certificate it's signed with, and hash of the signature.
This would allow to easily verify whether a particular binary is blocked on a system.

pesign-client -k fail to kill the daemon sometimes

In centos 8.
A test shell , using pesign-client -k to kill pesign daemon and using systemctl restart pesign to start daemon, using pesign-client --kill to kill pesign daemon and using systemctl restart pesign to start daemon。 After kill daemon, using systemctl status pesign to check whether process is dead. After restart pesign service, using systemctl status pesign to check whether process is running.
Loop 100 times, the result is 128 times killing success and 72 times fail.
"
for ((i=1;i<=100;i++)) do
pesign-client -k
check_pesign_service_status
#success++ if status is dead and fail++ if status is running

systemctl restart pesign
check_pesign_service_status
#just check

pesign-client --kill
check_pesign_service_status
#success++ if status is dead and fail++ if status is running

systemctl restart pesign
check_pesign_service_status
#just check

done
"
Question: pesign-client -k just send CMD_KILL_DAEMON to daemon and not receive daemon response. Current code implementation cannot sure the daemon receive message and exit. Why daemon not send response to client? Why the client not use "systemctl stop pesign" to kill daemon ?

handle_signing: invalid data \n possible exploit attempt. closing.

When I run

/usr/bin/pesign-client -t 'Fermi National Accelerator Labor' -c 'Fermi National Accelerator Laboratory' -i /usr/share/shim/x64-15.6-3.sl7/shimx64.efi -o shimx64-redhat.efi -s

from the system the shim is signed just fine.

However, when I run it from inside of mock I receive:

Jul 12 10:09:04 sl7-uefisign.fnal.gov pesignd[22977]: searching for command 2
Jul 12 10:09:04 sl7-uefisign.fnal.gov pesignd[22977]: cmd-version: found command "sign-attached" version 0
Jul 12 10:09:04 sl7-uefisign.fnal.gov pesignd[22977]: handle_signing: invalid data
Jul 12 10:09:04 sl7-uefisign.fnal.gov pesignd[22977]: possible exploit attempt. closing.

I'm open to suggestions on how to diagnose the differences between the two...

Can't build with LLVM/clang

I'm building pesing-0.112 with LLVM/clang-7.x

Here is the first issue

+ /usr/bin/make -O -j32 PREFIX=/usr LIBDIR=/usr/lib64
make[1]: Nothing to be done for 'deps'.
/usr/bin/make -f /builddir/build/BUILD/pesign-0.112/Make.deps deps SOURCES="pe_nextscn.c libdpe.c pe_rawfile.c pe_allocspace.c pe_opthdr.c pe_updatenull.c pe_error.c pe_updatefile.c pe_getscn.c pe_getdatadir.c pe_getshdr.c pe_readall.c pe_addcert.c pe_end.c pe_begin.c pe_getpehdr.c pe_update.c"
make[2]: Entering directory '/builddir/build/BUILD/pesign-0.112/libdpe'
/usr/bin/clang -Os -gdwarf-4 -Wstrict-aliasing=2 -pipe -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -fstack-protector-strong --param=ssp-buffer-size=4  -fPIC -flto -Qunused-arguments  -Wall -Werror -Wno-cpp  -Wsign-compare -Wno-unused-result -Wno-unused-function -std=gnu11 -fshort-wchar -fPIC -flto -fno-strict-aliasing -fno-merge-constants -fkeep-inline-functions -D_GNU_SOURCE -DCONFIG_x86_64 -I/builddir/build/BUILD/pesign-0.112/include      -Werror  -MM -MG -MF .pe_allocspace.d pe_allocspace.c
make[2]: Leaving directory '/builddir/build/BUILD/pesign-0.112/libdpe'
BUILDSTDERR: clang-7: error: optimization flag '-fno-merge-constants' is not supported [-Werror,-Wignored-optimization-argument]
BUILDSTDERR: clang-7: error: optimization flag '-fkeep-inline-functions' is not supported [-Werror,-Wignored-optimization-argument]
BUILDSTDERR: make[2]: *** [/builddir/build/BUILD/pesign-0.112/Make.deps:9: .pe_allocspace.d] Error 1
BUILDSTDERR: make[2]: *** Waiting for unfinished jobs....

Here is the second issue:

make[1]: Entering directory '/builddir/build/BUILD/pesign-0.112/libdpe'
/usr/bin/clang -Os -gdwarf-4 -Wstrict-aliasing=2 -pipe -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -fstack-protector-strong --param=ssp-buffer-size=4  -fPIC -flto -Qunused-arguments -Wno-error=ignored-optimization-argument  -Wall -Werror -Wno-cpp  -Wsign-compare -Wno-unused-result -Wno-unused-function -std=gnu11 -fshort-wchar -fPIC -flto -fno-strict-aliasing -fno-merge-constants -fkeep-inline-functions -D_GNU_SOURCE -DCONFIG_x86_64 -I/builddir/build/BUILD/pesign-0.112/include      -Werror  -c -o pe_opthdr.o pe_opthdr.c
make[1]: Leaving directory '/builddir/build/BUILD/pesign-0.112/libdpe'
BUILDSTDERR: clang-7: warning: optimization flag '-fno-merge-constants' is not supported [-Wignored-optimization-argument]
BUILDSTDERR: clang-7: warning: optimization flag '-fkeep-inline-functions' is not supported [-Wignored-optimization-argument]
BUILDSTDERR: pe_allocspace.c:64:33: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
BUILDSTDERR:         struct section_header shdr = { 0, }, tmp_shdr;
BUILDSTDERR:                                        ^
BUILDSTDERR:                                        {}
BUILDSTDERR: 1 error generated.
BUILDSTDERR: make[1]: *** [/builddir/build/BUILD/pesign-0.112/Make.rules:33: pe_allocspace.o] Error 1
BUILDSTDERR: make[1]: *** Waiting for unfinished jobs...

Here you can find sources:
https://github.com/OpenMandrivaAssociation/pesign

Docker image isn't working for poweron -ppc64le

0.91s$ if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run vathpela/efi-ci-rawhide:v0 /bin/sh -c "cd /root/ && ./build.sh --branch "$TRAVIS_BRANCH" --commit "$TRAVIS_COMMIT" --commit-range "$TRAVIS_COMMIT_RANGE" --event-type "$TRAVIS_EVENT_TYPE" --pull-request "$TRAVIS_PULL_REQUEST" --pr-branch "$TRAVIS_PULL_REQUEST_BRANCH" --pr-sha "$TRAVIS_PULL_REQUEST_SHA" --remote "$TRAVIS_PULL_REQUEST_SLUG" --repo "$TRAVIS_REPO_SLUG" --test-subject pesign" ; fi
standard_init_linux.go:211: exec user process caused "exec format error".

Starting docker image is failing on power on , Its probably due to the fact that the image isn't compiled for poweron -ppc64le,Can you check ?

couple of suggest to support power on,Can you pls help; to incorporate ?

1- The images for ppc64le can be built and pushed manually by doing native builds on ppc64le VMs available via OSU, OSL https://osuosl.org/services/powerdev/request_hosting/ (do let me know if you choose to go via that path and I can share more specific details). Once the Power images are published, multiarch manifests can be used https://www.docker.com/blog/multi-arch-build-and-images-the-simple-way/ to ensure support across different architectures, this would need to be created and published as well.
2- The process can be automated via travis-ci using multi-stage travis builds as shown here https://www.youtube.com/watch?v=_PbpRETbpow
3- not ideal from a performance perspective, but we can do cross-builds using docker buildx.

pesign creates bad signatures in some cases

pesign signed our kernels with a signature that didn't match the output file. It turned out that inserting the certs calls pe_set_image_size(), which pokes into the opthdr. But the header is included in the hash calculation, so modifying it changes the hash.

In other words, pesign -h prints a different value before/after signing.

I don't see the purpose of calling pe_set_image_size at all, because it doesn't seem to even look at the size of the certs. Also, the microsoft standard says that the certs don't get loaded into memory, which indicates to me that they should not be included in image_size.

Thus my suggestion is to remove pe_set_image_size() and the pe_get_file_alignment()/pe_get_scn_alignment() functions, as calling pe_set_image_size can only break the hash and doesn't seem to have any benefit.

pesignd token unlock status.

[Sat 16:57] so, it would be great if pesign-client could ask the server ''do you have key XX unlocked for me' and get a Yes/No reply

Migrate from /var/run/pesign to /run/pesign

Forwarding this from https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=964157:

Quoting from syslog:

| [...] systemd-tmpfiles[512]: [/usr/lib/tmpfiles.d/pesign.conf:1] Line references path below legacy directory /var/run/, updating /var/run/pesign → /run/pesign; please update the tmpfiles.d/ drop-in file accordingly.

AFAICT the /var/run/pesign should be replaced with /run/pesign.
FTR, it's not just present in /usr/lib/tmpfiles.d/pesign.conf but in several places of the source code, should maybe get adjusted to follow current best practices?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.