Don't need NFC? Solo 2 USB-A base model now in stock.

Trussed® Announcement

Today’s the day: We’re very proud to announce Trussed®, an open source framework for modern cryptographic applications, which powers the FIDO and PIV authenticators of the Bee firmware on the new Solo V2 security key by SoloKeys.

It’s written in Rust.


This announcement will give a high-level overview of the motivation for and design of Trussed. It will be followed soon by a “tutorial” of sorts, walking through an implementation of TOTP (time-based one-time password, a commonly used second factor authentication method) in minimal form on PC. 

We’re not just announcing, we’re also releasing the source code, dual-licensed under the Apache and MIT licenses, on GitHub: This code is still very much a work in progress, and does not yet come with stable functionality or API promises. However, we think the time has come to continue further work in public, so we may learn from the open source community.

“We” here are not just SoloKeys, but also Nitrokey, our competitor-slash-collaborator from Germany that has always used SoloKeys firmware in their web authentication products, and will continue to do so. Nitrokey will have their own announcement on this topic and their further plans for security keys.

Together, we loosely build the current “Trussed Alliance” of Trussed implementers, users, and evangelists. We are reachable by several means, for instance via email at [email protected], by Matrix chat in, or async at We are very interested in and open to additional allies. Particularly, at this stage, those with strong (correct) opinions, and the drive to contribute to the implementation :)

But what is Trussed?

You may be aware of PKCS #11 (usage guide), which – despite all of its warts – is a standardized, high-level, platform-independent API, enabling software to make use of hardware-backed cryptography. There are other APIs in a similar spirit, such as WebCrypto by the W3C (with its own warts, and notably relaying JavaScript applications to software implementations of cryptography), or PARSEC (backed by Arm and Docker, which has a rather more grand scope).

All of these have in common that applications can outsource their cryptographic needs to a trusted third party implementation through a common API. Secret keys can be generated for various algorithms or mechanisms (symmetric cryptography such as AES, asymmetric cryptography such as P256, Ed25519, X25519, RSA, etc.). The application obtains not the sensitive key material, but instead a handle object, with which it can then perform further operations: sign data, verify signatures, encrypt or decrypt data, etc.

The core idea of Trussed is this: What if there were similar facilities – without the warts – right inside the firmware of embedded devices?

Thinking further: What if these were provided by idiomatic, misuse-resistant, best cryptographic practice-following APIs? What if the list of available cryptographic mechanisms, together with their software or hardware implementations, were flexibly configurable at compile time, but came with “batteries included”? What if this “crypto-in-a-box” would be easy to plug into whatever setup one is already using? What if applications, then, could focus on implementing their domain-specific logic and interfaces with the outside world, while taking advantage of one cryptographic joint, kept well oiled.

And that is exactly what Trussed is!

Portable Trussed apps

You may see the term “Trussed app”. By this we mean any unit of firmware that uses the Trussed APIs, and otherwise is completely cross-platform (meanwhile, it will be called externally by the runtime/scheduler). To repeat, a Trussed app is called externally, but internally only calls Trussed APIs – this makes it portable to all platforms on which Trussed itself runs on.

Two prime examples would be the FIDO and PIV authenticator apps by SoloKeys. In the past (with the existing Solo V1 key C firmware), when others wanted to “somehow reuse” app code it didn’t really work – forks happened, or even simple copy-pastes. Similarly, Google’s FIDO2 implementation in OpenSK is tightly coupled to the Tock OS around it, and limited to devices which have Tock OS support.  

By decoupling from runtimes, and making minimal requirements on Trussed platforms, we envision that “Trussed apps” will be shareable between vendors (each adding their own runtime and physical product). That bug fixes and functionality additions can be shared. That alternative implementations of existing applications are possible (e.g., a DiceKeys-backed FIDO2 app).

Generally, we would like to open up an ecosystem of “Trussed apps” (WireGuard, password managers, GPG for those that like it, pocket HSMs, etc.), eventually replacing JavaCard and bringing embedded cryptographic firmware to the modern age.

Trussed Components

There are two major components in Trussed, the service, and the clients.

The service depends on platform resources (storage, entropy, UI facilities), bundles up cryptographic algorithm implementations at compile time, and is then just a beefy component with a “process” method. This method needs to be called by the runtime/scheduler, either regularly, or on-demand via a provided syscall abstraction.

The service’s storage is partitioned by client, and further by type of object the service is responsible for managing on a client’s behalf: A key store for cryptographic keys, a file store for binary metadata (exposed as a POSIX-ish filesystem interface), and a certificate store.

