On command-line argument parsing

The command-line tools that are part of GnuTLS (such as certtool and p11tool) had been using the GNU AutoGen for handling command-line arguments. AutoGen (do not be confused with autogen.sh script commonly used in Autotools based projects) does a great job in that regard, as it produces command-line parsing code and the documentation from the single source file. On the other hand, integrating the AutoGen infrastructure into a project can be tricky in many ways, e.g., it requires its own runtime library (libopts) whose interface compatibility is not well maintained. Therefore, we decided to switch to a simpler solution and have finally completed the migration recently. As I spent way too much time on this, I thought it might make sense to summarize the process in case anyone comes into a similar situation.

The first thing we tried was to define the requirements and review the existing alternatives. The requirements turned out to be:

  • The tool produces code and documentation from the same source, i.e., we do not need to repeat ourselves writing a separate documentation for the commands
  • The generated code has little to no run-time dependencies
  • The tool itself doesn’t have exotic (build-)dependencies

We soon realized that there are surprisingly few candidates that meet those requirements. help2man, which is widely used in GNU tools, generates documentation from the command output, while it only supports manual pages (no texinfo/html/pdf support); neither GNU Gengetopt, gaa, nor argtable supports documentation generation at all, etc.

The other thing to consider was how to implement it in a non-disruptive manner. The initial attempt was to combine a help2man-like approach with documentation format conversion using Pandoc, which seemed good in general but the hurdle was that the AutoGen option definitions are written in its own language. Before proceeding with this approach we need to find a way to convert the definitions into the actual option parsing code!

We split this task into two phases: first to parse the AutoGen definitions and convert it to an easier-to-use format such as JSON and YAML, and then process it to generate the code. For the former, I came across pest.rs, which is a PEG (parsing expression grammar) based parser generator with elegantly designed programming interface in Rust. With this I was able to write a converter from the AutoGen definitions to JSON.
Then the generated JSON files are processed by Python scripts to generate the code and documentation. As the first phase is one-shot, we do not need Rust at build time but only need the Python scripts and its dependencies to be integrated in the project.

The scripts and the JSON schema are now hosted as a separate project, which might be useful for other projects.

AF_ALG support in GnuTLS

The Linux kernel implements a set of cryptographic algorithms to be used by other parts of the kernel. These algorithms can be accessed through the internal API; notable consumers of this API are encrypted network protocols such as WireGuard, as well as data encryption as in fscrypt. The kernel also provides an interface for user-space programs to access the kernel crypto API.

GnuTLS has recently gained a new crypto backend that uses the kernel interface in addition to the user-space implementation. There are a few benefits of having it. The most obvious one is performance improvement: while the existing user-space assembly implementation has comparable performance to the in-kernel software emulation, the kernel crypto implementation also enables workload offloading to hardware accelerators, such as Intel QAT cards. Secondly, it brings support for a wider variety of CPU architectures: not only IA32 and AArch64, but also PowerPC and s390. The last but not least is that it could be used as a potential safety net for the crypto algorithms implementation: deferring the crypto operations to the kernel means that we could have an option to workaround any bugs or compliance (such as FIPS140) issues in the library.

As for the implementation, the kernel interface is exposed through the AF_ALG socket family along with a Netlink interface to retrieve information about algorithms; although it is not straightforward to directly work with the interface, libkcapi provides a nice abstraction over the underlying system calls, which we use as a basis for the integration with GnuTLS. František Krenželok in our team picked the initial patch set provided by Stephan Mueller and has successfully moved it towards the finish line.

With the upcoming 3.7.2 release, GnuTLS user programs could enjoy a performance boost (under certain circumstances) through this new crypto backend. Next up, we are aiming to integrate KTLS as well. Stay tuned.

Bringing FIDO2 device support to sandboxes

Hardening user logins with 2FA is becoming must-feature of Web services; most of the services I use daily (such as GitLab instances) are already enabling it. Although it’s a bit cumbersome to enter secondary factor manually, using hardware tokens (such as FIDO2 authenticators) simplifies the process to a single tap, also making the entire authentication more secure based on public key cryptography.

