This repository holds a reference implementation of the Android KeyMint HAL, including closely related HAL interfaces:
The codebase is divided into a number of interdependent crates, as follows.
kmr-derivecrate holds proc macros used for deriving the
kmr_wire::AsCborValuetrait that is used for message serialization. This crate uses
std, but is only required for the build process on the host, and does not produce code that runs on the device.
kmr-wirecrate holds the types that are used for communication between the userspace HAL service and the trusted application code that runs in the secure world, together with code for serializing and deserializing these types as CBOR. This crate is
kmr-commoncrate holds common code used throughout the KeyMint implementation. This includes metadata processing code, keyblob manipulation code, and also the abstractions used to represent access to underlying cryptographic functionality. This crate is
kmr-tacrate holds the implementation of the KeyMint trusted application (TA), which is expected to run within the device's secure environment. This crate is
kmr-halcrate holds the implementation of the HAL service for KeyMint, which is expected to run in the Android userspace and respond to Binder method invocations. This crate uses
std(as it runs within Android, not within the more restricted secure environment).
kmr-crypto-boringcrate holds a BoringSSL-based implementation of the cryptographic abstractions from
kmr-common. This crate is
alloc); however, it relies on the Rust
opensslcrate for BoringSSL support, and that crate uses
kmr-testscrate holds internal testing code.
|Yes (build-only)||Proc macros for deriving the |
|No||Types for HAL <-> TA communication|
|No||Common code used throughout KeyMint/Rust|
|Yes||HAL service implementation|
|Yes (via ||Boring/OpenSSL-based implementations of crypto traits|
|Tests and test infrastructure|
To use the Rust reference implementation on an Android device, implementations of various abstractions must be provided. This section describes the different areas of functionality that are required.
Using the reference implementation requires a Rust toolchain that can target the secure environment. This toolchain (and any associated system libraries) must also support heap allocation (or an approximation thereof) via the
alloc sysroot crate.
If the BoringSSL-based implementation of cryptographic functionality is used (see below), then some parts of the Rust
std library must also be provided, in order to support the compilation of the
openssl wrapper crate.
KeyMint appears as a HAL service in userspace, and so an executable that registers for and services the KeyMint related HALs must be provided.
The implementation of this service is mostly provided by the
kmr-hal crate, but a driver program must be provided that:
The KeyMint HAL service (which runs in userspace) must communicate with the KeyMint TA (which runs in the secure environment). The reference implementation assumes the existence of a reliable, message-oriented, bi-directional communication channel for this, as encapsulated in the
This trait has a single method
execute(), which takes as input a request message (as bytes), and returns a response message (as bytes) or an error.
A (shared) instance of this trait must be provided to each of the
kmr_hal::<interface>::Device types, which allows them to service Binder requests for the relevant interface by forwarding the requests to the TA as request/response pairs.
SerializedChanneltrait, for reliable HAL <-> TA communication.
The Cuttlefish implementation of the KeyMint/Rust HAL service provides an example of all of the above.
kmr-ta crate provides the majority of the implementation of the KeyMint TA, but needs a driver program that:
kmr_ta::KeyMintTa::process(), receiving a response
mainequivalent for TA, handling scheduling of incoming requests.
kmr_ta::KeyMintTa::set_boot_infoon receipt of boot info.
The Cuttlefish implementation of the KeyMint/Rust TA provides an example of all of the above.
The bootloader is required to transmit root of trust and boot state information to the TA at start of day, so the TA can bind keys to the root of trust appropriately. The bootloader should fill out and send a
kmr_wire::SetBootInfoRequest message to do this.
The KeyMint TA requires implementations for low-level cryptographic primitives to be provided, in the form of implementations of the various Rust traits held in
Note that some of these traits include methods that have default implementations, which means that an external implementation is not required (but can be provided if desired).
BoringSSL-based implementations are available for all of the above (except for secure time).
The KeyMint TA requires implementations of traits that involve interaction with device-specific features or provisioned information, in the form of implementations of the various Rust traits held in