|1.0.1||Apr 8, 2021|
#263 in Cryptography
This is a drop-in replacement for the RNP library supported and shipped by Thunderbird.
This project is called the Octopus, because octopuses can fit themselves in unusual places, and in this project we reimplement the RNP API as used by Thunderbird using Sequoia.
[Octopuses'] soft bodies mean octopuses can fit into impossibly small nooks and crannies, as long as the holes are not smaller than the only hard parts of their bodies: their beaks. If all else fails, octopuses can lose an arm to an attacker and regrow one later.
This is a young project. Use it with caution with your production
Thunderbird profile and production keys, and make sure you have a
backup (of at least
openpgp.sqlite) and know how to recover.
There may be dragons.
When Thunderbird auto-updates, it overwrites the Octopus' version of
librnp.sowith its own version. This issue has been reported to Thunderbird.
Thunderbird reads and caches the available certificates on startup. Thus if you add a new certificate to gpg, even though the Octopus will load it, Thunderbird will not notice it until either you manually reimport the keys using Thunderbird's
OpenPGP Keyring Manager,
Reload Key Cache, or you restart Thunderbird.
Note: Thunderbird only caches the list of keys and some meta-data, so it will normally take advantage of any updates inserted into the gpg keystore or fetched via Parcimonie.
The Octopus is actively developed by the Sequoia PGP team. We are primarily financed by the pep foundation. Our mandate is specifically to improve the OpenPGP ecosystem, and more generally to improve internet freedom tools.
Currently, the Octopus is developed outside of Thunderbird. There are two main reasons for this. First, the Thunderbird developers do not want to invest resources in supporting a new OpenPGP backend after having recently invested in RNP. Second, Sequoia and the Octopus are licensed under the GPLv2+. Although the GPLv2+ is compatible with MPL 2.0, adding GPLv2+ code to Thunderbird is not currently aligned with their licensing strategy.
In terms of testing, the Octopus includes a number of unit tests. Our CI runs these checks against all commits on Debian and Windows. It also runs the OpenPGP relevant unit tests from Thunderbird on Debian.
First of all, you will need to install Sequoia's build dependencies.
Then, building the Octopus is only a matter of invoking
optionally with the
--release flag to build an optimized build
suitable for end users. Non-release builds print debugging and
tracing information to stderr. You may optionally select one of
Sequoia's cryptographic backends, for example, on Windows you'll
probably want to use the Windows CNG backend instead of the Nettle
The result of the build is a shared library (i.e. a
*.so on Linux
and *BSD, a
*.dll on Windows, etc.). To use it, make your
Thunderbird pick it up instead of the
librnp.so that it ships,
e.g. by replacing it. The details are dependent on your deployment,
and this is something distributors need to figure out. This document
will demonstrate how to replace RNP in a local build of Thunderbird.
Note: the Octopus is fully backwards compatible with RNP. In
particular, it uses the same format for storing keys and stores them
in the same way. Thus, if you decide you don't like the Octopus, you
can simply restore the original
librnp, restart Thunderbird, and
Thunderbird will work as before with all of your data. Of course, you
should still make a backup (of at least
cargo build cp target/debug/libsequoia_octopus_librnp.so path/to/thunderbird/obj-x86_64-pc-linux-gnu/dist/bin/librnp.so
cargo build --release cp target/release/libsequoia_octopus_librnp.so path/to/thunderbird/obj-x86_64-pc-linux-gnu/dist/bin/librnp.so
cargo build --no-default-features --features crypto-cng cp target/debug/sequoia_octopus_librnp.dll path/to/thunderbird/.../dist/bin/rnp.dll # XXX: I'm guessing here
The following recipe was tested with version
Thunderbird (from Debian Bullseye). This uses
mechanism to move
librnp.so out of the way.
$ sudo apt install thunderbird ... thunderbird is already the newest version (1:78.9.0-1~deb10u1). ... $ ls -l /usr/lib/thunderbird/librnp.so -rw-r--r-- 1 root root 723248 Mar 24 19:57 /usr/lib/thunderbird/librnp.so $ sudo dpkg-divert --divert /usr/lib/thunderbird/librnp-orig.so --rename /usr/lib/thunderbird/librnp.so Adding 'local diversion of /usr/lib/thunderbird/librnp.so to /usr/lib/thunderbird/librnp-orig.so' $ sudo cp .../target/release/libsequoia_octopus_librnp.so /usr/lib/thunderbird/ $ sudo ln -sf libsequoia_octopus_librnp.so /usr/lib/thunderbird/librnp.so $ ls -l /usr/lib/thunderbird/*rnp* -rw-r--r-- 1 root root 723248 Mar 24 19:57 /usr/lib/thunderbird/librnp-orig.so lrwxrwxrwx 1 root root 28 Apr 7 13:59 /usr/lib/thunderbird/librnp.so -> libsequoia_octopus_librnp.so -rwxr-xr-x 1 root root 129988280 Apr 7 14:01 /usr/lib/thunderbird/libsequoia_octopus_librnp.so
If you are using the debug version, then change 'release' to 'debug'.
To uninstall the Octopus, you just need to remove the symlink and the diversion.
$ sudo rm /usr/lib/thunderbird/librnp.so $ sudo dpkg-divert --rename --remove /usr/lib/thunderbird/librnp.so Removing 'local diversion of /usr/lib/thunderbird/librnp.so to /usr/lib/thunderbird/librnp-orig.so' $ ls -l /usr/lib/thunderbird/*rnp* -rw-r--r-- 1 root root 723248 Mar 24 19:57 /usr/lib/thunderbird/librnp.so -rwxr-xr-x 1 root root 129988280 Apr 7 14:01 /usr/lib/thunderbird/libsequoia_octopus_librnp.so
If you are feeling particularly daring, you can download a precompiled
rnp.dll for Windows. This binary is created by our CI. It
corresponds to the current version of the
main branch. Before code
is checked into the
main branch, it must first pass our unit tests
on both Debian and Windows, and it must past the Thunderbird unit
tests on Debian.
To use the Octopus, replace the
rnp.dll binary in your Thunderbird
installation. This is usually at
C:\Users\USERNAME\AppData\Local\Mozilla Thunderbird\rnp.dll where
USERNAME is your username.
This library includes a number of additional features that enhance Thunderbird.
When Thunderbird starts, it asks RNP to parse its keyring. At this
point, the Octopus also runs
gpg --export and includes that in the
results. This makes the user's GnuPG keyring available to
Thunderbird. (From that point on the Octopus also monitors GnuPG's
keystore for updates.) This can be disabled by setting the
GNUPGHOME environment variable to
/dev/null as follows:
The certificates imported from GnuPG can be used as normal. It is possible to examine them in Thunderbird's OpenPGP Key Manager, set their "acceptance", etc.
There are two known limitations. First, the first time an OpenPGP
operation is performed, Thunderbird scans the keystore and creates an
index of the available keys. Thunderbird does not currently update
this index on its own. Thus, keys that are added to gpg's keystore
will not be visible to Thunderbird until either the cache is manually
OpenPGP Keyring Manager,
Reload Key Cache), or
you restart Thunderbird. Second, if you remove a certificate managed
by GnuPG using the Thunderbird certificate manager, it will be removed
from the in-memory keystore, but it is currently not actually removed
from your gpg keystore. As such, it will reappear the next time
Thunderbird loads the keyring.
The Octopus carefully keeps track of what certificates were loaded from GnuPG and only writes them out to Thunderbird's keyring if they have been modified; modified certificates are not currently written back to GnuPG. But, closer integration with GnuPG's keyring is planned.
The Octopus automatically monitors what keys are loaded into gpg's agent, and reports to Thunderbird that secret key material is available for them. This means that it is trivial to mark a key managed by the agent as a personal key in Thunderbird without modifying Thunderbird's configuration files. Also, attempts to decrypt messages encrypted to a key managed by the agent are automatically forwarded to the agent for decryption.
Unlike Thunderbird the Octopus talks directly to the agent. Thus,
it is not necessary to install GPGME; you only need to have
Thunderbird only supports a custom "acceptance" mechanism for authenticating OpenPGP certificate. Thunderbird ignores key signatures, and it is not possible to add certification authorities.
When Thunderbird starts up, the Octopus reads gpg's trust database, and merges it into Thunderbird's acceptance database. This means certificates that are considered authenticated by GnuPG are also considered authenticated by Thunderbird.
This integration is done carefully. If a user has manually accepted a certificate in Thunderbird, that setting is not overridden. This happens not only during the initial import, but also later: when the user accepts a certificate in Thunderbird, the Octopus detects this and will no longer update that certificate's acceptance based on GnuPG's trust database.
The Octopus monitors GnuPG for changes to its trust database. So, unlike when a new certificate is added to GnuPG's keystore, it is not necessary to restart Thunderbird to notice changes to the trust database.
Parcimonie is a feature that automatically refreshes the user's OpenPGP certificates in the background using a number of privacy preserving techniques. In particular, updates are staggered, and the time between updates is drawn from a memoryless distribution to frustrate an attacker who wants to predict when a user will check for an update. Enigmail had its own version of this mechanism, but it was removed when Enigmail was integrated into Thunderbird.
The Parcimonie feature in the Octopus currently checks for updates on keys.openpgp.org and in the appropriate Web Key Directories (WKDs) using the aforementioned privacy preserving mechanisms. It checks for updates for all non-revoked, valid certificates about once a week, on average. It also supports merging updates from User ID-less certificates.
Before importing a certificate, we first check if it appears to be flooded. If so, we strip third-party certifications from keys that we don't have a certificate for as those certifications are effectively useless.
This feature is controlled by the
net feature, which is enabled by
default. To disable it (and elide the dependencies on
tokio), build as follows:
cargo build --no-default-features --features sequoia-openpgp/default
The Octopus uses Sequoia, which rejects cryptographic algorithms that are known to be weak by default. Unfortunately, RNP still accepts MD5, among other vulnerable algorithms, without warning. Thunderbird has patched MD5 out of the version of RNP that they distribute, however, Thunderbird continues to support unlimited use of SHA-1, which is known to be vulnerable to collision attacks. Sequoia, and by extension, the Octopus, rejects certificates and messages that use weak cryptographic primitives. Because RNP does not have a mechanism to indicate that a certificate or component should not be used, the Octopus reports these keys as having expired one second after their creation time.
When Thunderbird creates an email it uses the RFC 1847 Encapsulation method construct, which has been known to be broken for over 20 years. The issue is that if Alice signs a message and sends it to Bob, Bob can use the signature in a different context.
This security issue can be fixed by using OpenPGP's intended recipient feature. Then, if Bob forwards the signed message (e.g., "I owe you 100 Euros") to Carol, Carol's MUA will mark the signature as invalid as she is not the intended recipient of the message.
In the Octopus, we detect the use of the encapsulation method and automatically and transparently replace it with the safer combined method whenever possible. Specifically, when we encrypt a message, we check whether we just generated the signed part. If so, we fix it. Because this generates another signature, if you are using a key managed by gpg's agent, you may be prompted to authorize a second signature.
Sequoia has a number of non-functional advantages relative to RNP.
Sequoia automatically encrypts unencrypted secret key material in memory when it is not in use. This makes secret key exfiltration ala Heartbleed much harder, and protects against Spectre, Rowhammer, etc.-style attacks. OpenSSH uses the same type of protection.
RNP has the concept of locking and unlocking keys, but this is explicit, and Thunderbird does not always relock keys after use.
Sequoia only accepts SHA-1 in safer contexts. For instance, SHA-1 over messages, and its use in third-party certifications are rejected by default. But, SHA-1 self-signatures that are not suspicious are allowed.
Sequoia has announced a timeline to completely deprecate the use of SHA-1: in 2023 SHA-1 will no longer be accepted for digital signatures.
Sequoia includes a salt in signatures and self-signatures to defend against collision attacks, among others. OpenSSH does the same thing. Should the collision resistance of another hash be broken, this will frustrate attackers trying to perform a Shambles-style attack.
RNP maintains separate public and secret keyrings. This can lead to a so-called split-brain problem where a certificate is present in both keyrings, and confusingly one version is returned sometimes and the other version other times. This is also the model that GnuPG 1.x used, and is one of the reasons that GnuPG migrated to a single OpenPGP keystore in GnuPG 2.0 with only the secret key material held by the agent.
To avoid this problem, the Octopus merges the two databases. To
remain backwards compatible with RNP, when the Octopus writes out the
certificates, certificates with secret key material are written to
secring.gpg and those without are written to
Thanks to Rust's safer concurrency paradigms, it is less dangerous and less complicated for the Octopus to use threads than libraries written in other languages. The Octopus uses this, for instance, to parse keyrings faster. And to perform updates in the background.
RNP doesn't implement a number of important parts. For instance, it does not reject unknown critical subpackets and notations. This is a security problem. RNP doesn't handle unknown packet versions. This is a future compatibility problem. RNP also doesn't handle "esoteric" keys, like shared keys where only the encryption subkey's secret key material is shared. This is a compatibility problem. More examples can be found in the OpenPGP interoperability test suite.