diff --git a/.gitignore b/.gitignore index 5823b44e..988879bd 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,8 @@ /.idea /android/verification/ + +# Ignore all generated Maven local repository files and folders +/android-release-support/maven/pom.xml +/android-release-support/maven/rustls/rustls-platform-verifier/**/ +/android-release-support/maven/rustls/rustls-platform-verifier/maven-metadata-local.xml \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index a4eea190..60a4df44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -313,6 +313,7 @@ dependencies = [ "once_cell", "rustls", "rustls-native-certs", + "rustls-platform-verifier-android", "rustls-webpki", "security-framework", "security-framework-sys", @@ -320,6 +321,10 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.0" + [[package]] name = "rustls-webpki" version = "0.101.4" diff --git a/Cargo.toml b/Cargo.toml index 8099dc5a..c29f147e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,72 +1,7 @@ -[package] -name = "rustls-platform-verifier" -version = "0.1.0" -authors = ["ComplexSpaces ", "1Password"] -description = "rustls-platform-verifier supports verifying TLS certificates in rustls with the operating system verifier" -keywords = ["tls", "certificate", "verification", "os", "native"] -repository = "https://github.com/1Password/rustls-platform-verifier" -license = "MIT OR Apache-2.0" -edition = "2021" -rust-version = "1.64.0" - -exclude = [ - "android/.run", - "android/gradle/**", - "android/gradle*", - "android/settings.gradle", - "android/src/androidTest", +[workspace] +members = [ + "android-release-support", + "rustls-platform-verifier", ] -[lib] -name = "rustls_platform_verifier" -# Note: The `cdylib` specification is for testing only. The shared library -# is not expected to have a stable API. -crate-type = ["cdylib", "rlib"] - -[features] -# Enables a C interface to use for testing where `cargo` can't be used. -# This feature is not stable, nor is the interface exported when it is enabled. -# Do not rely on this or use it in production. -ffi-testing = ["android_logger"] -# Enables APIs that expose lower-level verifier types for debugging purposes. -dbg = [] -# Enables `log::debug` base64-encoded logging of all end-entity certificates processed -# by the platform's verifier. -cert-logging = ["base64"] -# Used for nicely documenting the Android-specific APIs. This feature is not stable. -docsrs = ["jni", "once_cell"] - -[dependencies] -rustls = { version = "0.21", features = ["dangerous_configuration", "tls12", "logging"] } -log = { version = "0.4" } -base64 = { version = "0.21", optional = true } # Only used when the `cert-logging` feature is enabled. -jni = { version = "0.19", default-features = false, optional = true } # Only used during doc generation -once_cell = { version = "1.9", optional = true } # Only used during doc generation. - -[target.'cfg(target_os = "linux")'.dependencies] -rustls-native-certs = "0.6" -once_cell = "1.9" -webpki = { package = "rustls-webpki", version = "0.101", features = ["alloc", "std"] } - -[target.'cfg(target_os = "android")'.dependencies] -jni = { version = "0.19", default-features = false } -webpki = { package = "rustls-webpki", version = "0.101", features = ["alloc", "std"] } -once_cell = "1.9" -android_logger = { version = "0.13", optional = true } # Only used during testing. - -[target.'cfg(target_arch = "wasm32")'.dependencies] -once_cell = "1.9" -webpki-roots = "0.25" - -[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] -core-foundation = "0.9" -core-foundation-sys = "0.8" -security-framework = { version = "2.6", features = ["OSX_10_14"] } -security-framework-sys = { version = "2.4", features = ["OSX_10_14"] } - -[target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["wincrypt", "winerror"] } - -[package.metadata.docs.rs] -rustdoc-args = ["--cfg", "docsrs"] -features = ["dbg", "docsrs"] +resolver = "2" diff --git a/README.md b/README.md index c3626b0e..8338d496 100644 --- a/README.md +++ b/README.md @@ -47,59 +47,59 @@ component must be included in your app's build to support `rustls-platform-verif #### 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. +automatically and correctly. These steps assume you are using `.gradle` Groovy files because they're the most common, but everything +is 100% applicable to Kotlin script (`.gradle.kts`) configurations too with a few replacements. -Firstly, create an [init script](https://docs.gradle.org/current/userguide/init_scripts.html) 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: +Inside of your project's `build.gradle` file, add the following code and Maven repository definition. If applicable, this should only be the one "app" sub-project that +will actually be using this crate at runtime. With multiple projects running this, your Gradle configuration performance may degrade. -```groovy -apply from: file("./init.gradle"); -// Cargo automatically handles finding the downloaded crate in the correct location -// for your project. -def veifierProjectPath = findRustlsPlatformVerifierProject() -includeBuild("${verifierProjectPath}/android/") -``` +`$PATH_TO_DEPENDENT_CRATE` is the relative path to the Cargo manifest (`Cargo.toml`) of any crate in your workspace that depends on `rustls-platform-verifier` from +the location of your `build.gradle` file: -Next, the `rustls-platform-verifier` external dependency needs to be setup. Open the `init.gradle` file and add the following: -`$PATH_TO_DEPENDENT_CRATE` is the relative path to the Cargo manifest (`Cargo.toml`) of any crate in your workspace that depends on `rustls-platform-verifier` -from the location of your `init.gradle` file. +```groovy +import groovy.json.JsonSlurper -Alternatively, you can use `cmdProcessBuilder.directory(File("PATH_TO_ROOT"))` to change the working directory instead. +// ...Your own script code could be here... -```groovy -ext.findRustlsPlatformVerifierProject = { - def cmdProcessBuilder = new ProcessBuilder(new String[] { "cargo", "metadata", "--format-version", "1", "--manifest-path", "$PATH_TO_DEPENDENT_CRATE" }) - def dependencyInfoText = new StringBuffer() +repositories { + // ... Your other repositories could be here... + maven { + url = findRustlsPlatformVerifierProject() + metadataSources.artifact() + } +} - def cmdProcess = cmdProcessBuilder.start() - cmdProcess.consumeProcessOutput(dependencyInfoText, null) - cmdProcess.waitFor() +String findRustlsPlatformVerifierProject() { + def dependencyText = providers.exec { + it.workingDir = new File("../") + commandLine("cargo", "metadata", "--format-version", "1", "--manifest-path", "$PATH_TO_DEPENDENT_CRATE/Cargo.toml") + }.standardOutput.asText.get() - def dependencyJson = new groovy.json.JsonSlurper().parseText(dependencyInfoText.toString()) - def manifestPath = file(dependencyJson.packages.find { it.name == "rustls-platform-verifier" }.manifest_path) - return manifestPath.parent + def dependencyJson = new JsonSlurper().parseText(dependencyText) + def manifestPath = file(dependencyJson.packages.find { it.name == "rustls-platform-verifier-android" }.manifest_path) + return new File(manifestPath.parentFile, "maven").path } ``` -This script can be tweaked as best suits your project, but the `cargo metadata` invocation must be included so that the Android -implementation source can be located on disk. +Then, wherever you declare your dependencies, add the following: +```groovy +implementation "rustls:rustls-platform-verifier:latest.release" +``` -If your project often updates its Android Gradle Plugin versions, you should additionally consider setting your app's project -up to override `rustls-platform-verifier`'s dependency versions. This allows your app to control what versions are used and avoid -conflicts. To do so, advertise a `versions.path` system property from your `settings.gradle`: +Cargo automatically handles finding the downloaded crate in the correct location for your project. It also handles updating the version when +new releases of `rustls-platform-verifier` are published. If you only use published releases, no extra maintenance should be required. -```groovy -ext.setVersionsPath = { - System.setProperty("versions.path", file("your/versions/path.toml").absolutePath) -} +These script snippets can be tweaked as best suits your project, but the `cargo metadata` invocation must be included so that the Android +implementation part can be located on-disk. -setVersionsPath() -``` +#### Proguard -Finally, sync your gradle project changes. It should pick up on the `rustls-platform-verifier` Gradle project. It should finish -successfully, resulting in a `rustls` group appearing in Android Studio's project view. -After this, everything should be ready to use. Future updates of `rustls-platform-verifier` won't need any maintenance beyond the -expected `cargo update`. +If your Android application makes use of Proguard for optimizations, its important to make sure that the Android verifier component isn't optimized +out because it looks like dead code. Proguard is unable to see any JNI usage, so your rules must manually opt into keeping it. The following rule +can do this for you: +```text +-keep, includedescriptorclasses class org.rustls.platformverifier.** { *; } +``` #### Crate initialization diff --git a/admin/RELEASING.md b/admin/RELEASING.md new file mode 100644 index 00000000..dd5cf4ba --- /dev/null +++ b/admin/RELEASING.md @@ -0,0 +1,34 @@ +# How-to release `rustls-platform-verifier` + +This document records the steps to publish new versions of the crate since it requires non-trivial preparation and ordering +that needs to be remembered due to the Android component's distribution. + +## Steps + +1. Update main crate's version in `rustls-platform-verifier/Cargo.toml`. +2. If any non-test changes have been made to the `android` directory since the last release: + 1. Update Android artifact version in `android-release-support/Cargo.toml` + 2. Bump dependency version of the Android support crate in `rustls-platform-verifier/Cargo.toml` to match the new one + 3. Commit version increase changes on the release branch + * We typically name these branches `rel-xxx` where `xxx` is the major version. + * We typically leave these branches around for future maintenance releases. + 4. Run `ci/package_android_release.sh` in a UNIX compatible shell + 5. (Optional) `cargo publish -p rustls-platform-verifier-android --dry-run --alow-dirty` + + * `--allow-dirty` is required because we don't check-in the generated Maven local repository at this time. + 6. (Optional) Inspect extracted archive to ensure the local Maven repository artifacts are present + 1. Un-tar the `rustls-platform-verifier-android-*.crate` file inside of `target/package`. + 2. Verify `maven/rustls/rustls-platform-verifier` contains a single `*.RELEASE` directory and that contains a `.aar` file. + 3. (Optional) If the releaser has an external Gradle project that uses the configuration from the README, paste the path to the + unzipped package's `Cargo.toml` as a replacement for the `manifestPath` variable. Run a Gradle Sync and observe everything works. + 7. Publish the Android artifacts' new version: `cargo publish -p rustls-platform-verifier-android --alow-dirty` +3. Commit main crate's version increase on the release branch +4. Publish the main crate's new version: `cargo publish -p rustls-platform-verifier` + * Do **not** use `--allow-dirty` for the main crate. Only the Android component requires it and a dirty workspace elsewhere is an error. + +See the Rustls repo [RELEASING] guidance for more information (e.g. on best practices for creating a GitHub release with a changelog). + +[RELEASING]: https://github.com/rustls/rustls/blob/main/RELEASING.md diff --git a/android-release-support/Cargo.toml b/android-release-support/Cargo.toml new file mode 100644 index 00000000..da7063b4 --- /dev/null +++ b/android-release-support/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "rustls-platform-verifier-android" +version = "0.1.0" +description = "The internal JVM support component of the rustls-platform-verifier crate. You shouldn't depend on this directly." +repository = "https://github.com/rustls/rustls-platform-verifier" +license = "MIT OR Apache-2.0" +edition = "2021" + +# Explicitly include the Maven local repository for the Android component. +# While not checked into the repository, it is generated for releases and other contexts. +include = [ + "src/*", + "maven/pom.xml", + "maven/rustls/rustls-platform-verifier/**/", + "maven/rustls/rustls-platform-verifier/maven-metadata-local.xml", +] + +[dependencies] diff --git a/android-release-support/maven/rustls/rustls-platform-verifier/.gitkeep b/android-release-support/maven/rustls/rustls-platform-verifier/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/android-release-support/pom-template.xml b/android-release-support/pom-template.xml new file mode 100644 index 00000000..cbc86eb9 --- /dev/null +++ b/android-release-support/pom-template.xml @@ -0,0 +1,10 @@ + + + 4.0.0 + rustls + rustls-platform-verifier + $VERSION + aar + The internal JVM support component of the rustls-platform-verifier Rust crate + \ No newline at end of file diff --git a/android-release-support/src/lib.rs b/android-release-support/src/lib.rs new file mode 100644 index 00000000..97fb79ad --- /dev/null +++ b/android-release-support/src/lib.rs @@ -0,0 +1,75 @@ +//! # rustls-platform-verifier-android +//! +//! This crate is an implementation detail of the actual [rustls-platform-verifier](https://github.com/rustls/rustls-platform-verifier) crate. +//! +//! It contains no Rust code and is solely intended as a convenient delivery mechanism for the supporting Kotlin code that the main crate +//! requires to perform TLS certificate validation using Android's APIs. +//! +//! Other crates should not directly depend on this crate in any way, as nothing about it is considered stable and it is probably useless elsewhere. +//! +//! ## Details +//! +//! Note: Everything in this section is subject to change at any time. Semver may not be followed. +//! +//! ### Why? +//! +//! It was the best middle ground between several tradeoffs. The important ones, in priority order, are: +//! - Automatically keeping component versions in sync +//! - Allowing well-tested and well-known `cargo` dependency management patterns to apply everywhere +//! - Providing a smooth developer experience as an Android consumer of `rustls-platform-verifier` +//! +//! Firstly, what alternatives are available for distributing the component? The other two known are source distribution in some form (here, it will be through crates.io) +//! and Maven Central. Starting with the first, its become infeasible due to toolchain syncing requirements. If the Android component is +//! built as part of the host app's Gradle build, then it becomes subject to any Gradle or Android Gradle Plugin incompatibilities/requirements. In practice this means +//! the AGP version between this project and the main application have to match all the time. Sometimes this works, but it becomes challenging/unfeasible +//! during yearly toolchain/SDK upgrades and is not maintainable long term. Note that this is the _only_ option in this section which retains compatibility +//! with Cargo's Git dependency patching. +//! +//! Next, Maven Central. This is considered the standard way of distributing public Android dependencies. There are two downsides to this +//! approach: version synchronization and publishing overhead. Version syncing is the hardest part: There's not a good way to know what version +//! a crate is that doesn't hurt the Cargo part of the build or damage functionality. So instead of making assumptions at runtime, we would need to do +//! clunky and manual version counting with an extra error case. Less importantly, the admin overhead of Maven Central is non-zero so its good to avoid +//! if possible for such a small need. +//! +//! It is also worth calling out a third set of much worse options: requiring users to manually download and install the Android component +//! on each update, which magnifies the version syncing problem with lots of user overhead and then deleting the component outright. A rewrite +//! could be done with raw JNI calls, but this would easily be 3x the size of the existing implementation and require huge amounts of `unsafe` +//! to review then audit. +//! +//! ### The solution +//! +//! The final design was built to avoid the pitfalls the previous two options mentioned. To build it, we rely on CI and packaging scripts to build +//! the Android component into a prebuilt AAR file before creating a release. Next, a [on-disk Maven repository](https://maven.apache.org/repositories/local.html) +//! is hosted inside of this repository. Only the unchanging file structure of it is kept checked-in, to avoid churn. The remaining parts are filled in +//! during the packaging/release process, before being included in `cargo package` via an `include` Cargo.toml directive. Finally, once the repository has had +//! its artifacts added the crate containing the Maven repository is published to crates.io. Then, the main crate ensures it's downloaded when an Android target +//! is compiled via a platform-specific dependency. +//! +//! On [the Gradle side](https://github.com/rustls/rustls-platform-verifier/tree/main#gradle-setup), we include a very small snippet of code for users to include in their `settings.gradle` file +//! to dynamically locate the local maven repository on disk automatically based off Cargo's current version of it. The script is configuration cache friendly and +//! doesn't impact performance either. When the script is run, it finds the cargo-cached download of the crate and tells Gradle it can find the Android component there +//! when it gets sourced into the hosting application's build tree. +//! +//! Assuming a properly configured Gradle project, the slow (~500ms) script should only run once per Gradle sync while the `android-release-support` crate +//! remains untouched. This is due to the configuration cache previously mentioned and is what ensures performance on-par with a "normal" Maven repository. +//! Upon any version updates (semver, Git refs, etc), the change will be detected as-intended by Gradle, break the cache, and the project will update the dependency reference to the new AAR file. +//! +//! ### Precompiled artifacts? +//! +//! For some, the notion of shipping something pre-compiled with an existing source distribution might seem incorrect, or insecure. However in this specific case, +//! putting aside the fact shipping Kotlin code doesn't work (see above), there are many reasons this isn't the case: +//! - Shipping pre-compiled artifacts is normal in the Java ecosystem. Maven Central and other package repositories do the same thing and serve `.jar` downloads. +//! - Those not using Android will never download the pre-compiled AAR file. +//! - The artifacts are incredibly easy to reproduce given an identical compilation toolchain. +//! - The artifacts are not native executables, or raw `.jar` files, so they can't be accidentally executed on a host system. +//! +//! ## Summary +//! +//! In summary, the selected distribution method avoids most of the previous pitfalls while still balancing a good experience for `cargo` and Gradle users. Some of its +//! positive properties include: +//! - Full compatibility with Cargo's dependency management, including Git patching[^1] +//! - No version checking or synchronization required +//! - Painless and harmless to integrate into an Android app's build system +//! - Low maintenance for the main crate maintainers' +//! +//! [^1]: The Git reference being used must have the local maven repository built and checked-in first. diff --git a/android/rustls-platform-verifier/build.gradle b/android/rustls-platform-verifier/build.gradle index c285d5ac..8171ef72 100644 --- a/android/rustls-platform-verifier/build.gradle +++ b/android/rustls-platform-verifier/build.gradle @@ -50,7 +50,7 @@ android { task buildTestLib(type: Exec) { workingDir "../../" - commandLine "cargo", "ndk", "-t", getOsArch(), "-o", "android/rustls-platform-verifier/src/androidTest/jniLibs", "build", "--features", "ffi-testing" + commandLine "cargo", "ndk", "-t", getOsArch(), "-o", "android/rustls-platform-verifier/src/androidTest/jniLibs", "build", "-p", "rustls-platform-verifier", "--features", "ffi-testing" } // Only compile the test library if this package is being built for testing by itself. diff --git a/android/settings.gradle b/android/settings.gradle index e4416705..e00d83fe 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -12,19 +12,9 @@ dependencyResolutionManagement { mavenCentral() } - // We use a version catalog for two reasons: - // 1. Ease of dependency management - // 2. Supporting having our versions overridden by a larger project including us - // as a composite build. This lets versions stay in sync when they would otherwise become - // incompatible. Examples of this include AGP, where an actual app might have a newer one - // then this library (which doesn't need to). - // - // This works by first trying to read global property that a parent module could advertise - // and then falling back to our local definitions. In combination, both project-local tasks - // still work as intended and use as a library in a full application. versionCatalogs { libs { - from(files(System.getProperty("versions.path", "gradle/libraries.versions.toml"))) + from(files("gradle/libraries.versions.toml")) } } } diff --git a/ci/package_android_release.sh b/ci/package_android_release.sh new file mode 100755 index 00000000..91b06eac --- /dev/null +++ b/ci/package_android_release.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash + +# This script's purpose is to automate the build + packaging steps for the pre-compiled Android verifier component. +# It works with template files and directories inside the `android-release-support/` part of the repository to setup +# a Maven local repository and then add the pre-compiled AAR file into it for distribution. The results of this packaging +# are then included by `cargo` when publishing `rustls-platform-verifier-android`. + +set -euo pipefail + +if ! type mvn > /dev/null; then + echo "The maven CLI, mvn, is required to run this script." + echo "Download it from: https://maven.apache.org/download.cgi" + exit 1 +fi + +version=$(grep -m 1 "version = " android-release-support/Cargo.toml | tr -d "version= " | tr -d '"') + +echo "Packaging v$version of the Android support component" + +pushd ./android + +./gradlew assembleRelease + +popd + +artifact_name="rustls-platform-verifier-release.aar" + +pushd ./android-release-support + +artifact_path="../android/rustls-platform-verifier/build/outputs/aar/$artifact_name" + +# Ensure no prior artifacts are present +git clean -dfX "./maven/" + +cp ./pom-template.xml ./maven/pom.xml + +# This sequence is meant to workaround the incompatibilites between macOS's sed +# command and the GNU command. Referenced from the following: +# https://stackoverflow.com/questions/5694228/sed-in-place-flag-that-works-both-on-mac-bsd-and-linux +sed -i.bak "s/\$VERSION/$version/" ./maven/pom.xml +rm ./maven/pom.xml.bak + +mvn install:install-file -Dfile="$artifact_path" -Dpackaging="aar" -DpomFile="./maven/pom.xml" -DlocalRepositoryPath="./maven/" diff --git a/rustls-platform-verifier/Cargo.toml b/rustls-platform-verifier/Cargo.toml new file mode 100644 index 00000000..9403a64b --- /dev/null +++ b/rustls-platform-verifier/Cargo.toml @@ -0,0 +1,65 @@ +[package] +name = "rustls-platform-verifier" +version = "0.1.0" +authors = ["ComplexSpaces ", "1Password"] +description = "rustls-platform-verifier supports verifying TLS certificates in rustls with the operating system verifier" +keywords = ["tls", "certificate", "verification", "os", "native"] +repository = "https://github.com/rustls/rustls-platform-verifier" +license = "MIT OR Apache-2.0" +edition = "2021" +rust-version = "1.64.0" + +[lib] +name = "rustls_platform_verifier" +# Note: The `cdylib` specification is for testing only. The shared library +# is not expected to have a stable API. +crate-type = ["cdylib", "rlib"] + +[features] +# Enables a C interface to use for testing where `cargo` can't be used. +# This feature is not stable, nor is the interface exported when it is enabled. +# Do not rely on this or use it in production. +ffi-testing = ["android_logger"] +# Enables APIs that expose lower-level verifier types for debugging purposes. +dbg = [] +# Enables `log::debug` base64-encoded logging of all end-entity certificates processed +# by the platform's verifier. +cert-logging = ["base64"] +# Used for nicely documenting the Android-specific APIs. This feature is not stable. +docsrs = ["jni", "once_cell"] + +[dependencies] +rustls = { version = "0.21", features = ["dangerous_configuration", "tls12", "logging"] } +log = { version = "0.4" } +base64 = { version = "0.21", optional = true } # Only used when the `cert-logging` feature is enabled. +jni = { version = "0.19", default-features = false, optional = true } # Only used during doc generation +once_cell = { version = "1.9", optional = true } # Only used during doc generation. + +[target.'cfg(target_os = "linux")'.dependencies] +rustls-native-certs = "0.6" +once_cell = "1.9" +webpki = { package = "rustls-webpki", version = "0.101", features = ["alloc", "std"] } + +[target.'cfg(target_os = "android")'.dependencies] +rustls-platform-verifier-android = { path = "../android-release-support", version = "0.1.0" } +jni = { version = "0.19", default-features = false } +webpki = { package = "rustls-webpki", version = "0.101", features = ["alloc", "std"] } +once_cell = "1.9" +android_logger = { version = "0.13", optional = true } # Only used during testing. + +[target.'cfg(target_arch = "wasm32")'.dependencies] +once_cell = "1.9" +webpki-roots = "0.25" + +[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] +core-foundation = "0.9" +core-foundation-sys = "0.8" +security-framework = { version = "2.6", features = ["OSX_10_14"] } +security-framework-sys = { version = "2.4", features = ["OSX_10_14"] } + +[target.'cfg(windows)'.dependencies] +winapi = { version = "0.3", features = ["wincrypt", "winerror"] } + +[package.metadata.docs.rs] +rustdoc-args = ["--cfg", "docsrs"] +features = ["dbg", "docsrs"] diff --git a/rustls-platform-verifier/README.md b/rustls-platform-verifier/README.md new file mode 120000 index 00000000..32d46ee8 --- /dev/null +++ b/rustls-platform-verifier/README.md @@ -0,0 +1 @@ +../README.md \ No newline at end of file diff --git a/src/android.rs b/rustls-platform-verifier/src/android.rs similarity index 100% rename from src/android.rs rename to rustls-platform-verifier/src/android.rs diff --git a/src/lib.rs b/rustls-platform-verifier/src/lib.rs similarity index 100% rename from src/lib.rs rename to rustls-platform-verifier/src/lib.rs diff --git a/src/tests/ffi.rs b/rustls-platform-verifier/src/tests/ffi.rs similarity index 100% rename from src/tests/ffi.rs rename to rustls-platform-verifier/src/tests/ffi.rs diff --git a/src/tests/mod.rs b/rustls-platform-verifier/src/tests/mod.rs similarity index 100% rename from src/tests/mod.rs rename to rustls-platform-verifier/src/tests/mod.rs diff --git a/src/tests/verification_mock/ca.go b/rustls-platform-verifier/src/tests/verification_mock/ca.go similarity index 100% rename from src/tests/verification_mock/ca.go rename to rustls-platform-verifier/src/tests/verification_mock/ca.go diff --git a/src/tests/verification_mock/go.mod b/rustls-platform-verifier/src/tests/verification_mock/go.mod similarity index 100% rename from src/tests/verification_mock/go.mod rename to rustls-platform-verifier/src/tests/verification_mock/go.mod diff --git a/src/tests/verification_mock/go.sum b/rustls-platform-verifier/src/tests/verification_mock/go.sum similarity index 100% rename from src/tests/verification_mock/go.sum rename to rustls-platform-verifier/src/tests/verification_mock/go.sum diff --git a/src/tests/verification_mock/mod.rs b/rustls-platform-verifier/src/tests/verification_mock/mod.rs similarity index 100% rename from src/tests/verification_mock/mod.rs rename to rustls-platform-verifier/src/tests/verification_mock/mod.rs diff --git a/src/tests/verification_mock/root1-int1-ee_1-good.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-good.crt similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_1-good.crt rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-good.crt diff --git a/src/tests/verification_mock/root1-int1-ee_1-good.ocsp b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-good.ocsp similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_1-good.ocsp rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-good.ocsp diff --git a/src/tests/verification_mock/root1-int1-ee_1-revoked.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-revoked.crt similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_1-revoked.crt rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-revoked.crt diff --git a/src/tests/verification_mock/root1-int1-ee_1-revoked.ocsp b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-revoked.ocsp similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_1-revoked.ocsp rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-revoked.ocsp diff --git a/src/tests/verification_mock/root1-int1-ee_1-wrong_eku.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-wrong_eku.crt similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_1-wrong_eku.crt rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_1-wrong_eku.crt diff --git a/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.crt similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.crt rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.crt diff --git a/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.ocsp b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.ocsp similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.ocsp rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-good.ocsp diff --git a/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.crt similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.crt rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.crt diff --git a/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.ocsp b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.ocsp similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.ocsp rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-revoked.ocsp diff --git a/src/tests/verification_mock/root1-int1-ee_127.0.0.1-wrong_eku.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-wrong_eku.crt similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_127.0.0.1-wrong_eku.crt rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_127.0.0.1-wrong_eku.crt diff --git a/src/tests/verification_mock/root1-int1-ee_example.com-good.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-good.crt similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_example.com-good.crt rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-good.crt diff --git a/src/tests/verification_mock/root1-int1-ee_example.com-good.ocsp b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-good.ocsp similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_example.com-good.ocsp rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-good.ocsp diff --git a/src/tests/verification_mock/root1-int1-ee_example.com-revoked.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-revoked.crt similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_example.com-revoked.crt rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-revoked.crt diff --git a/src/tests/verification_mock/root1-int1-ee_example.com-revoked.ocsp b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-revoked.ocsp similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_example.com-revoked.ocsp rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-revoked.ocsp diff --git a/src/tests/verification_mock/root1-int1-ee_example.com-wrong_eku.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-wrong_eku.crt similarity index 100% rename from src/tests/verification_mock/root1-int1-ee_example.com-wrong_eku.crt rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1-ee_example.com-wrong_eku.crt diff --git a/src/tests/verification_mock/root1-int1.crt b/rustls-platform-verifier/src/tests/verification_mock/root1-int1.crt similarity index 100% rename from src/tests/verification_mock/root1-int1.crt rename to rustls-platform-verifier/src/tests/verification_mock/root1-int1.crt diff --git a/src/tests/verification_mock/root1.crt b/rustls-platform-verifier/src/tests/verification_mock/root1.crt similarity index 100% rename from src/tests/verification_mock/root1.crt rename to rustls-platform-verifier/src/tests/verification_mock/root1.crt diff --git a/src/tests/verification_real_world/1password_com_valid_1.crt b/rustls-platform-verifier/src/tests/verification_real_world/1password_com_valid_1.crt similarity index 100% rename from src/tests/verification_real_world/1password_com_valid_1.crt rename to rustls-platform-verifier/src/tests/verification_real_world/1password_com_valid_1.crt diff --git a/src/tests/verification_real_world/1password_com_valid_2.crt b/rustls-platform-verifier/src/tests/verification_real_world/1password_com_valid_2.crt similarity index 100% rename from src/tests/verification_real_world/1password_com_valid_2.crt rename to rustls-platform-verifier/src/tests/verification_real_world/1password_com_valid_2.crt diff --git a/src/tests/verification_real_world/1password_com_valid_3.crt b/rustls-platform-verifier/src/tests/verification_real_world/1password_com_valid_3.crt similarity index 100% rename from src/tests/verification_real_world/1password_com_valid_3.crt rename to rustls-platform-verifier/src/tests/verification_real_world/1password_com_valid_3.crt diff --git a/src/tests/verification_real_world/1password_com_valid_4.crt b/rustls-platform-verifier/src/tests/verification_real_world/1password_com_valid_4.crt similarity index 100% rename from src/tests/verification_real_world/1password_com_valid_4.crt rename to rustls-platform-verifier/src/tests/verification_real_world/1password_com_valid_4.crt diff --git a/src/tests/verification_real_world/agilebits_com_valid_1.crt b/rustls-platform-verifier/src/tests/verification_real_world/agilebits_com_valid_1.crt similarity index 100% rename from src/tests/verification_real_world/agilebits_com_valid_1.crt rename to rustls-platform-verifier/src/tests/verification_real_world/agilebits_com_valid_1.crt diff --git a/src/tests/verification_real_world/agilebits_com_valid_2.crt b/rustls-platform-verifier/src/tests/verification_real_world/agilebits_com_valid_2.crt similarity index 100% rename from src/tests/verification_real_world/agilebits_com_valid_2.crt rename to rustls-platform-verifier/src/tests/verification_real_world/agilebits_com_valid_2.crt diff --git a/src/tests/verification_real_world/agilebits_com_valid_3.crt b/rustls-platform-verifier/src/tests/verification_real_world/agilebits_com_valid_3.crt similarity index 100% rename from src/tests/verification_real_world/agilebits_com_valid_3.crt rename to rustls-platform-verifier/src/tests/verification_real_world/agilebits_com_valid_3.crt diff --git a/src/tests/verification_real_world/agilebits_com_valid_4.crt b/rustls-platform-verifier/src/tests/verification_real_world/agilebits_com_valid_4.crt similarity index 100% rename from src/tests/verification_real_world/agilebits_com_valid_4.crt rename to rustls-platform-verifier/src/tests/verification_real_world/agilebits_com_valid_4.crt diff --git a/src/tests/verification_real_world/letsencrypt_org_valid_1.crt b/rustls-platform-verifier/src/tests/verification_real_world/letsencrypt_org_valid_1.crt similarity index 100% rename from src/tests/verification_real_world/letsencrypt_org_valid_1.crt rename to rustls-platform-verifier/src/tests/verification_real_world/letsencrypt_org_valid_1.crt diff --git a/src/tests/verification_real_world/letsencrypt_org_valid_2.crt b/rustls-platform-verifier/src/tests/verification_real_world/letsencrypt_org_valid_2.crt similarity index 100% rename from src/tests/verification_real_world/letsencrypt_org_valid_2.crt rename to rustls-platform-verifier/src/tests/verification_real_world/letsencrypt_org_valid_2.crt diff --git a/src/tests/verification_real_world/letsencrypt_org_valid_3.crt b/rustls-platform-verifier/src/tests/verification_real_world/letsencrypt_org_valid_3.crt similarity index 100% rename from src/tests/verification_real_world/letsencrypt_org_valid_3.crt rename to rustls-platform-verifier/src/tests/verification_real_world/letsencrypt_org_valid_3.crt diff --git a/src/tests/verification_real_world/mod.rs b/rustls-platform-verifier/src/tests/verification_real_world/mod.rs similarity index 100% rename from src/tests/verification_real_world/mod.rs rename to rustls-platform-verifier/src/tests/verification_real_world/mod.rs diff --git a/src/tests/verification_real_world/revoked_badssl_com_1.crt b/rustls-platform-verifier/src/tests/verification_real_world/revoked_badssl_com_1.crt similarity index 100% rename from src/tests/verification_real_world/revoked_badssl_com_1.crt rename to rustls-platform-verifier/src/tests/verification_real_world/revoked_badssl_com_1.crt diff --git a/src/tests/verification_real_world/revoked_badssl_com_1.ocsp b/rustls-platform-verifier/src/tests/verification_real_world/revoked_badssl_com_1.ocsp similarity index 100% rename from src/tests/verification_real_world/revoked_badssl_com_1.ocsp rename to rustls-platform-verifier/src/tests/verification_real_world/revoked_badssl_com_1.ocsp diff --git a/src/tests/verification_real_world/revoked_badssl_com_2.crt b/rustls-platform-verifier/src/tests/verification_real_world/revoked_badssl_com_2.crt similarity index 100% rename from src/tests/verification_real_world/revoked_badssl_com_2.crt rename to rustls-platform-verifier/src/tests/verification_real_world/revoked_badssl_com_2.crt diff --git a/src/tests/verification_real_world/update_valid_ee_certs.rs b/rustls-platform-verifier/src/tests/verification_real_world/update_valid_ee_certs.rs similarity index 100% rename from src/tests/verification_real_world/update_valid_ee_certs.rs rename to rustls-platform-verifier/src/tests/verification_real_world/update_valid_ee_certs.rs diff --git a/src/verification/android.rs b/rustls-platform-verifier/src/verification/android.rs similarity index 100% rename from src/verification/android.rs rename to rustls-platform-verifier/src/verification/android.rs diff --git a/src/verification/apple.rs b/rustls-platform-verifier/src/verification/apple.rs similarity index 100% rename from src/verification/apple.rs rename to rustls-platform-verifier/src/verification/apple.rs diff --git a/src/verification/mod.rs b/rustls-platform-verifier/src/verification/mod.rs similarity index 100% rename from src/verification/mod.rs rename to rustls-platform-verifier/src/verification/mod.rs diff --git a/src/verification/others.rs b/rustls-platform-verifier/src/verification/others.rs similarity index 100% rename from src/verification/others.rs rename to rustls-platform-verifier/src/verification/others.rs diff --git a/src/verification/windows.rs b/rustls-platform-verifier/src/verification/windows.rs similarity index 100% rename from src/verification/windows.rs rename to rustls-platform-verifier/src/verification/windows.rs diff --git a/src/windows.rs b/rustls-platform-verifier/src/windows.rs similarity index 100% rename from src/windows.rs rename to rustls-platform-verifier/src/windows.rs