Over the last few days I’ve merged in the PKCS7 support into fwupd as an optional feature. I’ve done this for a few reasons:
- Some distributors of fwupd were disabling the GPG code as it’s GPLv3, and I didn’t feel comfortable saying just use no signatures
- Trusted vendors want to ship testing versions of firmware directly to users without first uploading to the LVFS.
- Some firmware is inherently internal use only and needs to be signed using existing cryptographic hardware.
- The gpgme code scares me.
Did you know GPGME is a library based around screen scraping the output of the gpg2
binary? When you perform an action using the libgpgme APIs you’re literally injecting a string into a pipe and waiting for it to return. You can’t even use libgcrypt (the thing that gpg2 uses) directly as it’s way too low level and doesn’t have any sane abstractions or helpers to read or write packaged data. I don’t want to learn LISP S-Expressions (yes, really) and manually deal with packing data just to do vanilla X509 crypto.
Although the LVFS instance only signs files and metadata with GPG at the moment I’ve added the missing bits into python-gnutls so it could become possible in the future. If this is accepted then I think it would be fine to support both GPG and PKCS7 on the server.
One of the temptations for X509 signing would be to get a certificate from an existing CA and then sign the firmware with that. From my point of view that would be bad, as any firmware signed by any certificate in my system trust store to be marked as valid, when really all I want to do is check for a specific (or a few) certificates that I know are going to be providing certified working firmware. Although I could achieve this to some degree with certificate pinning, it’s not so easy if there is a hierarchical trust relationship or anything more complicated than a simple 1:1 relationship.
So this is possible I’ve created a LVFS CA certificate, and also a server certificate for the specific instance I’m running on OpenShift. I’ve signed the instance certificate with the CA certificate and am creating detached signatures with an embedded (signed-by-the-CA) server certificate. This seems to work well, and means we can issue other certificates (or CRLs) if the server ever moves or the trust is compromised in some way.
So, tl;dr: (should have been at the top of this page…) if you see a /etc/pki/fwupd/LVFS-CA.pem
appear on your system in the next release you can relax. Comments, especially from crypto experts welcome. Thanks!
I hope your CA private key is on a yubikey or similar hw token?
It’d be worrying if it is just stored on a March ne that is connected to the network.
It’s not (yet) but it is stored on a USB key in my drawer. I’ll look at the yubikey idea — do you have any recommendations?
Danielle wrote about the different kinds of hardware tokens and made a library to use them from Python that abstracts away a lot of the OpenSSL library horrors:
https://blogs.gnome.org/danni/2017/06/06/applied-pkcs11/
http://python-pkcs11.readthedocs.io/en/latest/applied.html