On the client side, major browsers provide built-in support for hardware tokens (at least CTAP1), though sandboxed applications cannot benefit from this without allowing direct access to the host hardware. To improve the situation, we had several discussions in forums last year and somehow reached a rough consensus: we need a proxy for those authenticator devices.

Norbert Pócs in our team tackled this problem and has managed to create a D-Bus based proxy service that can bridge the device access to sandboxed applications. At DevConf.cz 2021, we presented our effort covering a proof-of-concept Firefox/Flatpak integration (special thanks to the people behind zbus, which made this pretty straightforward).

If you are interested in this topic, take a look at the recording of our presentation. Slides are also available. It’s still up in the air how to properly integrate this feature into browsers, but maybe the next step would be to finalize the protocol to allow different implementations.

What’s new in GnuTLS 3.7.0

On behalf of the GnuTLS team, I am pleased to present GnuTLS 3.7.0, the first cut of the 3.7 series. This is the result of several months of planning and work by 25 contributors and includes feature enhancements and behavior changes, such as removal of deprecated functions and tightening of system requirements. In this entry, I will try to detail some notable features in the release.

API for on-demand CA certificates retrieval

During the TLS authentication phase, the server typically presents a chain of X.509 certificates, from the end-entity certificate to the trusted CA certificate. The AIA extension allows the server to omit certain portion of the certificate chain, by pointing to the location where the client can download the missing certificates. Although GnuTLS provides a means to override the certificate verification logic completely through callbacks, this task is error-prone and thus desired to be supported natively. Sahana Prasad introduced the new set of API that allow applications to safely complement the certificate chain. The API is already being used in glib-networking.

API to support QUIC

QUIC is a new, UDP based transport protocol used as the basis of HTTP/3. Although the protocol internally relies on TLS for security, the networking protocol requires direct access to the TLS handshake state machine, which is normally hidden behind the TLS library interface.

After examining the design decisions in other libraries, we took the approach to provide a small set of API that exposes the necessary part of the state machine: capturing and injecting Handshake/Alert messages, and notifying key installation.

The API can be used as a crypto backend of the ngtcp2 library, and in turn by curl’s experimental HTTP/3 support. Here is a quick screenshot how it works:


$ ./src/curl -V
curl 7.74.0-DEV (x86_64-pc-linux-gnu) libcurl/7.74.0-DEV GnuTLS/3.7.0 zlib/1.2.11 brotli/1.0.9 libidn2/2.3.0 libpsl/0.21.0 (+libidn2/2.3.0) ngtcp2/0.1.0-DEV nghttp3/0.1.0-DEV
Release-Date: [unreleased]
Protocols: dict file ftp ftps gopher http https imap imaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: alt-svc AsynchDNS brotli Debug HTTP3 HTTPS-proxy IDN IPv6 Largefile libz NTLM NTLM_WB PSL SSL TLS-SRP TrackMemory UnixSockets

