From 1c7273143ed8e2b8d05a5bc53e630b98f64badb4 Mon Sep 17 00:00:00 2001 From: "sinu.eth" <65924192+sinui0@users.noreply.github.com> Date: Tue, 10 Oct 2023 13:13:40 -0700 Subject: [PATCH] tlsn-core fixtures (#359) * move fixtures back into tlsn-core crate * add --all-features tests * limit --all-features tests to tlsn workspace * satisfy clippy * fix eph key fixture * Update tlsn/tlsn-core/src/fixtures/cert.rs Co-authored-by: dan * remove webpki tests, and factor out cert verifier * fix unused import --------- Co-authored-by: dan --- .github/workflows/rust.yml | 10 + components/tls/tls-client-async/src/lib.rs | 2 +- tlsn/Cargo.toml | 2 - tlsn/tlsn-core/Cargo.toml | 4 +- tlsn/tlsn-core/src/commitment/builder.rs | 6 +- tlsn/tlsn-core/src/fixtures/cert.rs | 130 +++++++ tlsn/tlsn-core/src/fixtures/mod.rs | 164 ++++++++ .../fixtures}/testdata/key_exchange/README | 0 .../key_exchange/appliedzkp.org/ca.der | Bin .../key_exchange/appliedzkp.org/client_random | 0 .../key_exchange/appliedzkp.org/ee.der | Bin .../key_exchange/appliedzkp.org/inter.der | Bin .../key_exchange/appliedzkp.org/pubkey | 0 .../key_exchange/appliedzkp.org/server_random | 0 .../key_exchange/appliedzkp.org/signature | 0 .../key_exchange/tlsnotary.org/ca.der | Bin .../key_exchange/tlsnotary.org/client_random | 0 .../key_exchange/tlsnotary.org/ee.der | Bin .../key_exchange/tlsnotary.org/inter.der | Bin .../key_exchange/tlsnotary.org/pubkey | 0 .../key_exchange/tlsnotary.org/server_random | 0 .../key_exchange/tlsnotary.org/signature | 0 .../testdata/key_exchange/unknown/ca.der | Bin .../testdata/key_exchange/unknown/ee.der | Bin tlsn/tlsn-core/src/lib.rs | 10 +- tlsn/tlsn-core/src/proof/tls.rs | 25 +- tlsn/tlsn-core/tests/api.rs | 41 +- tlsn/tlsn-fixtures/Cargo.toml | 12 - tlsn/tlsn-fixtures/src/cert.rs | 367 ------------------ tlsn/tlsn-fixtures/src/lib.rs | 2 - 30 files changed, 336 insertions(+), 439 deletions(-) create mode 100644 tlsn/tlsn-core/src/fixtures/cert.rs create mode 100644 tlsn/tlsn-core/src/fixtures/mod.rs rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/README (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/appliedzkp.org/ca.der (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/appliedzkp.org/client_random (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/appliedzkp.org/ee.der (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/appliedzkp.org/inter.der (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/appliedzkp.org/pubkey (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/appliedzkp.org/server_random (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/appliedzkp.org/signature (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/tlsnotary.org/ca.der (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/tlsnotary.org/client_random (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/tlsnotary.org/ee.der (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/tlsnotary.org/inter.der (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/tlsnotary.org/pubkey (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/tlsnotary.org/server_random (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/tlsnotary.org/signature (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/unknown/ca.der (100%) rename tlsn/{tlsn-fixtures/src => tlsn-core/src/fixtures}/testdata/key_exchange/unknown/ee.der (100%) delete mode 100644 tlsn/tlsn-fixtures/Cargo.toml delete mode 100644 tlsn/tlsn-fixtures/src/cert.rs delete mode 100644 tlsn/tlsn-fixtures/src/lib.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 43ed8e008b..3fd9cacc83 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -31,6 +31,8 @@ jobs: include: - package: components/integration-tests release: true + - package: tlsn + all-features: true defaults: run: working-directory: ${{ matrix.package }} @@ -63,10 +65,18 @@ jobs: if: ${{ matrix.release != true }} run: cargo test --lib --bins --tests --examples --workspace + - name: "Test all features" + if: ${{ matrix.release != true && matrix.all-features == true }} + run: cargo test --lib --bins --tests --examples --workspace --all-features + - name: "Integration Test" if: ${{ matrix.release == true }} run: cargo test --release --tests + - name: "Integration Test all features" + if: ${{ matrix.release == true && matrix.all-features == true }} + run: cargo test --release --tests --all-features + - name: "Check that benches compile" run: cargo bench --no-run diff --git a/components/tls/tls-client-async/src/lib.rs b/components/tls/tls-client-async/src/lib.rs index 8351821a0a..79a13b4bda 100644 --- a/components/tls/tls-client-async/src/lib.rs +++ b/components/tls/tls-client-async/src/lib.rs @@ -121,7 +121,7 @@ pub fn bind_client( // error. let _ignored = client.write_tls_async(&mut server_tx).await; - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + Err(std::io::Error::new(std::io::ErrorKind::InvalidData, e))? } } diff --git a/tlsn/Cargo.toml b/tlsn/Cargo.toml index 493c6aed5a..20a16675b0 100644 --- a/tlsn/Cargo.toml +++ b/tlsn/Cargo.toml @@ -3,7 +3,6 @@ members = [ "tlsn-core", "tlsn-notary", "tlsn-prover", - "tlsn-fixtures", "tlsn-server-fixture", "tests-integration", "examples", @@ -14,7 +13,6 @@ resolver = "2" tlsn-core = { path = "tlsn-core" } tlsn-prover = { path = "tlsn-prover" } tlsn-notary = { path = "tlsn-notary" } -tlsn-fixtures = { path = "tlsn-fixtures" } tlsn-server-fixture = { path = "tlsn-server-fixture" } tlsn-tls-core = { path = "../components/tls/tls-core" } diff --git a/tlsn/tlsn-core/Cargo.toml b/tlsn/tlsn-core/Cargo.toml index 7a7c59ee48..595114faa1 100644 --- a/tlsn/tlsn-core/Cargo.toml +++ b/tlsn/tlsn-core/Cargo.toml @@ -10,6 +10,7 @@ edition = "2021" [features] default = [] +fixtures = ["dep:hex"] [dependencies] tlsn-tls-core = { workspace = true, features = ["serde"] } @@ -33,8 +34,6 @@ opaque-debug.workspace = true bimap = { version = "0.6.3", features = ["serde"] } [dev-dependencies] -tlsn-fixtures.workspace = true - rstest.workspace = true hex.workspace = true rand_core.workspace = true @@ -43,3 +42,4 @@ bincode.workspace = true [[test]] name = "api" +required-features = ["fixtures"] diff --git a/tlsn/tlsn-core/src/commitment/builder.rs b/tlsn/tlsn-core/src/commitment/builder.rs index aa2fe8f409..bddf0ecd6e 100644 --- a/tlsn/tlsn-core/src/commitment/builder.rs +++ b/tlsn/tlsn-core/src/commitment/builder.rs @@ -2,7 +2,6 @@ use std::collections::HashMap; use bimap::BiMap; use mpz_core::hash::Hash; -use mpz_garble_core::{encoding_state, EncodedValue}; use utils::range::RangeSet; use crate::{ @@ -11,12 +10,9 @@ use crate::{ }, merkle::MerkleTree, transcript::get_value_ids, - Direction, + Direction, EncodingProvider, }; -type EncodingProvider = - Box Option>> + Send>; - /// An error for [`TranscriptCommitmentBuilder`] #[derive(Debug, thiserror::Error)] pub enum TranscriptCommitmentBuilderError { diff --git a/tlsn/tlsn-core/src/fixtures/cert.rs b/tlsn/tlsn-core/src/fixtures/cert.rs new file mode 100644 index 0000000000..c52d14be46 --- /dev/null +++ b/tlsn/tlsn-core/src/fixtures/cert.rs @@ -0,0 +1,130 @@ +use tls_core::{ + key::{Certificate, PublicKey}, + msgs::{ + codec::Codec, + enums::{NamedGroup, SignatureScheme}, + handshake::{DigitallySignedStruct, Random, ServerECDHParams}, + }, +}; + +use hex::FromHex; + +/// Collects data needed for testing +pub struct TestData { + /// end-entity cert + pub ee: Certificate, + /// intermediate cert + pub inter: Certificate, + /// CA cert + pub ca: Certificate, + /// client random + pub cr: Random, + /// server random + pub sr: Random, + /// server ephemeral P256 pubkey + pub pubkey: PublicKey, + /// server signature over the key exchange parameters + pub sig: Vec, + /// unix time when TLS handshake began + pub time: u64, + /// algorithm used to create the sig + pub sig_scheme: SignatureScheme, + /// DNS name of the website + pub dns_name: String, +} + +impl TestData { + /// Returns the [ServerECDHParams] in encoded form + pub fn kx_params(&self) -> Vec { + let mut params = Vec::new(); + let ecdh_params = ServerECDHParams::new(NamedGroup::secp256r1, &self.pubkey.key); + ecdh_params.encode(&mut params); + params + } + + /// Returns the [DigitallySignedStruct] + pub fn dss(&self) -> DigitallySignedStruct { + DigitallySignedStruct::new(self.sig_scheme, self.sig.clone()) + } + + /// Returns the client random + server random + kx params in encoded form + pub fn signature_msg(&self) -> Vec { + let mut msg = Vec::new(); + msg.extend_from_slice(&self.cr.0); + msg.extend_from_slice(&self.sr.0); + msg.extend_from_slice(&self.kx_params()); + msg + } +} + +/// Returns test data for the tlsnotary.org website +pub fn tlsnotary() -> TestData { + TestData { + ee: Certificate(include_bytes!("testdata/key_exchange/tlsnotary.org/ee.der").to_vec()), + inter: Certificate( + include_bytes!("testdata/key_exchange/tlsnotary.org/inter.der").to_vec(), + ), + ca: Certificate(include_bytes!("testdata/key_exchange/tlsnotary.org/ca.der").to_vec()), + cr: Random( + <[u8; 32]>::from_hex(include_bytes!( + "testdata/key_exchange/tlsnotary.org/client_random" + )) + .unwrap(), + ), + sr: Random( + <[u8; 32]>::from_hex(include_bytes!( + "testdata/key_exchange/tlsnotary.org/server_random" + )) + .unwrap(), + ), + pubkey: PublicKey::new( + NamedGroup::secp256r1, + &Vec::::from_hex(include_bytes!("testdata/key_exchange/tlsnotary.org/pubkey")) + .unwrap(), + ), + sig: Vec::::from_hex(include_bytes!( + "testdata/key_exchange/tlsnotary.org/signature" + )) + .unwrap(), + time: 1671637529, + sig_scheme: SignatureScheme::RSA_PKCS1_SHA256, + dns_name: "tlsnotary.org".to_string(), + } +} + +/// Returns test data for the appliedzkp.org website +pub fn appliedzkp() -> TestData { + TestData { + ee: Certificate(include_bytes!("testdata/key_exchange/appliedzkp.org/ee.der").to_vec()), + inter: Certificate( + include_bytes!("testdata/key_exchange/appliedzkp.org/inter.der").to_vec(), + ), + ca: Certificate(include_bytes!("testdata/key_exchange/appliedzkp.org/ca.der").to_vec()), + cr: Random( + <[u8; 32]>::from_hex(include_bytes!( + "testdata/key_exchange/appliedzkp.org/client_random" + )) + .unwrap(), + ), + sr: Random( + <[u8; 32]>::from_hex(include_bytes!( + "testdata/key_exchange/appliedzkp.org/server_random" + )) + .unwrap(), + ), + pubkey: PublicKey::new( + NamedGroup::secp256r1, + &Vec::::from_hex(include_bytes!( + "testdata/key_exchange/appliedzkp.org/pubkey" + )) + .unwrap(), + ), + sig: Vec::::from_hex(include_bytes!( + "testdata/key_exchange/appliedzkp.org/signature" + )) + .unwrap(), + time: 1671637529, + sig_scheme: SignatureScheme::ECDSA_NISTP256_SHA256, + dns_name: "appliedzkp.org".to_string(), + } +} diff --git a/tlsn/tlsn-core/src/fixtures/mod.rs b/tlsn/tlsn-core/src/fixtures/mod.rs new file mode 100644 index 0000000000..59ce6e26cf --- /dev/null +++ b/tlsn/tlsn-core/src/fixtures/mod.rs @@ -0,0 +1,164 @@ +//! Fixtures for testing + +/// Certificate fixtures +pub mod cert; + +use std::collections::HashMap; + +use hex::FromHex; +use mpz_circuits::types::ValueType; +use mpz_core::{commit::HashCommit, hash::Hash, value::ValueId}; +use mpz_garble_core::{ChaChaEncoder, Encoder}; +use tls_core::{ + cert::ServerCertDetails, + handshake::HandshakeData, + ke::ServerKxDetails, + key::{Certificate, PublicKey}, + msgs::{ + codec::Codec, + enums::{NamedGroup, SignatureScheme}, + handshake::{DigitallySignedStruct, Random, ServerECDHParams}, + }, +}; + +use p256::ecdsa::SigningKey; + +use crate::{ + merkle::MerkleRoot, + session::{HandshakeSummary, SessionHeader}, + EncodingProvider, +}; + +/// Returns a session header fixture using the given transcript lengths and merkle root. +/// +/// # Arguments +/// +/// * `root` - The merkle root of the transcript commitments. +/// * `sent_len` - The length of the sent transcript. +/// * `recv_len` - The length of the received transcript. +pub fn session_header(root: MerkleRoot, sent_len: usize, recv_len: usize) -> SessionHeader { + SessionHeader::new( + encoder_seed(), + root, + sent_len, + recv_len, + handshake_summary(), + ) +} + +/// Returns an encoding provider fixture using the given transcripts. +pub fn encoding_provider(transcript_tx: &[u8], transcript_rx: &[u8]) -> EncodingProvider { + let encoder = encoder(); + let mut active_encodings = HashMap::new(); + for (idx, byte) in transcript_tx.iter().enumerate() { + let id = format!("tx/{idx}"); + let enc = encoder.encode_by_type(ValueId::new(&id).to_u64(), &ValueType::U8); + active_encodings.insert(id, enc.select(*byte).unwrap()); + } + for (idx, byte) in transcript_rx.iter().enumerate() { + let id = format!("rx/{idx}"); + let enc = encoder.encode_by_type(ValueId::new(&id).to_u64(), &ValueType::U8); + active_encodings.insert(id, enc.select(*byte).unwrap()); + } + + Box::new(move |ids: &[&str]| { + ids.iter() + .map(|id| active_encodings.get(*id).cloned()) + .collect() + }) +} + +/// Returns a handshake summary fixture. +pub fn handshake_summary() -> HandshakeSummary { + HandshakeSummary::new(1671637529, server_ephemeral_key(), handshake_commitment()) +} + +/// Returns a handshake commitment fixture. +pub fn handshake_commitment() -> Hash { + let (_, hash) = handshake_data().hash_commit(); + hash +} + +/// Returns a handshake data fixture. +pub fn handshake_data() -> HandshakeData { + HandshakeData::new( + server_cert_details(), + server_kx_details(), + client_random(), + server_random(), + ) +} + +/// Returns a server certificate details fixture. +pub fn server_cert_details() -> ServerCertDetails { + ServerCertDetails::new( + vec![ + Certificate(include_bytes!("testdata/key_exchange/tlsnotary.org/ee.der").to_vec()), + Certificate(include_bytes!("testdata/key_exchange/tlsnotary.org/inter.der").to_vec()), + Certificate(include_bytes!("testdata/key_exchange/tlsnotary.org/ca.der").to_vec()), + ], + vec![], + None, + ) +} + +/// Returns a server key exchange details fixture. +pub fn server_kx_details() -> ServerKxDetails { + let mut params = Vec::new(); + let ecdh_params = ServerECDHParams::new(NamedGroup::secp256r1, &server_ephemeral_key().key); + ecdh_params.encode(&mut params); + + ServerKxDetails::new( + params, + DigitallySignedStruct::new( + SignatureScheme::RSA_PKCS1_SHA256, + Vec::::from_hex(include_bytes!( + "testdata/key_exchange/tlsnotary.org/signature" + )) + .unwrap(), + ), + ) +} + +/// Returns a client random fixture. +pub fn client_random() -> Random { + Random( + <[u8; 32]>::from_hex(include_bytes!( + "testdata/key_exchange/tlsnotary.org/client_random" + )) + .unwrap(), + ) +} + +/// Returns a server random fixture. +pub fn server_random() -> Random { + Random( + <[u8; 32]>::from_hex(include_bytes!( + "testdata/key_exchange/tlsnotary.org/server_random" + )) + .unwrap(), + ) +} + +/// Returns an encoder fixture. +pub fn encoder() -> ChaChaEncoder { + ChaChaEncoder::new(encoder_seed()) +} + +/// Returns an encoder seed fixture. +pub fn encoder_seed() -> [u8; 32] { + [0u8; 32] +} + +/// Returns a server ephemeral key fixture. +pub fn server_ephemeral_key() -> PublicKey { + PublicKey::new( + NamedGroup::secp256r1, + &Vec::::from_hex(include_bytes!("testdata/key_exchange/tlsnotary.org/pubkey")).unwrap(), + ) +} + +/// Returns a notary signing key fixture. +pub fn notary_signing_key() -> SigningKey { + SigningKey::from_slice(&[1; 32]).unwrap() +} diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/README b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/README similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/README rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/README diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/ca.der b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/ca.der similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/ca.der rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/ca.der diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/client_random b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/client_random similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/client_random rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/client_random diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/ee.der b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/ee.der similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/ee.der rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/ee.der diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/inter.der b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/inter.der similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/inter.der rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/inter.der diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/pubkey b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/pubkey similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/pubkey rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/pubkey diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/server_random b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/server_random similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/server_random rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/server_random diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/signature b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/signature similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/appliedzkp.org/signature rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/appliedzkp.org/signature diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/ca.der b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/ca.der similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/ca.der rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/ca.der diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/client_random b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/client_random similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/client_random rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/client_random diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/ee.der b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/ee.der similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/ee.der rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/ee.der diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/inter.der b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/inter.der similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/inter.der rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/inter.der diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/pubkey b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/pubkey similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/pubkey rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/pubkey diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/server_random b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/server_random similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/server_random rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/server_random diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/signature b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/signature similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/tlsnotary.org/signature rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/tlsnotary.org/signature diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/unknown/ca.der b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/unknown/ca.der similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/unknown/ca.der rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/unknown/ca.der diff --git a/tlsn/tlsn-fixtures/src/testdata/key_exchange/unknown/ee.der b/tlsn/tlsn-core/src/fixtures/testdata/key_exchange/unknown/ee.der similarity index 100% rename from tlsn/tlsn-fixtures/src/testdata/key_exchange/unknown/ee.der rename to tlsn/tlsn-core/src/fixtures/testdata/key_exchange/unknown/ee.der diff --git a/tlsn/tlsn-core/src/lib.rs b/tlsn/tlsn-core/src/lib.rs index 3e55ac46fe..3301655857 100644 --- a/tlsn/tlsn-core/src/lib.rs +++ b/tlsn/tlsn-core/src/lib.rs @@ -7,6 +7,8 @@ #![forbid(unsafe_code)] pub mod commitment; +#[cfg(feature = "fixtures")] +pub mod fixtures; pub mod merkle; pub mod msg; pub mod proof; @@ -14,11 +16,13 @@ pub mod session; mod signature; pub mod transcript; -use serde::{Deserialize, Serialize}; pub use session::{HandshakeSummary, NotarizedSession, SessionData, SessionHeader}; pub use signature::{NotaryPublicKey, Signature}; pub use transcript::{Direction, RedactedTranscript, Transcript, TranscriptSlice}; +use mpz_garble_core::{encoding_state, EncodedValue}; +use serde::{Deserialize, Serialize}; + /// The maximum allowed total bytelength of all committed data. Used to prevent DoS during verification. /// (this will cause the verifier to hash up to a max of 1GB * 128 = 128GB of plaintext encodings if the /// commitment type is [crate::commitment::Blake3]). @@ -26,6 +30,10 @@ pub use transcript::{Direction, RedactedTranscript, Transcript, TranscriptSlice} /// This value must not exceed bcs's MAX_SEQUENCE_LENGTH limit (which is (1 << 31) - 1 by default) const MAX_TOTAL_COMMITTED_DATA: usize = 1_000_000_000; +/// A provider of plaintext encodings. +pub(crate) type EncodingProvider = + Box Option>> + Send>; + /// The encoding id /// /// A 64 bit Blake3 hash which is used for the plaintext encodings diff --git a/tlsn/tlsn-core/src/proof/tls.rs b/tlsn/tlsn-core/src/proof/tls.rs index d285c72505..22200ca9d0 100644 --- a/tlsn/tlsn-core/src/proof/tls.rs +++ b/tlsn/tlsn-core/src/proof/tls.rs @@ -111,16 +111,19 @@ impl SessionProof { &self, notary_public_key: impl Into, ) -> Result<(), SessionProofError> { - let mut root_store = RootCertStore::empty(); - root_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| { - OwnedTrustAnchor::from_subject_spki_name_constraints( - ta.subject, - ta.spki, - ta.name_constraints, - ) - })); - let verifier = WebPkiVerifier::new(root_store, None); - - self.verify(notary_public_key, &verifier) + self.verify(notary_public_key, &default_cert_verifier()) } } + +fn default_cert_verifier() -> WebPkiVerifier { + let mut root_store = RootCertStore::empty(); + root_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| { + OwnedTrustAnchor::from_subject_spki_name_constraints( + ta.subject, + ta.spki, + ta.name_constraints, + ) + })); + + WebPkiVerifier::new(root_store, None) +} diff --git a/tlsn/tlsn-core/tests/api.rs b/tlsn/tlsn-core/tests/api.rs index f6a1b84d42..320c72bd59 100644 --- a/tlsn/tlsn-core/tests/api.rs +++ b/tlsn/tlsn-core/tests/api.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, ops::Range}; +use std::ops::Range; use p256::{ ecdsa::{ @@ -17,20 +17,17 @@ use tls_core::{ msgs::{enums::SignatureScheme, handshake::DigitallySignedStruct}, }; -use mpz_circuits::types::ValueType; -use mpz_core::{commit::HashCommit, serialize::CanonicalSerialize, value::ValueId}; -use mpz_garble_core::{encoding_state, ChaChaEncoder, EncodedValue, Encoder}; +use mpz_core::{commit::HashCommit, serialize::CanonicalSerialize}; use tlsn_core::{ commitment::TranscriptCommitmentBuilder, + fixtures, msg::SignedSessionHeader, proof::{SessionProof, SubstringsProof}, session::SessionData, HandshakeSummary, NotarizedSession, ServerName, SessionHeader, Signature, Transcript, }; -use tlsn_fixtures as fixtures; - #[test] /// Tests that the commitment creation protocol and verification work end-to-end fn test_api() { @@ -46,16 +43,7 @@ fn test_api() { let range2: Range = Range { start: 1, end: 3 }; // Plaintext encodings which the Prover obtained from GC evaluation - // (for simplicity of this test we instead generate the encodings using the Notary's encoder) - let notary_encoder_seed = [5u8; 32]; - let notary_encoder = ChaChaEncoder::new(notary_encoder_seed); - - let active_encodings = build_active_encodings(¬ary_encoder, data_sent, data_recv); - let encodings_provider = Box::new(move |ids: &[&str]| { - ids.iter() - .map(|id| active_encodings.get(*id).cloned()) - .collect() - }); + let encodings_provider = fixtures::encoding_provider(data_sent, data_recv); // At the end of the session the Prover holds the: // - time when the TLS handshake began @@ -116,7 +104,7 @@ fn test_api() { assert!(data_sent.len() <= (u32::MAX as usize) && data_recv.len() <= (u32::MAX as usize)); let header = SessionHeader::new( - notary_encoder_seed, + fixtures::encoder_seed(), session_data.commitments().merkle_root(), data_sent.len(), data_recv.len(), @@ -198,22 +186,3 @@ fn test_api() { assert_eq!(&sent.data()[range1], b"se".as_slice()); assert_eq!(&recv.data()[range2], b"ec".as_slice()); } - -fn build_active_encodings( - encoder: &ChaChaEncoder, - tx: &[u8], - rx: &[u8], -) -> HashMap> { - let mut active_encodings = HashMap::new(); - for (idx, byte) in tx.iter().enumerate() { - let id = format!("tx/{idx}"); - let enc = encoder.encode_by_type(ValueId::new(&id).to_u64(), &ValueType::U8); - active_encodings.insert(id, enc.select(*byte).unwrap()); - } - for (idx, byte) in rx.iter().enumerate() { - let id = format!("rx/{idx}"); - let enc = encoder.encode_by_type(ValueId::new(&id).to_u64(), &ValueType::U8); - active_encodings.insert(id, enc.select(*byte).unwrap()); - } - active_encodings -} diff --git a/tlsn/tlsn-fixtures/Cargo.toml b/tlsn/tlsn-fixtures/Cargo.toml deleted file mode 100644 index 7a2e1d2669..0000000000 --- a/tlsn/tlsn-fixtures/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "tlsn-fixtures" -version = "0.0.0" -edition = "2021" - -[dependencies] -tlsn-core.workspace = true -tlsn-tls-core.workspace = true - -hex.workspace = true -rstest.workspace = true -webpki-roots.workspace = true diff --git a/tlsn/tlsn-fixtures/src/cert.rs b/tlsn/tlsn-fixtures/src/cert.rs deleted file mode 100644 index 84330de142..0000000000 --- a/tlsn/tlsn-fixtures/src/cert.rs +++ /dev/null @@ -1,367 +0,0 @@ -#[cfg(test)] -use std::time::{Duration, SystemTime}; - -use rstest::{fixture, rstest}; -#[allow(unused_imports)] -use tls_core::{ - anchors::{OwnedTrustAnchor, RootCertStore}, - dns::ServerName, - key::{Certificate, PublicKey}, - msgs::{ - codec::Codec, - enums::{NamedGroup, SignatureScheme}, - handshake::{DigitallySignedStruct, Random, ServerECDHParams}, - }, - verify::ServerCertVerifier, -}; - -/// Collects data needed for testing -pub struct TestData { - /// end-entity cert - pub ee: Certificate, - /// intermediate cert - pub inter: Certificate, - /// CA cert - pub ca: Certificate, - /// client random - pub cr: Random, - /// server random - pub sr: Random, - /// server ephemeral P256 pubkey - pub pubkey: PublicKey, - /// server signature over the key exchange parameters - pub sig: Vec, - /// unix time when TLS handshake began - pub time: u64, - /// algorithm used to create the sig - pub sig_scheme: SignatureScheme, - /// DNS name of the website - pub dns_name: String, -} - -impl TestData { - /// Returns the [ServerECDHParams] in encoded form - pub fn kx_params(&self) -> Vec { - let mut params = Vec::new(); - let ecdh_params = ServerECDHParams::new(NamedGroup::secp256r1, &self.pubkey.key); - ecdh_params.encode(&mut params); - params - } - - /// Returns the [DigitallySignedStruct] - pub fn dss(&self) -> DigitallySignedStruct { - DigitallySignedStruct::new(self.sig_scheme, self.sig.clone()) - } - - /// Returns the client random + server random + kx params in encoded form - pub fn signature_msg(&self) -> Vec { - let mut msg = Vec::new(); - msg.extend_from_slice(&self.cr.0); - msg.extend_from_slice(&self.sr.0); - msg.extend_from_slice(&self.kx_params()); - msg - } -} - -/// Convert a hex string to bytes -fn from_hex(string: &[u8]) -> Vec { - hex::decode(string.to_ascii_lowercase()).unwrap() -} - -/// Returns a cert verifier -#[fixture] -pub fn cert_verifier() -> impl ServerCertVerifier { - let mut root_store = RootCertStore::empty(); - root_store.add_server_trust_anchors(webpki_roots::TLS_SERVER_ROOTS.0.iter().map(|ta| { - OwnedTrustAnchor::from_subject_spki_name_constraints( - ta.subject, - ta.spki, - ta.name_constraints, - ) - })); - - tls_core::verify::WebPkiVerifier::new(root_store, None) -} - -/// Returns test data for the tlsnotary.org website -#[fixture] -pub fn tlsnotary() -> TestData { - TestData { - ee: Certificate(include_bytes!("testdata/key_exchange/tlsnotary.org/ee.der").to_vec()), - inter: Certificate( - include_bytes!("testdata/key_exchange/tlsnotary.org/inter.der").to_vec(), - ), - ca: Certificate(include_bytes!("testdata/key_exchange/tlsnotary.org/ca.der").to_vec()), - cr: Random( - from_hex(include_bytes!( - "testdata/key_exchange/tlsnotary.org/client_random" - )) - .try_into() - .unwrap(), - ), - sr: Random( - from_hex(include_bytes!( - "testdata/key_exchange/tlsnotary.org/server_random" - )) - .try_into() - .unwrap(), - ), - pubkey: PublicKey::new( - NamedGroup::secp256r1, - &from_hex(include_bytes!("testdata/key_exchange/tlsnotary.org/pubkey")), - ), - sig: from_hex(include_bytes!( - "testdata/key_exchange/tlsnotary.org/signature" - )), - time: 1671637529, - sig_scheme: SignatureScheme::RSA_PKCS1_SHA256, - dns_name: "tlsnotary.org".to_string(), - } -} - -/// Returns test data for the appliedzkp.org website -#[fixture] -pub fn appliedzkp() -> TestData { - TestData { - ee: Certificate(include_bytes!("testdata/key_exchange/appliedzkp.org/ee.der").to_vec()), - inter: Certificate( - include_bytes!("testdata/key_exchange/appliedzkp.org/inter.der").to_vec(), - ), - ca: Certificate(include_bytes!("testdata/key_exchange/appliedzkp.org/ca.der").to_vec()), - cr: Random( - from_hex(include_bytes!( - "testdata/key_exchange/appliedzkp.org/client_random" - )) - .try_into() - .unwrap(), - ), - sr: Random( - from_hex(include_bytes!( - "testdata/key_exchange/appliedzkp.org/server_random" - )) - .try_into() - .unwrap(), - ), - pubkey: PublicKey::new( - NamedGroup::secp256r1, - &from_hex(include_bytes!( - "testdata/key_exchange/appliedzkp.org/pubkey" - )), - ), - sig: from_hex(include_bytes!( - "testdata/key_exchange/appliedzkp.org/signature" - )), - time: 1671637529, - sig_scheme: SignatureScheme::ECDSA_NISTP256_SHA256, - dns_name: "appliedzkp.org".to_string(), - } -} - -/// Expect chain verification to succeed -#[rstest] -#[case(tlsnotary())] -#[case(appliedzkp())] -fn test_verify_cert_chain_sucess_ca_implicit( - cert_verifier: impl ServerCertVerifier, - #[case] data: TestData, -) { - assert!(cert_verifier - .verify_server_cert( - &data.ee, - &[data.inter], - &ServerName::try_from(data.dns_name.as_ref()).unwrap(), - &mut std::iter::empty(), - &[], - SystemTime::UNIX_EPOCH + Duration::from_secs(data.time), - ) - .is_ok()); -} - -/// Expect chain verification to succeed even when a trusted CA is provided among the intermediate -/// certs. webpki handles such cases properly. -#[rstest] -#[case(tlsnotary())] -#[case(appliedzkp())] -fn test_verify_cert_chain_success_ca_explicit( - cert_verifier: impl ServerCertVerifier, - #[case] data: TestData, -) { - assert!(cert_verifier - .verify_server_cert( - &data.ee, - &[data.inter, data.ca], - &ServerName::try_from(data.dns_name.as_ref()).unwrap(), - &mut std::iter::empty(), - &[], - SystemTime::UNIX_EPOCH + Duration::from_secs(data.time), - ) - .is_ok()); -} - -/// Expect to fail since the end entity cert was not valid at the time -#[rstest] -#[case(tlsnotary())] -#[case(appliedzkp())] -fn test_verify_cert_chain_fail_bad_time( - cert_verifier: impl ServerCertVerifier, - #[case] data: TestData, -) { - // unix time when the cert chain was NOT valid - let bad_time: u64 = 1571465711; - - let err = cert_verifier.verify_server_cert( - &data.ee, - &[data.inter], - &ServerName::try_from(data.dns_name.as_ref()).unwrap(), - &mut std::iter::empty(), - &[], - SystemTime::UNIX_EPOCH + Duration::from_secs(bad_time), - ); - - assert!(matches!( - err.unwrap_err(), - tls_core::Error::InvalidCertificateData(_) - )); -} - -/// Expect to fail when no intermediate cert provided -#[rstest] -#[case(tlsnotary())] -#[case(appliedzkp())] -fn test_verify_cert_chain_fail_no_interm_cert( - cert_verifier: impl ServerCertVerifier, - #[case] data: TestData, -) { - let err = cert_verifier.verify_server_cert( - &data.ee, - &[], - &ServerName::try_from(data.dns_name.as_ref()).unwrap(), - &mut std::iter::empty(), - &[], - SystemTime::UNIX_EPOCH + Duration::from_secs(data.time), - ); - - assert!(matches!( - err.unwrap_err(), - tls_core::Error::InvalidCertificateData(_) - )); -} - -/// Expect to fail when no intermediate cert provided even if a trusted CA cert is provided -#[rstest] -#[case(tlsnotary())] -#[case(appliedzkp())] -fn test_verify_cert_chain_fail_no_interm_cert_with_ca_cert( - cert_verifier: impl ServerCertVerifier, - #[case] data: TestData, -) { - let err = cert_verifier.verify_server_cert( - &data.ee, - &[data.ca], - &ServerName::try_from(data.dns_name.as_ref()).unwrap(), - &mut std::iter::empty(), - &[], - SystemTime::UNIX_EPOCH + Duration::from_secs(data.time), - ); - - assert!(matches!( - err.unwrap_err(), - tls_core::Error::InvalidCertificateData(_) - )); -} - -/// Expect to fail because end-entity cert is wrong -#[rstest] -#[case(tlsnotary())] -#[case(appliedzkp())] -fn test_verify_cert_chain_fail_bad_ee_cert( - cert_verifier: impl ServerCertVerifier, - #[case] data: TestData, -) { - let ee: &[u8] = include_bytes!("testdata/key_exchange/unknown/ee.der"); - - let err = cert_verifier.verify_server_cert( - &Certificate(ee.to_vec()), - &[data.inter], - &ServerName::try_from(data.dns_name.as_ref()).unwrap(), - &mut std::iter::empty(), - &[], - SystemTime::UNIX_EPOCH + Duration::from_secs(data.time), - ); - - assert!(matches!( - err.unwrap_err(), - tls_core::Error::InvalidCertificateData(_) - )); -} - -/// Expect to succeed when key exchange params signed correctly with a cert -#[rstest] -#[case(tlsnotary())] -#[case(appliedzkp())] -fn test_verify_sig_ke_params_success( - cert_verifier: impl ServerCertVerifier, - #[case] data: TestData, -) { - assert!(cert_verifier - .verify_tls12_signature(&data.signature_msg(), &data.ee, &data.dss()) - .is_ok()); -} - -/// Expect sig verification to fail because client_random is wrong -#[rstest] -#[case(tlsnotary())] -#[case(appliedzkp())] -fn test_verify_sig_ke_params_fail_bad_client_random( - cert_verifier: impl ServerCertVerifier, - #[case] mut data: TestData, -) { - data.cr.0[31] = data.cr.0[31].wrapping_add(1); - - assert!(cert_verifier - .verify_tls12_signature(&data.signature_msg(), &data.ee, &data.dss()) - .is_err()); -} - -/// Expect sig verification to fail because the sig is wrong -#[rstest] -#[case(tlsnotary())] -#[case(appliedzkp())] -fn test_verify_sig_ke_params_fail_bad_sig( - cert_verifier: impl ServerCertVerifier, - #[case] mut data: TestData, -) { - data.sig[31] = data.sig[31].wrapping_add(1); - - assert!(cert_verifier - .verify_tls12_signature(&data.signature_msg(), &data.ee, &data.dss()) - .is_err()); -} - -/// Expect to fail because the dns name is not in the cert -#[rstest] -#[case(tlsnotary())] -#[case(appliedzkp())] -fn test_check_dns_name_present_in_cert_fail_bad_host( - cert_verifier: impl ServerCertVerifier, - #[case] data: TestData, -) { - let bad_name = ServerName::try_from("badhost.com").unwrap(); - - assert!(cert_verifier - .verify_server_cert( - &data.ee, - &[data.inter, data.ca], - &bad_name, - &mut std::iter::empty(), - &[], - SystemTime::UNIX_EPOCH + Duration::from_secs(data.time), - ) - .is_err()); -} - -/// Expect to fail because the host name is not a valid DNS name -#[rstest] -fn test_check_dns_name_present_in_cert_fail_invalid_dns_name() { - assert!(ServerName::try_from("tlsnotary.org%").is_err()); -} diff --git a/tlsn/tlsn-fixtures/src/lib.rs b/tlsn/tlsn-fixtures/src/lib.rs deleted file mode 100644 index 3f57743d5e..0000000000 --- a/tlsn/tlsn-fixtures/src/lib.rs +++ /dev/null @@ -1,2 +0,0 @@ -/// Certificate fixtures -pub mod cert;