In 2015 I wrote a bit about Microsoft Catalog files and threatened to invent a new specification if nobody else stepped up to the plate. Microsoft have still not documented the format, and have seemingly broken the on-disk file format at least once, and there’s still no easy way we can write these files in Linux. Yesterday was a long day, and I think I have a prototype I want to share with the world now. Lets go back a bit first, what is a catalog file anyway?
A catalog file is a container format that can hold any number of signatures for external files. The data files themselves are not contained in the catalog, only the signatures. Detached signatures are something we’re familiar with in Linux, typically in the form of .asc
files for GPG and .p7b
files for PKCS-7 protocols. Detached files are something we also generate on the LVFS and consume in fwupd and this is the reason you can see more than just the README.txt
, firmware.bin
and firmware.metainfo.xml
in the cabinet archive:
The bug we’re trying to fix was we wanted to sign the metainfo file too so we can be sure that it came from the LVFS, rather than been modified by anyone capable of extracting and creating a new cabinet archive. This would have added firmware.metainfo.xml.asc
and firmware.metainfo.xml.p7b
to the archive, and at some point you have to wonder just how many extensions we can nest before the world descends into chaos. It also meant that we would have to add an extra n_firmware_files + n_metainfo_files
detached signatures to each archive for every extra signing mechanism we add.
The other problem with a single detached signature per engine per file is that only one entity can sign the firmware. At the moment it’s just the LVFS, but what if Dell wanted to sign the firmware with a detached signature too, saying “this firmware is 100% from Dell”? Would we have com.dell.firmware.metainfo.xml.p7b
too? This all got very complicated and basically forced me to create a new project to make it all much simpler.
Jcat is a gzipped JSON file of detached signatures. Because it’s gzipped it’s easy to compress and decompress in basically any language, and because it’s JSON it’s dead simple to parse and generate in any framework. There is a little overhead of some metadata (e.g. signing ID, creation time, etc) and but it’s all the kind of thing you can just edit in vim if you needed to. There’s also support for storing binary stuff like DER certificates (base64 to the rescue…), but if possible I’d like it to be all readable in a text editor. The jcat
command line tool can import existing detached signatures into the Jcat file, and can also verify the existing .jcat
file against all the files in a directory or archive. You can include multiple signatures for the same file (using the AppStream ID as the key) and of course sign multiple files using all the cryptographic engines you need. There’s also rudimentary support for actually creating signatures in the jcat
command line client too, although it’s WIP for the GNUTLS engine and completely missing for GPGME at the moment.
This new thing also lets us fix another glaring issue in fwupd. Some companies can’t use PKCS-7, and some can’t use GPG for equally bad and nonsensical reasons – at the moment you need to specify the remote keyring when enabling a remote as we need to know if we need to download the metadata.xml.gz.asc
or the .p7b
version. Using a .jcat
file allows to to not care, and just download one detached thing that can be used no matter how you’ve compiled your system. By adding SHA-256 as an additional not-to-be-used-for-trust engine, Jcat also lets you verify the download of your metadata and cabinet files even when you don’t have GPG or PKCS-7 available, which I know at least one company does on an IOT project. Jcat allows us to move the scary cryptographic verification code out of fwupd and makes the update-your-firmware codebase easier to maintain without worrying about potential landmines.
I’ve got a wip/hughsie/jcat
branch on fwupd, and the same for lvfs-website although none of it has had any kind of peer review. Feedback on the initial release of libjcat most welcome from anyone familiar with writing libraries with GIO and Glib.
I suck at naming, but Jcat is supposed to be “JSON Catalog”. My daughters also have lots of Jellycat toys scattered around the house too, and the name seemed not to be taken by any other projects so far. If anyone knows of a project already using the name, please let me know. Feedback very welcome.
it is worth the gzipped part ?
it de-dupes any signatures where the filename is different by the contents are the same.
RFC 5652 Signed CMS
You can use OpenSSL to create and verify detached CMS signatures. It’s basically the same format as Signed Email.
Looks neat! The `jcat` binary name will cause problems though, at the very least in Debian: https://manpages.debian.org/testing/sleuthkit/jcat.1.en.html
I don’t have any idea for a better name just now, except for creating acronyms like `jsic/`jsc“ (JSON Signature catalog/collection)
In the spirit of “something simple”, why not ditch PGP and PKCS and go for OpenBSD’s signify?
We could! There are lots of legal and crazy reasons why some users have to use X or cannot use Y and with Jcat it would be exceptionally simple to add another signing mechanism without breaking forwards or backwards compatibility.