$ ./src/curl --verbose -s --alt-svc altsvc.cache https://quic.aiortc.org/
* STATE: INIT => CONNECT handle 0x7c8a68; line 1796 (connection #-5000)
* Alt-svc connecting from [h1]quic.aiortc.org:443 to [h3-29]quic.aiortc.org:443
* Added connection 0. The cache now contains 1 members
* STATE: CONNECT => WAITRESOLVE handle 0x7c8a68; line 1842 (connection #0)
[...]
* QUIC handshake is completed
* ngtcp2 established connection!
* Connected to quic.aiortc.org () port 443 (#0)
* Marked for [keep alive]: HTTP/3 default
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x7c8a68; line 1987 (connection #0)
* STATE: SENDPROTOCONNECT => DO handle 0x7c8a68; line 2011 (connection #0)
* Using HTTP/3 Stream ID: 0 (easy handle 0x7c8a68)
> GET / HTTP/3
> Host: quic.aiortc.org
> user-agent: curl/7.74.0-DEV
> accept: */*
> alt-used: quic.aiortc.org:443
>
[...]

Hard dependency on Nettle 3.6

GnuTLS relies on the Nettle library for cryptographic algorithm implementations. While we closely work with the Nettle upstream, we have kept the copy of the library in our tree for compatibility reasons. By requiring Nettle 3.6, we were able to remove those compatibility code from the distribution, which makes the maintenance easier.

GOST MAGMA/KUZNYECHIK CTR-ACPKM and CMAC

Thanks to Dmitry Baryshkov, Nettle 3.6 has seen adoption of the GOST hash and digital signature (GOSTDSA) algorithms. Aiming at the inclusion of the future Nettle releases, the GOST block cipher algorithms, Magma and Kuznyechik, have also been made available through the abstract crypto API.

Resurrection of padlock instruction set and support for Zhaoxin CPU

GnuTLS has supported the VIA padlock instruction set for many years now. However, the support has become difficult to test as the VIA CPUs are hard to obtain. Jonas Zhou fixed the current padlock detection code, and added support for the compatible instruction set available in the Zhaoxin CPU family.

3.8.0 and 3.7.1 milestones are now open!

Now that 3.7.0 was released, a couple of milestones have been created for the new development.

I would expect even more new features coming in the those future releases, such as the Linux kernel TLS (KTLS) support, DTLS 1.3, algorithm acceleration based on AF_ALG, and TPM 2.0 support, to name a few. Stay tuned for updates!

libsecret is accepting Outreachy interns as well

Like other projects in GNOME, libsecret also has an open project for Outreachy internship: Create a portable library for reading/writing libsecret keyring format.

libsecret is a library that allows applications to store/retrieve user secrets (typically passwords). While it usually works as a client against a separate D-Bus service, it can also use a local file as database. The project is about refactoring the file database so it can easily gain more advanced features like hardware-based security, etc. That might sound intimidating as it touches cryptography, but don’t worry and reach out to us if you are interested 🙂

Update: we didn’t get applicants in this round, but the project is still open until someone will step up to implement it. Here is the details from the proposal:

libsecret is a library that allows applications to store and retrieve user secrets, widely used by GNOME and other desktop applications. While it works as a client of the D-Bus service, it has recently gained support for storing secrets in a local file for constrained applications. The current implementation, however, has a few shortcomings:

  1. it is tied to the specific crypto library (libgcrypt)
  2. it cannot be easily used by other projects, such as GNOME Keyring
  3. no versioning / migration support from other keyring formats

The objective of this project is to revamp the implementation in a modular design, allowing multiple crypto libraries (OpenSSL, GnuTLS, etc) to be used as backend, making the reader/writer code standalone, and adding proper support for data migration.

The resulting library shall be embedded as a git submodule in libsecret and linked as a static library, in a way akin to the GVDB library.

Secrets management for Flatpak applications

At this year’s GUADEC, I talked about how Flatpak applications could manage user secrets such as passwords. It has now been summarized as an article on opensource.com:

TL;DR, the points are:

  • If your app is using libsecret and you are willing to avoid unnecessary exposure of D-Bus Secret Service API to Flatpak sandboxes, we recommend to stick with (or port to) the simple API of libsecret
  • libsecret and co. are still maintained and your help is greatly appreciated! 🙂

Talk on TLS 1.3 APIs

I have been recently working on TLS (Transport Layer Security) libraries, in particular GnuTLS and NSS. For the last few years there had been a lot of activities in upstream implementing the latest standard, which officially came out as TLS 1.3. While the protocol design drastically changed from TLS 1.2, applications usually don’t need to be modified to just enable TLS 1.3; that is a good thing. On the other hand, a new API set is added to support the new concepts in TLS 1.3, such as 0-RTT mode.

In January, I had a chance to talk at DevConf.cz (and later FOSDEM) to go through those new APIs (slides, recording), which I hope application developers might find useful. Note that the APIs are still changing as we continue adding remaining features to the libraries.