The clients correspondingly have APIs (for crypto, file and other needs) to send requests with, for instance a “CryptoClient + P256 + HmacSha256”. Client and service communicate via interchanges, shared memory areas in which requests and replies are placed. Both the requests and replies are modeled as Rust types, so there is no low-level memory copying and length calculations.  Additionally, interchanges serve as a strong demarcation between different privileged executions (such as the secure and nonsecure worlds in ARM TrustZone).

What is Trussed not?

Trussed intends to be a configurable box you can use with ease in your firmware, but it does not intend to take over your entire platform. It is not an embedded operating system. Trussed does not use the heap, all variables are allocated on the stack. Trussed does not internally use threads in any way, control flow is linear and predictable.

To create a functional product, besides a Trussed platform, you need to supply:

  • runtime/scheduler: with SoloKeys, we use RTIC (Real-Time Interrupt-driven Concurrency), which is a thin software wrapper around the Arm Cortex-M NVIC hardware scheduler. Conceivably, something like Tock should work, or threaded scheduling on PC.
  • interfaces: with SoloKeys, we use usb-device as a framework to implement USB classes (CTAPHID, CCID) on top of our LPC55 HAL (hardware abstraction layer), and our own NFC device framework.
  • dispatch: depending on the richness of the runtime, there may be separate need to dispatch between multiple interfaces and multiple applications.
  • secure manufacturing: Trussed has the concept of “device attestation”, binding a unique identifier for the chip it runs on to private device attestation keys (Ed255 + P256), via a vendor certificate authority. Further it has a concept of “key attestation”, attesting keys on the device as being generated on the device and not being extractable, via the device attestation keys and certificates.  While Trussed exposes methods to do this, they rely on preparations that depend on the platform and need to be done in the manufacturing process.
  • optionally, a secure signed firmware update procedure: conceivably, Trussed might be used in a custom bootloader, but the compile-time security of Trussed comes from firmware “bundles” being verified by a vendor. There needs to be a way to ensure any changes to the firmware are “atomic” and authorized, replacing the entire bundle of runner + apps + Trussed with a new non-compromised setup (operating on the existing data).

First Implementation

SoloKeys will be releasing the first products built with Trussed.  Their Solo v2 authenticators are fully open source and designed for enterprise use for FIDO2 and PIV.  More applications are to follow, all based on Trussed.

What about the trademark?

Trussed sometimes has a registered trademark symbol next to it. Why? First off, as mentioned, the source code itself is permissively dual-licensed. There is no intent for any “open core” kind of license/monetization scheme (some reasoning that resonates is here). We consider the ideas expressed in Trussed to be public domain, and really just an (ongoing) distillation of best practices.

However, when a vendor wishes to sell a product, and advertise that it is “Built on Trussed”, has “Trussed® Inside”, or similar (in effect, profit from the trust we will build in Trussed!), we would like to be able to ensure that basic requirements are fulfilled for the platform, applications and product manufacturing chain – this is needed to make a secure product.

As an example, Trussed ensures keys are kept secret by storing them encrypted-at-rest at all times. It can do so either by using a backing storage that is encrypted by hardware, or adding a software encryption layer itself – one or the other, but it needs to be ensured.

As another example, Trussed needs a source of entropy. Ideally, a platform has a hardware source, alternatively, the manufacturing process can inject an entropic seed – again, one or the other (or both) need to be ensured.

To sum up, we hope that you find use for Trussed in your products. The more eyes, the better! If you do use Trussed, we’d like you to advertise that you do. In this case, please contact [email protected] so we can discuss. There is no formal certification process at this point.

Some more details about portability

Cryptographic implementations should be constant-time, and, particularly for asymmetric algorithms, need to be tailored to the platform for speed. For these, Trussed currently uses specific implementations for Cortex-M4 (and above, i.e. Cortex-M33 and Cortex-M35P). For Cortex-M3, the problem is that multiplication is not constant time. For Cortex-M0, the problem is that the non-cryptographic part of the implementation has as requirement the existence of atomics, which this platform does not have.

Mostly, Trussed should be portable to sufficiently capable platforms. We’d be very excited to see Tropic Square’s vision come to fruition – a RISC-V platform with security features and low-enough power requirements to be driven by NFC. We’d definitely like to run Trussed apps on PC, backed by encrypted storage, possibly with real USB interfaces via USB/IP or USB Raw Gadget, possibly with cryptography delegated to a TPM – this would simplify app development a lot, and allow, e.g., an alternative implementation of SoftHSM.

A hat tip: For non-asymmetric cryptography (digests, symmetrics algorithms), we rely on for the implementations. They are well-written, with care taken to ensure they run well on embedded systems. Kudos to all the RustCrypto developers!