A certificate verification library for rustls that uses the operating system's verifier

Overview

rustls-platform-verifier

crates.io version crate documentation MSRV crates.io downloads CI

A Rust library to verify the validity of TLS certificates based on the operating system's certificate facilities. On operating systems that don't have these, webpki and/or rustls-native-certs is used instead.

This crate is advantageous over rustls-native-certs on its own for a few reasons:

  • Improved correctness and security, as the OSes CA constraints will be taken into account.
  • Better integration with OS certificate stores and enterprise CA deployments.
  • Revocation support via verifying validity via OCSP and CRLs.
  • Less I/O and memory overhead because all the platform CAs don't need to be loaded and parsed.

This library supports the following platforms and flows:

OS Certificate Store Verification Method Revocation Support
Windows Windows platform certificate store Windows API certificate verification Yes
macOS (10.14+) macOS platform roots and keychain certificate macOS Security.framework Yes
iOS iOS platform roots and keychain certificates iOS Security.framework Yes
Android Android System Trust Store Android Trust Manager Sometimes1
Linux webpki roots and platform certificate bundles webpki No2
WASM webpki roots webpki No2

Installation and setup

On most platforms, no setup should be required beyond adding the dependency via cargo:

rustls-platform-verifier = "0.1"

Android

Some manual setup is required, outside of cargo, to use this crate on Android. In order to use Android's certificate verifier, the crate needs to call into the JVM. A small Kotlin component must be included in your app's build to support rustls-platform-verifier.

Gradle Setup

rustls-platform-verifier bundles the required native components in the crate, but the project must be setup to locate them automatically and correctly.

Firstly, create an init script in your Android Gradle project, with a filename of init.gradle. This is generally placed in your project's root. In your project's settings.gradle, add these lines:

apply from: file("./init.gradle");
configurePlatformVerifierProject()

// includeFlat is not deprecated, see https://github.com/gradle/gradle/issues/18644#issuecomment-980037131 for more details.
//noinspection GrDeprecatedAPIUsage
includeFlat("rustls-platform-verifier")

// Note: This path is dependent on where your workspace's target path.
project(":rustls-platform-verifier").projectDir = file("$rootDir/../target/rustls-platform-verifier/android/")

Next, the rustls-platform-verifier external dependency needs to be setup. Open the init.gradle file and add the following, where $PATH_TO_ROOT is replaced with a directory navigation to where your project's Cargo.toml is located (ie; "../"):

ext.configurePlatformVerifierProject = {
    def cmdProcessBuilder = new ProcessBuilder(new String[] { "cargo", "check", "-p", "rustls-platform-verifier" })
    cmdProcessBuilder.directory(File("$PATH_TO_ROOT"))
    cmdProcessBuilder.environment().put("RUSTLS_PLATFORM_VERIFIER_GEN_ANDROID_SRC", "1")

    def cmdProcess = cmdProcessBuilder.start()

    cmdProcess.waitFor()
}

This script can be tweaked as best suits your project, but the cargo check invocation must be included.

Finally, sync your gradle project changes. It should pick up on the rustls-platform-verifier Gradle project and, if you look in ./target/rustls-platform-verifier, there should be an android folder containing the required Kotlin sources. After this, everything should be ready to use.Future updates of rustls-platform-verifier shouldn't need anything beyond the usual cargo update either.

Crate initialization

In order for the crate to call into the JVM, it needs handles from Android. These are provided either the init_external or init_hosted function. These give rustls-platform-verifier the resources it needs to make calls into the Android certificate verifier.

As an example, if your Rust Android component which the "native" Android part of your app calls at startup has an initialization, like this:

#[export_name = "Java_com_orgname_android_rust_init"]
extern "C" fn java_init(
    env: JNIEnv,
    _class: JClass,
    context: JObject,
) -> jboolean {
    // ... initialize your app's other parts here.
}

In the simplest case, you should to insert a call to rustls_platform_verifier::android::init_hosted() here, before any networking has a chance to run. This only needs to be called once and the verifier will be valid for the lifetime of your app's process.

extern "C" fn java_init(
    env: JNIEnv,
    _class: JClass,
    context: JObject,
) -> jboolean {
    // ... initialize your app's other parts here.

    // Then, initialize the certificate verifier for future use.
    rustls_platform_verifier::android::init_hosted(&env, context);
}

In more advanced cases, such as where your code already stores long-lived handles into the Android environment, you can alternatively use init_external. This function takes a &'static reference to something that implements the android::Runtime trait, which the crate then uses to obtain the access when required to the JVM.

Credits

Made with ❤️ by the 1Password team. Portions of the Android and Windows implementation were adapted and referenced from Chromium's verifier implementation as well.

