add crate for provider integration tests

As an initial starting point, test that the aws-lc-rs HPKE suites from
the main rustls crate and the hpke-rs HPKE suites from the
provider-example crate can interoperate.

This process is slower (~30s) so having the tests in a separate crate is
helpful. It also allows us to take heavier deps (like the
provider-example crate, hpke-rs and rust crypto).
This commit is contained in:
Daniel McCarney committed 2024-05-31 12:46:48 +00:00
1 parent d8a9498184
commit 209e892992
9 files changed
+82 -23

No files matched your search

+3
View File
@@ -98,6 +98,9 @@ jobs:
- name: cargo build (debug; rustls-provider-example lib in no-std mode)
run: cargo build --locked -p rustls-provider-example --no-default-features
- name: cargo build (debug; rustls-provider-test)
run: cargo build --locked -p rustls-provider-test
msrv:
name: MSRV
runs-on: ubuntu-latest
Generated
+11 -3
View File
@@ -2346,7 +2346,6 @@ dependencies = [
"der",
"ecdsa",
"env_logger",
"hex",
"hmac",
"hpke-rs",
"hpke-rs-crypto",
@@ -2359,14 +2358,23 @@ dependencies = [
"rustls 0.23.8",
"rustls-pki-types",
"rustls-webpki 0.102.4",
"serde",
"serde_json",
"sha2",
"signature",
"webpki-roots 0.26.1",
"x25519-dalek",
]
[[package]]
name = "rustls-provider-test"
version = "0.1.0"
dependencies = [
"hex",
"rustls 0.23.8",
"rustls-provider-example",
"serde",
"serde_json",
]
[[package]]
name = "rustls-webpki"
version = "0.101.7"
+2
View File
@@ -14,6 +14,8 @@ members = [
"rustls",
# experimental post-quantum algorithm support
"rustls-post-quantum",
# rustls cryptography provider integration tests
"rustls-provider-test",
]
default-members = [
"examples",
+3
View File
@@ -18,4 +18,7 @@ cargo test --locked $(admin/all-features-except brotli rustls)
cargo test --locked --all-features run_bogo_tests_ring -- --ignored
cargo test --locked --all-features run_bogo_tests_aws_lc_rs -- --ignored
## provider tests
cargo test --locked --package rustls-provider-test
cargo llvm-cov report "$@"
-7
View File
@@ -27,16 +27,9 @@ x25519-dalek = "2"
[dev-dependencies]
env_logger = "0.10" # 0.11 requires 1.71 MSRV even as a dev-dep (due to manifest features)
hex = "0.4.3"
rcgen = { version = "0.13", features = ["aws_lc_rs"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
webpki-roots = "0.26"
[features]
default = ["std"]
std = ["hpke-rs/std", "hpke-rs-crypto/std", "pkcs8/std", "rustls/std"]
[[test]]
name = "hpke"
required-features = ["std"]
+14
View File
@@ -0,0 +1,14 @@
[package]
name = "rustls-provider-test"
version = "0.1.0"
edition = "2021"
license = "Apache-2.0 OR ISC OR MIT"
description = "Integration tests for Rustls cryptography providers"
publish = false
[dependencies]
hex = "0.4"
provider-example = { package = "rustls-provider-example", version = "0.0.1", path = "../provider-example" }
rustls = { version = "0.23.8", features = ["aws_lc_rs", "logging"], path = "../rustls" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
+4
View File
@@ -0,0 +1,4 @@
# Rustls Provider Tests
This crate is an unpublished workspace crate that holds integration tests for different cryptography providers
and associated machinery. We add tests here to avoid taking heavy dependencies on the main rustls crate.
@@ -1,9 +1,9 @@
use std::fs::File;
use rustls::crypto::aws_lc_rs;
use rustls::crypto::hpke::{Hpke, HpkePrivateKey, HpkePublicKey, HpkeSuite};
use rustls::internal::msgs::enums::{HpkeAead, HpkeKdf, HpkeKem};
use rustls::internal::msgs::handshake::HpkeSymmetricCipherSuite;
use rustls_provider_example::hpke::ALL_SUPPORTED_SUITES;
use serde::Deserialize;
/// Confirm open/seal operations work using the test vectors from [RFC 9180 Appendix A].
@@ -12,7 +12,7 @@ use serde::Deserialize;
#[test]
fn check_test_vectors() {
for (idx, vec) in test_vectors().into_iter().enumerate() {
let Some(hpke) = vec.applicable() else {
let Some(hpke_pairs) = vec.applicable() else {
println!("skipping inapplicable vector {idx}");
continue;
};
@@ -26,14 +26,16 @@ fn check_test_vectors() {
let aad = hex::decode(enc.aad).unwrap();
let pt = hex::decode(enc.pt).unwrap();
let (enc, ciphertext) = hpke
.seal(&info, &aad, &pt, &pk_r)
.unwrap();
for (sealer, opener) in &hpke_pairs {
let (enc, ciphertext) = sealer
.seal(&info, &aad, &pt, &pk_r)
.unwrap();
let plaintext = hpke
.open(&enc, &info, &aad, &ciphertext, &sk_r)
.unwrap();
assert_eq!(plaintext, pt);
let plaintext = opener
.open(&enc, &info, &aad, &ciphertext, &sk_r)
.unwrap();
assert_eq!(plaintext, pt);
}
}
}
}
@@ -69,15 +71,45 @@ impl TestVector {
}
}
fn applicable(&self) -> Option<&'static dyn Hpke> {
fn applicable(&self) -> Option<Vec<(&'static dyn Hpke, &'static dyn Hpke)>> {
// Only base mode test vectors for supported suites are applicable.
if self.mode == 0 {
if self.mode != 0 {
return None;
}
ALL_SUPPORTED_SUITES
match (
Self::lookup_suite(self.suite(), aws_lc_rs::hpke::ALL_SUPPORTED_SUITES),
Self::lookup_suite(self.suite(), provider_example::hpke::ALL_SUPPORTED_SUITES),
) {
// Both providers support the suite. Test against themselves, and each other.
(Some(aws_suite), Some(hpke_rs_suite)) => Some(vec![
(aws_suite, aws_suite),
(hpke_rs_suite, hpke_rs_suite),
(aws_suite, hpke_rs_suite),
(hpke_rs_suite, aws_suite),
]),
// aws-lc-rs supported the suite, not hpke-rs, test against itself
(Some(aws_suite), None) => Some(vec![(aws_suite, aws_suite)]),
// hpke-rs supported the suite, not AWS-LC-RS, test against itself
//
// Note: presently there are no suites hpke-rs supports that aws-lc-rs doesn't. This
// is future-proofing.
(None, Some(hpke_rs_suite)) => Some(vec![(hpke_rs_suite, hpke_rs_suite)]),
// Neither provider supported the suite - nothing to do.
(None, None) => None,
}
}
fn lookup_suite(
suite: HpkeSuite,
supported: &[&'static dyn Hpke],
) -> Option<&'static dyn Hpke> {
supported
.iter()
.find(|hpke| hpke.suite() == self.suite())
.find(|s| s.suite() == suite)
.copied()
}
}