License

Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Footnotes

  1. On Android, revocation checking requires API version >= 24 (e.g. at least Android 7.0, August 2016). For newer devices that support revocation, Android requires certificates to specify a revocation provider for network fetch (including optionally stapled OSCP response only applies to chain's end-entity). This may cause revocation checking to fail for enterprise/internal CAs that don't properly issue an end-entity.

  2. https://docs.rs/rustls/0.20.6/src/rustls/verify.rs.html#341 2

You might also like...
🛠️ Uses zkevm-circuits and anvil mainnetfork to prove that a tx solves an EVM challenge

zk-proof-of-evm-execution This is a PoC developed at hackathon that enables a user to prove that they know some calldata that can solve a challenge on

Uses Plonky2 proof system to build recursive circuits for Merkle Trees.

ProvableMerkleTrees Introduction This repo provides Rust code to build Merkle Trees, equipped with a Provable interface to generate Zero Knowledge pro

MimiRust - Hacking the Windows operating system to hand us the keys to the kingdom with Rust
MimiRust - Hacking the Windows operating system to hand us the keys to the kingdom with Rust

MimiRust - Hacking the Windows operating system to hand us the keys to the kingdom with Rust

CosmOS - experimental operating system written in Rust.

CosmOS A simple operating system written in Rust. Table of Contents CosmOS Setup QEMU Run OS dev resources General Bootloader Setup Linux Arch pacman

A prototype implementation of the Host Identity Protocol v2 for bare-metal systems, written in pure-rust.
A prototype implementation of the Host Identity Protocol v2 for bare-metal systems, written in pure-rust.

Host Identity Protocol for bare-metal systems, using Rust I've been evaluating TLS replacements in constrained environments for a while now. Embedded

A guide for Mozilla's developers and data scientists to analyze and interpret the data gathered by our data collection systems.

Mozilla Data Documentation This documentation was written to help Mozillians analyze and interpret data collected by our products, such as Firefox and

OpenZKP - pure Rust implementations of Zero-Knowledge Proof systems.

OpenZKP OpenZKP - pure Rust implementations of Zero-Knowledge Proof systems. Overview Project current implements 🐺 the Stark protocol (see its readme

The fly.io distributed systems challenges solved in Rust

The fly.io distributed systems challenges solved in Rust. Live-streamed in https://youtu.be/gboGyccRVXI License Licensed under either of Apache Licens

Kryptokrona SDK in Rust for building decentralized private communication and payment systems.

Kryptokrona Rust SDK Kryptokrona is a decentralized blockchain from the Nordic based on CryptoNote, which forms the basis for Monero, among others. Cr

Comments
  • Explicitly remove and/or verify Android mock test code in release builds

    Explicitly remove and/or verify Android mock test code in release builds

    In the Android verifier implementation, we have several class fields and conditionals that are solely in place to facilitate testing with mocked certificates and roots. While the use of said store is guarded, it would be better if it was provable these couldn't affect a production app, similar to #[cfg(debug_assertions)] in Rust.

    I can think of two initial approaches for this:

    • Create custom Proguard rules that remove this code from anything but an explicit integration test build
    • Automatically verify that the code doesn't end up being loaded at runtime
    O-Android 
    opened by complexspaces 0
  • Add iOS integration testing to CI

    Add iOS integration testing to CI

    To complete test coverage for the native platforms (WASM testing will need handled on its own), we need to add iOS testing inside of CI. This can be done via the simulator included with XCode on the GitHub actions runners. It should run the exact same tests that the Android FFI testing layer currently uses.

    Past work in this area includes:

    O-Apple 
    opened by complexspaces 0
  • Investigate allowing OID_ANY_EKU for certificate verification policies

    Investigate allowing OID_ANY_EKU for certificate verification policies

    Chromium allows this OID in their Android verifier, so we should investigate if its correct for us to add it addition to the existing server auth EKU. They also check for it and test against it in their verifier.

    Additionally, we should take this chance to try and document/verify which EKUs are enforced on what platforms and hopefully make them uniform as reasonable.

    opened by complexspaces 0
Owner
Modern TLS for Rust
null
A boringssl-based rustls crypto provider

boring-rustls-provider This is supposed to be the start to a boringssl-based rustls crypto provider. Status This is just a dump of me figuring out how

Jan 5 Nov 28, 2023
Simple, bare-minimum recaptcha verifier helper

recaptcha-verify Simple, bare-minimum recaptcha verifier helper Quick Start This library is supposed to be a (near) drop-in replacement for recaptcha-

Ivan Ganev 4 Oct 20, 2023
WebPKI X.509 Certificate Validation in Rust

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABIL

Brian Smith 408 Dec 16, 2022
An implementation of the append-only log described in the Certificate Transparency specification (RFC 6962)

CT Merkle This is an implementation of the append-only log described in the Certificate Transparency specification (RFC 6962). The log is a Merkle tre

Michael Rosenberg 30 Dec 2, 2022
Fast and efficient ed25519 signing and verification in Rust.

ed25519-dalek Fast and efficient Rust implementation of ed25519 key generation, signing, and verification in Rust. Documentation Documentation is avai

dalek cryptography 563 Dec 26, 2022
deductive verification of Rust code. (semi) automatically prove your code satisfies your specifications!

Le marteau-pilon, forges et aciéries de Saint-Chamond, Joseph-Fortuné LAYRAUD, 1889 About Creusot is a tool for deductive verification of Rust code. I

Xavier Denis 609 Dec 28, 2022
An implementation of NZ COVID Pass verification written in Rust

NZCP Rust   An implementation of NZ COVID Pass verification, New Zealand's proof of COVID-19 vaccination solution, written in Rust ?? We also have a J

Vaxx.nz 7 Nov 24, 2022
RSA dependency for rust, with cert verification

About Project End to End encryption (RSA) for multiple languages (cross-platform) with double encryption and double decryption methods Icon Item ?? Up

Zot Cryptography 2 Nov 27, 2022
Simple, reliable, open-source contract verification built for an L2 centric Ethereum ecosystem

Cove This repo contains the backend verification1 code for Cove, a simple, reliable, open-source contract verification built for an L2 centric Ethereu

ScopeLift 12 Apr 1, 2023
specs & benchmarks for the ZPrize 3 - High Throughput Signature Verification

Zprize: High Throughput Signature Verification How fast do you think you can verify our ECDSA signatures on Aleo? This year's Zprize is winner-take-al

null 6 Oct 21, 2023