docs: rustfmt wrap_comments (#611)

This commit is contained in:
sinu.eth
2024-10-01 07:18:51 -07:00
committed by GitHub
parent b76b8314ad
commit 17476bc2cf
63 changed files with 645 additions and 467 deletions

View File

@@ -29,8 +29,8 @@ static VERSION: Lazy<Version> = Lazy::new(|| {
pub struct ProtocolConfig {
/// Maximum number of bytes that can be sent.
max_sent_data: usize,
/// Maximum number of bytes that can be decrypted online, i.e. while the MPC-TLS connection is
/// active.
/// Maximum number of bytes that can be decrypted online, i.e. while the
/// MPC-TLS connection is active.
#[builder(default = "0")]
max_recv_data_online: usize,
/// Maximum number of bytes that can be received.
@@ -93,8 +93,8 @@ impl ProtocolConfig {
}
}
/// Protocol configuration validator used by checker (i.e. verifier) to perform compatibility check
/// with the peer's (i.e. the prover's) configuration.
/// Protocol configuration validator used by checker (i.e. verifier) to perform
/// compatibility check with the peer's (i.e. the prover's) configuration.
#[derive(derive_builder::Builder, Clone, Debug)]
pub struct ProtocolConfigValidator {
/// Maximum number of bytes that can be sent.
@@ -122,7 +122,8 @@ impl ProtocolConfigValidator {
self.max_recv_data
}
/// Performs compatibility check of the protocol configuration between prover and verifier.
/// Performs compatibility check of the protocol configuration between
/// prover and verifier.
pub fn validate(&self, config: &ProtocolConfig) -> Result<(), ProtocolConfigError> {
self.check_max_transcript_size(config.max_sent_data, config.max_recv_data)?;
self.check_version(&config.version)?;
@@ -152,7 +153,8 @@ impl ProtocolConfigValidator {
Ok(())
}
// Checks if both versions are the same (might support check for different but compatible versions in the future).
// Checks if both versions are the same (might support check for different but
// compatible versions in the future).
fn check_version(&self, peer_version: &Version) -> Result<(), ProtocolConfigError> {
if *peer_version != self.version {
return Err(ProtocolConfigError::version(format!(

View File

@@ -61,7 +61,8 @@ impl Future for MuxFuture {
/// Attaches a multiplexer to the provided socket.
///
/// Returns the multiplexer and a controller for creating streams with a codec attached.
/// Returns the multiplexer and a controller for creating streams with a codec
/// attached.
///
/// # Arguments
///

View File

@@ -59,8 +59,8 @@ async fn compute_tag_share<C: StreamCipher<Aes128Ctr> + ?Sized, H: UniversalHash
/// Computes the tag for a ciphertext and additional data.
///
/// The commit-reveal step is not required for computing a tag sent to the Server, as it
/// will be able to detect if the tag is incorrect.
/// The commit-reveal step is not required for computing a tag sent to the
/// Server, as it will be able to detect if the tag is incorrect.
#[instrument(level = "debug", skip_all, err)]
pub(crate) async fn compute_tag<
Ctx: Context,
@@ -89,9 +89,10 @@ pub(crate) async fn compute_tag<
/// Verifies a purported tag against the ciphertext and additional data.
///
/// Verifying a tag requires a commit-reveal protocol between the leader and follower.
/// Without it, the party which receives the other's tag share first could trivially compute
/// a tag share which would cause an invalid message to be accepted.
/// Verifying a tag requires a commit-reveal protocol between the leader and
/// follower. Without it, the party which receives the other's tag share first
/// could trivially compute a tag share which would cause an invalid message to
/// be accepted.
#[instrument(level = "debug", skip_all, err)]
#[allow(clippy::too_many_arguments)]
pub(crate) async fn verify_tag<

View File

@@ -1,12 +1,14 @@
//! This crate provides implementations of 2PC AEADs for authenticated encryption with
//! a shared key.
//! This crate provides implementations of 2PC AEADs for authenticated
//! encryption with a shared key.
//!
//! Both parties can work together to encrypt and decrypt messages with different visibility
//! configurations. See [`Aead`] for more information on the interface.
//! Both parties can work together to encrypt and decrypt messages with
//! different visibility configurations. See [`Aead`] for more information on
//! the interface.
//!
//! For example, one party can privately provide the plaintext to encrypt, while both parties
//! can see the ciphertext and the tag. Or, both parties can cooperate to decrypt a ciphertext
//! and verify the tag, while only one party can see the plaintext.
//! For example, one party can privately provide the plaintext to encrypt, while
//! both parties can see the ciphertext and the tag. Or, both parties can
//! cooperate to decrypt a ciphertext and verify the tag, while only one party
//! can see the plaintext.
#![deny(missing_docs, unreachable_pub, unused_must_use)]
#![deny(clippy::all)]
@@ -37,14 +39,15 @@ pub trait Aead: Send {
/// The AEAD assigns unique identifiers to each byte of plaintext
/// during encryption and decryption.
///
/// For example, if the transcript id is set to `foo`, then the first byte will
/// be assigned the id `foo/0`, the second byte `foo/1`, and so on.
/// For example, if the transcript id is set to `foo`, then the first byte
/// will be assigned the id `foo/0`, the second byte `foo/1`, and so on.
///
/// Each transcript id has an independent counter.
///
/// # Note
///
/// The state of a transcript counter is preserved between calls to `set_transcript_id`.
/// The state of a transcript counter is preserved between calls to
/// `set_transcript_id`.
fn set_transcript_id(&mut self, id: &str);
/// Performs any necessary one-time setup for the AEAD.
@@ -74,7 +77,8 @@ pub trait Aead: Send {
aad: Vec<u8>,
) -> Result<Vec<u8>, Self::Error>;
/// Encrypts a plaintext message, hiding it from the other party, returning the ciphertext and tag.
/// Encrypts a plaintext message, hiding it from the other party, returning
/// the ciphertext and tag.
///
/// # Arguments
///
@@ -105,7 +109,8 @@ pub trait Aead: Send {
/// Decrypts a ciphertext message, returning the plaintext to both parties.
///
/// This method checks the authenticity of the ciphertext, tag and additional data.
/// This method checks the authenticity of the ciphertext, tag and
/// additional data.
///
/// # Arguments
///
@@ -119,9 +124,11 @@ pub trait Aead: Send {
aad: Vec<u8>,
) -> Result<Vec<u8>, Self::Error>;
/// Decrypts a ciphertext message, returning the plaintext only to this party.
/// Decrypts a ciphertext message, returning the plaintext only to this
/// party.
///
/// This method checks the authenticity of the ciphertext, tag and additional data.
/// This method checks the authenticity of the ciphertext, tag and
/// additional data.
///
/// # Arguments
///
@@ -135,9 +142,11 @@ pub trait Aead: Send {
aad: Vec<u8>,
) -> Result<Vec<u8>, Self::Error>;
/// Decrypts a ciphertext message, returning the plaintext only to the other party.
/// Decrypts a ciphertext message, returning the plaintext only to the other
/// party.
///
/// This method checks the authenticity of the ciphertext, tag and additional data.
/// This method checks the authenticity of the ciphertext, tag and
/// additional data.
///
/// # Arguments
///
@@ -153,7 +162,8 @@ pub trait Aead: Send {
/// Verifies the tag of a ciphertext message.
///
/// This method checks the authenticity of the ciphertext, tag and additional data.
/// This method checks the authenticity of the ciphertext, tag and
/// additional data.
///
/// # Arguments
///
@@ -167,13 +177,13 @@ pub trait Aead: Send {
aad: Vec<u8>,
) -> Result<(), Self::Error>;
/// Locally decrypts the provided ciphertext and then proves in ZK to the other party(s) that the
/// plaintext is correct.
/// Locally decrypts the provided ciphertext and then proves in ZK to the
/// other party(s) that the plaintext is correct.
///
/// Returns the plaintext.
///
/// This method requires this party to know the encryption key, which can be achieved by calling
/// the `decode_key_private` method.
/// This method requires this party to know the encryption key, which can be
/// achieved by calling the `decode_key_private` method.
///
/// # Arguments
///
@@ -187,17 +197,18 @@ pub trait Aead: Send {
aad: Vec<u8>,
) -> Result<Vec<u8>, Self::Error>;
/// Locally decrypts the provided ciphertext and then proves in ZK to the other party(s) that the
/// plaintext is correct.
/// Locally decrypts the provided ciphertext and then proves in ZK to the
/// other party(s) that the plaintext is correct.
///
/// Returns the plaintext.
///
/// This method requires this party to know the encryption key, which can be achieved by calling
/// the `decode_key_private` method.
/// This method requires this party to know the encryption key, which can be
/// achieved by calling the `decode_key_private` method.
///
/// # WARNING
///
/// This method does not verify the tag of the ciphertext. Only use this if you know what you're doing.
/// This method does not verify the tag of the ciphertext. Only use this if
/// you know what you're doing.
///
/// # Arguments
///
@@ -209,7 +220,8 @@ pub trait Aead: Send {
ciphertext: Vec<u8>,
) -> Result<Vec<u8>, Self::Error>;
/// Verifies the other party(s) can prove they know a plaintext which encrypts to the given ciphertext.
/// Verifies the other party(s) can prove they know a plaintext which
/// encrypts to the given ciphertext.
///
/// # Arguments
///
@@ -223,11 +235,13 @@ pub trait Aead: Send {
aad: Vec<u8>,
) -> Result<(), Self::Error>;
/// Verifies the other party(s) can prove they know a plaintext which encrypts to the given ciphertext.
/// Verifies the other party(s) can prove they know a plaintext which
/// encrypts to the given ciphertext.
///
/// # WARNING
///
/// This method does not verify the tag of the ciphertext. Only use this if you know what you're doing.
/// This method does not verify the tag of the ciphertext. Only use this if
/// you know what you're doing.
///
/// # Arguments
///

View File

@@ -1,6 +1,7 @@
//! This crate provides a 2PC block cipher implementation.
//!
//! Both parties work together to encrypt or share an encrypted block using a shared key.
//! Both parties work together to encrypt or share an encrypted block using a
//! shared key.
#![deny(missing_docs, unreachable_pub, unused_must_use)]
#![deny(clippy::all)]

View File

@@ -80,7 +80,8 @@ pub fn hmac_sha256_partial(key: &[u8]) -> ([u32; 8], [u32; 8]) {
/// HMAC-SHA256 finalization function.
///
/// Returns the HMAC-SHA256 digest of the provided message using existing outer and inner states.
/// Returns the HMAC-SHA256 digest of the provided message using existing outer
/// and inner states.
///
/// # Arguments
///
@@ -103,7 +104,8 @@ pub fn hmac_sha256_finalize_trace<'a>(
/// Reference implementation of the HMAC-SHA256 finalization function.
///
/// Returns the HMAC-SHA256 digest of the provided message using existing outer and inner states.
/// Returns the HMAC-SHA256 digest of the provided message using existing outer
/// and inner states.
///
/// # Arguments
///

View File

@@ -10,7 +10,8 @@ use crate::prf::{prf, prf_trace};
/// Computes verify_data as specified in RFC 5246, Section 7.4.9.
///
/// verify_data
/// PRF(master_secret, finished_label, Hash(handshake_messages))[0..verify_data_length-1];
/// PRF(master_secret, finished_label,
/// Hash(handshake_messages))[0..verify_data_length-1];
///
/// # Arguments
///
@@ -31,7 +32,8 @@ pub fn verify_data_trace<'a>(
vd.try_into().expect("vd is 12 bytes")
}
/// Reference implementation of verify_data as specified in RFC 5246, Section 7.4.9.
/// Reference implementation of verify_data as specified in RFC 5246, Section
/// 7.4.9.
///
/// # Arguments
///

View File

@@ -56,7 +56,8 @@ impl State {
/// An MPC key exchange protocol.
///
/// Can be either a leader or a follower depending on the `role` field in [`KeyExchangeConfig`].
/// Can be either a leader or a follower depending on the `role` field in
/// [`KeyExchangeConfig`].
#[derive(Debug)]
pub struct MpcKeyExchange<Ctx, C0, C1, E> {
ctx: Ctx,
@@ -66,7 +67,8 @@ pub struct MpcKeyExchange<Ctx, C0, C1, E> {
converter_1: C1,
/// MPC executor.
executor: E,
/// The private key of the party behind this instance, either follower or leader.
/// The private key of the party behind this instance, either follower or
/// leader.
private_key: Option<SecretKey>,
/// The public key of the server.
server_key: Option<PublicKey>,
@@ -419,9 +421,9 @@ async fn compute_pms_shares<
) -> Result<(P256, P256), KeyExchangeError> {
// Compute the leader's/follower's share of the pre-master secret.
//
// We need to mimic the [diffie-hellman](p256::ecdh::diffie_hellman) function without the
// [SharedSecret](p256::ecdh::SharedSecret) wrapper, because this makes it harder to get
// the result as an EC curve point.
// We need to mimic the [diffie-hellman](p256::ecdh::diffie_hellman) function
// without the [SharedSecret](p256::ecdh::SharedSecret) wrapper, because
// this makes it harder to get the result as an EC curve point.
let shared_secret = {
let public_projective = server_key.to_projective();
(public_projective * private_key.to_nonzero_scalar().as_ref()).to_affine()

View File

@@ -1,9 +1,10 @@
//! # The Key Exchange Protocol
//!
//! This crate implements a key exchange protocol with 3 parties, namely server, leader and
//! follower. The goal is to end up with a shared secret (ECDH) between the server and the client.
//! The client in this context is leader and follower combined, which means that each of them will
//! end up with a share of the shared secret. The leader will do all the necessary communication
//! This crate implements a key exchange protocol with 3 parties, namely server,
//! leader and follower. The goal is to end up with a shared secret (ECDH)
//! between the server and the client. The client in this context is leader and
//! follower combined, which means that each of them will end up with a share of
//! the shared secret. The leader will do all the necessary communication
//! with the server alone and forward all messages from and to the follower.
//!
//! A detailed description of this protocol can be found in our documentation
@@ -58,8 +59,9 @@ pub trait KeyExchange {
/// Computes the client's public key.
///
/// The client's public key in this context is the combined public key (EC point addition) of
/// the leader's public key and the follower's public key.
/// The client's public key in this context is the combined public key (EC
/// point addition) of the leader's public key and the follower's public
/// key.
async fn client_key(&mut self) -> Result<PublicKey, KeyExchangeError>;
/// Performs any necessary one-time setup, returning a reference to the PMS.

View File

@@ -1,5 +1,5 @@
//! This module provides mock types for key exchange leader and follower and a function to create
//! such a pair.
//! This module provides mock types for key exchange leader and follower and a
//! function to create such a pair.
use crate::{KeyExchangeConfig, MpcKeyExchange, Role};

View File

@@ -1,6 +1,6 @@
//! This module implements a secure two-party computation protocol for adding two private EC points
//! and secret-sharing the resulting x coordinate (the shares are field elements of the field
//! underlying the elliptic curve).
//! This module implements a secure two-party computation protocol for adding
//! two private EC points and secret-sharing the resulting x coordinate (the
//! shares are field elements of the field underlying the elliptic curve).
//! This protocol has semi-honest security.
//!
//! The protocol is described in <https://docs.tlsnotary.org/protocol/notarization/key_exchange.html>

View File

@@ -191,10 +191,11 @@ impl<C: CtrCircuit> KeyStream<C> {
}
}
ExecutionMode::Prove => {
// Note that after the circuit execution, the value of `block` can be considered as
// implicitly authenticated since `key` and `iv` have already been authenticated earlier
// and `nonce_ref` and `ctr_ref` are public.
// [Prove::prove] will **not** be called on `block` at any later point.
// Note that after the circuit execution, the value of `block` can be considered
// as implicitly authenticated since `key` and `iv` have already
// been authenticated earlier and `nonce_ref` and `ctr_ref` are
// public. [Prove::prove] will **not** be called on `block` at
// any later point.
thread.commit_prove(&inputs).await?;
for (circ, inputs, outputs) in calls {
thread.execute_prove(circ, &inputs, &outputs).await?;

View File

@@ -1,16 +1,19 @@
//! This crate provides a 2PC stream cipher implementation using a block cipher in counter mode.
//! This crate provides a 2PC stream cipher implementation using a block cipher
//! in counter mode.
//!
//! Each party plays a specific role, either the `StreamCipherLeader` or the `StreamCipherFollower`.
//! Both parties work together to encrypt and decrypt messages using a shared key.
//! Each party plays a specific role, either the `StreamCipherLeader` or the
//! `StreamCipherFollower`. Both parties work together to encrypt and decrypt
//! messages using a shared key.
//!
//! # Transcript
//!
//! Using the `record` flag, the `StreamCipherFollower` can optionally use a dedicated stream when
//! encoding the plaintext labels, which allows the `StreamCipherLeader` to build a transcript of
//! active labels which are pushed to the provided `TranscriptSink`.
//! Using the `record` flag, the `StreamCipherFollower` can optionally use a
//! dedicated stream when encoding the plaintext labels, which allows the
//! `StreamCipherLeader` to build a transcript of active labels which are pushed
//! to the provided `TranscriptSink`.
//!
//! Afterwards, the `StreamCipherLeader` can create commitments to the transcript which can be used in
//! a selective disclosure protocol.
//! Afterwards, the `StreamCipherLeader` can create commitments to the
//! transcript which can be used in a selective disclosure protocol.
#![deny(missing_docs, unreachable_pub, unused_must_use)]
#![deny(clippy::all)]
@@ -43,7 +46,8 @@ where
/// Decodes the key for the stream cipher, revealing it to this party.
async fn decode_key_private(&mut self) -> Result<(), StreamCipherError>;
/// Decodes the key for the stream cipher, revealing it to the other party(s).
/// Decodes the key for the stream cipher, revealing it to the other
/// party(s).
async fn decode_key_blind(&mut self) -> Result<(), StreamCipherError>;
/// Sets the transcript id
@@ -51,14 +55,15 @@ where
/// The stream cipher assigns unique identifiers to each byte of plaintext
/// during encryption and decryption.
///
/// For example, if the transcript id is set to `foo`, then the first byte will
/// be assigned the id `foo/0`, the second byte `foo/1`, and so on.
/// For example, if the transcript id is set to `foo`, then the first byte
/// will be assigned the id `foo/0`, the second byte `foo/1`, and so on.
///
/// Each transcript id has an independent counter.
///
/// # Note
///
/// The state of a transcript counter is preserved between calls to `set_transcript_id`.
/// The state of a transcript counter is preserved between calls to
/// `set_transcript_id`.
fn set_transcript_id(&mut self, id: &str);
/// Preprocesses the keystream for the given number of bytes.
@@ -141,13 +146,13 @@ where
ciphertext: Vec<u8>,
) -> Result<(), StreamCipherError>;
/// Locally decrypts the provided ciphertext and then proves in ZK to the other party(s) that the
/// plaintext is correct.
/// Locally decrypts the provided ciphertext and then proves in ZK to the
/// other party(s) that the plaintext is correct.
///
/// Returns the plaintext.
///
/// This method requires this party to know the encryption key, which can be achieved by calling
/// the `decode_key_private` method.
/// This method requires this party to know the encryption key, which can be
/// achieved by calling the `decode_key_private` method.
///
/// # Arguments
///
@@ -159,7 +164,8 @@ where
ciphertext: Vec<u8>,
) -> Result<Vec<u8>, StreamCipherError>;
/// Verifies the other party(s) can prove they know a plaintext which encrypts to the given ciphertext.
/// Verifies the other party(s) can prove they know a plaintext which
/// encrypts to the given ciphertext.
///
/// # Arguments
///
@@ -171,7 +177,8 @@ where
ciphertext: Vec<u8>,
) -> Result<(), StreamCipherError>;
/// Returns an additive share of the keystream block for the given explicit nonce and counter.
/// Returns an additive share of the keystream block for the given explicit
/// nonce and counter.
///
/// # Arguments
///

View File

@@ -57,8 +57,8 @@ struct KeyAndIv {
/// A subset of plaintext bytes processed by the stream cipher.
///
/// Note that `Transcript` does not store the actual bytes. Instead, it provides IDs which are
/// assigned to plaintext bytes of the stream cipher.
/// Note that `Transcript` does not store the actual bytes. Instead, it provides
/// IDs which are assigned to plaintext bytes of the stream cipher.
struct Transcript {
/// The ID of this transcript.
id: String,
@@ -74,7 +74,8 @@ impl Transcript {
}
}
/// Returns unique identifiers for the next plaintext bytes in the transcript.
/// Returns unique identifiers for the next plaintext bytes in the
/// transcript.
fn extend_plaintext(&mut self, len: usize) -> Vec<String> {
(0..len)
.map(|_| self.plaintext.increment_in_place().to_string())

View File

@@ -24,8 +24,8 @@ impl GhashCore {
///
/// # Arguments
///
/// * `max_block_count` - Determines the maximum number of 128-bit message blocks we want to
/// authenticate. Panics if `max_block_count` is 0.
/// * `max_block_count` - Determines the maximum number of 128-bit message
/// blocks we want to authenticate. Panics if `max_block_count` is 0.
pub(crate) fn new(max_block_count: usize) -> Self {
assert!(max_block_count > 0);
@@ -35,10 +35,11 @@ impl GhashCore {
}
}
/// Transforms `self` into a `GhashCore<Intermediate>`, holding multiplicative shares of
/// powers of `H`.
/// Transforms `self` into a `GhashCore<Intermediate>`, holding
/// multiplicative shares of powers of `H`.
///
/// Converts `H` into `H`, `H^3`, `H^5`, ... depending on `self.max_block_count`.
/// Converts `H` into `H`, `H^3`, `H^5`, ... depending on
/// `self.max_block_count`.
#[instrument(level = "trace", skip_all)]
pub(crate) fn compute_odd_mul_powers(self, mul_share: Gf2_128) -> GhashCore<Intermediate> {
let mut hashkey_powers = vec![mul_share];
@@ -63,17 +64,17 @@ impl GhashCore<Intermediate> {
/// exists, are not returned.
#[instrument(level = "trace", skip_all)]
pub(crate) fn odd_mul_shares(&self) -> Vec<Gf2_128> {
// If we already have some cached additive sharings, we do not need to compute new powers.
// So we compute an offset to ignore them. We divide by 2 because
// `self.state.cached_add_shares` contain even and odd powers, while
// `self.state.odd_mul_shares` only have odd powers.
// If we already have some cached additive sharings, we do not need to compute
// new powers. So we compute an offset to ignore them. We divide by 2
// because `self.state.cached_add_shares` contain even and odd powers,
// while `self.state.odd_mul_shares` only have odd powers.
let offset = self.state.cached_add_shares.len() / 2;
self.state.odd_mul_shares[offset..].to_vec()
}
/// Adds new additive shares of hashkey powers by also computing the even ones
/// and transforms `self` into a `GhashCore<Finalized>`.
/// Adds new additive shares of hashkey powers by also computing the even
/// ones and transforms `self` into a `GhashCore<Finalized>`.
#[instrument(level = "trace", skip_all)]
pub(crate) fn add_new_add_shares(
mut self,
@@ -120,8 +121,9 @@ impl GhashCore<Finalized> {
/// Changes the maximum hashkey power.
///
/// If we want to create a GHASH output for a new message, which is longer than the old one, we need
/// to compute the missing shares of the powers of `H`.
/// If we want to create a GHASH output for a new message, which is longer
/// than the old one, we need to compute the missing shares of the
/// powers of `H`.
#[instrument(level = "debug", skip(self))]
pub(crate) fn change_max_hashkey(
self,

View File

@@ -1,19 +1,21 @@
//! This module implements the AES-GCM's GHASH function in a secure two-party computation (2PC)
//! setting. The parties start with their secret XOR shares of H (the GHASH key) and at the end
//! each gets their XOR share of the GHASH output. The method is described here:
//! <https://tlsnotary.org/how_it_works#section4>.
//! This module implements the AES-GCM's GHASH function in a secure two-party
//! computation (2PC) setting. The parties start with their secret XOR shares of
//! H (the GHASH key) and at the end each gets their XOR share of the GHASH
//! output. The method is described here: <https://tlsnotary.org/how_it_works#section4>.
//!
//! At first we will convert the XOR (additive) share of `H`, into a multiplicative share. This
//! allows us to compute all the necessary powers of `H^n` locally. Note, that it is only required
//! to compute the odd multiplicative powers, because of free squaring. Then each of these
//! multiplicative shares will be converted back into additive shares. The even additive shares can
//! then locally be built by using the odd ones. This way, we can batch nearly all oblivious
//! transfers and reduce the round complexity of the protocol.
//! At first we will convert the XOR (additive) share of `H`, into a
//! multiplicative share. This allows us to compute all the necessary powers of
//! `H^n` locally. Note, that it is only required to compute the odd
//! multiplicative powers, because of free squaring. Then each of these
//! multiplicative shares will be converted back into additive shares. The even
//! additive shares can then locally be built by using the odd ones. This way,
//! we can batch nearly all oblivious transfers and reduce the round complexity
//! of the protocol.
//!
//! On the whole, we need a single additive-to-multiplicative (A2M) and `n/2`, where `n` is the
//! number of blocks of message, multiplicative-to-additive (M2A) conversions. Finally, having
//! additive shares of `H^n` for all needed `n`, we can compute an additive share of the GHASH
//! output.
//! On the whole, we need a single additive-to-multiplicative (A2M) and `n/2`,
//! where `n` is the number of blocks of message, multiplicative-to-additive
//! (M2A) conversions. Finally, having additive shares of `H^n` for all needed
//! `n`, we can compute an additive share of the GHASH output.
/// Contains the core logic for ghash.
mod core;
@@ -35,14 +37,16 @@ pub(crate) enum GhashError {
/// Computes missing odd multiplicative shares of the hashkey powers.
///
/// Checks if depending on the number of `needed` shares, we need more odd multiplicative shares and
/// computes them. Notice that we only need odd multiplicative shares for the OT, because we can
/// derive even additive shares from odd additive shares, which we call free squaring.
/// Checks if depending on the number of `needed` shares, we need more odd
/// multiplicative shares and computes them. Notice that we only need odd
/// multiplicative shares for the OT, because we can derive even additive shares
/// from odd additive shares, which we call free squaring.
///
/// # Arguments
///
/// * `present_odd_mul_shares` - Multiplicative odd shares already present.
/// * `needed` - How many powers we need including odd and even.
/// * `needed` - How many powers we need including odd and
/// even.
#[instrument(level = "trace", skip(present_odd_mul_shares))]
fn compute_missing_mul_shares(present_odd_mul_shares: &mut Vec<Gf2_128>, needed: usize) {
// Divide by 2 and round up.
@@ -59,33 +63,35 @@ fn compute_missing_mul_shares(present_odd_mul_shares: &mut Vec<Gf2_128>, needed:
}
}
/// Computes new even (additive) shares from new odd (additive) shares and saves both the new odd shares
/// and the new even shares.
/// Computes new even (additive) shares from new odd (additive) shares and saves
/// both the new odd shares and the new even shares.
///
/// This function implements the derivation of even additive shares from odd additive shares,
/// which we refer to as free squaring. Every additive share of an even power of
/// `H` can be computed without an OT interaction by squaring the corresponding additive share
/// of an odd power of `H`, e.g. if we have a share of H^3, we can derive the share of H^6 by doing
/// (H^3)^2.
/// This function implements the derivation of even additive shares from odd
/// additive shares, which we refer to as free squaring. Every additive share of
/// an even power of `H` can be computed without an OT interaction by squaring
/// the corresponding additive share of an odd power of `H`, e.g. if we have a
/// share of H^3, we can derive the share of H^6 by doing (H^3)^2.
///
/// # Arguments
///
/// * `new_add_odd_shares` - New odd additive shares we got as a result of doing an OT on odd
/// multiplicative shares.
/// * `add_shares` - All additive shares (even and odd) we already have. This is a mutable
/// reference to cached_add_shares in [crate::ghash::state::Intermediate].
/// * `new_add_odd_shares` - New odd additive shares we got as a result of doing
/// an OT on odd multiplicative shares.
/// * `add_shares` - All additive shares (even and odd) we already have.
/// This is a mutable reference to cached_add_shares in
/// [crate::ghash::state::Intermediate].
#[instrument(level = "trace", skip_all)]
fn compute_new_add_shares(new_add_odd_shares: &[Gf2_128], add_shares: &mut Vec<Gf2_128>) {
for (odd_share, current_odd_power) in new_add_odd_shares
.iter()
.zip((add_shares.len() + 1..).step_by(2))
{
// `add_shares` always have an even number of shares so we simply add the next odd share.
// `add_shares` always have an even number of shares so we simply add the next
// odd share.
add_shares.push(*odd_share);
// Now we need to compute the next even share and add it.
// Note that the n-th index corresponds to the (n+1)-th power, e.g. add_shares[4]
// is the share of H^5.
// Note that the n-th index corresponds to the (n+1)-th power, e.g.
// add_shares[4] is the share of H^5.
let mut base_share = add_shares[current_odd_power / 2];
base_share = base_share * base_share;
add_shares.push(base_share);

View File

@@ -24,8 +24,8 @@ opaque_debug::implement!(Init);
/// Intermediate state for Ghash protocol.
///
/// This is when the additive share has been converted into a multiplicative share and all the
/// needed powers have been computed.
/// This is when the additive share has been converted into a multiplicative
/// share and all the needed powers have been computed.
#[derive(Clone)]
pub(crate) struct Intermediate {
pub(super) odd_mul_shares: Vec<Gf2_128>,
@@ -41,8 +41,8 @@ opaque_debug::implement!(Intermediate);
/// Final state for Ghash protocol.
///
/// This is when each party can compute a final share of the ghash output, because both now have
/// additive shares of all the powers of `H`.
/// This is when each party can compute a final share of the ghash output,
/// because both now have additive shares of all the powers of `H`.
#[derive(Clone)]
pub(crate) struct Finalized {
pub(super) odd_mul_shares: Vec<Gf2_128>,

View File

@@ -46,8 +46,8 @@ where
/// # Arguments
///
/// * `config` - The configuration for this Ghash instance.
/// * `converter` - An instance which allows to convert multiplicative into additive shares
/// and vice versa.
/// * `converter` - An instance which allows to convert multiplicative
/// into additive shares and vice versa.
/// * `context` - The context.
pub fn new(config: GhashConfig, converter: C, context: Ctx) -> Self {
Self {
@@ -128,9 +128,9 @@ where
#[instrument(level = "debug", fields(thread = %self.context.id()), skip_all, err)]
async fn setup(&mut self) -> Result<(), UniversalHashError> {
// We need only half the number of `max_block_count` M2As because of the free squaring trick
// and we need one extra A2M conversion in the beginning. Both M2A and A2M, each require a single
// OLE.
// We need only half the number of `max_block_count` M2As because of the free
// squaring trick and we need one extra A2M conversion in the beginning.
// Both M2A and A2M, each require a single OLE.
let ole_count = self.config.max_block_count / 2 + 1;
self.converter.alloc(ole_count);

View File

@@ -1,12 +1,13 @@
//! Attestation types.
//!
//! An attestation is a cryptographically signed document from a Notary who witnessed a TLS
//! connection. It contains various fields which can be used to verify statements about the
//! connection and the associated application data.
//! An attestation is a cryptographically signed document from a Notary who
//! witnessed a TLS connection. It contains various fields which can be used to
//! verify statements about the connection and the associated application data.
//!
//! Attestations contain a header and a body. The header is signed by a Notary and it contains
//! a merkle root of the body fields. This allows a Prover to disclose only necessary fields
//! to a Verifier depending on the statements being made.
//! Attestations contain a header and a body. The header is signed by a Notary
//! and it contains a merkle root of the body fields. This allows a Prover to
//! disclose only necessary fields to a Verifier depending on the statements
//! being made.
mod builder;
mod config;
@@ -122,10 +123,10 @@ impl_domain_separator!(Header);
/// Attestation body.
///
/// An attestation contains a set of fields which are cryptographically signed by
/// a Notary via a [`Header`]. These fields include data which can be
/// used to verify aspects of a TLS connection, such as the server's identity, and facts
/// about the transcript.
/// An attestation contains a set of fields which are cryptographically signed
/// by a Notary via a [`Header`]. These fields include data which can be
/// used to verify aspects of a TLS connection, such as the server's identity,
/// and facts about the transcript.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Body {
verifying_key: Field<VerifyingKey>,
@@ -158,14 +159,16 @@ impl Body {
/// Returns the fields of the body hashed and sorted by id.
///
/// Each field is hashed with a domain separator to mitigate type confusion attacks.
/// Each field is hashed with a domain separator to mitigate type confusion
/// attacks.
///
/// # Note
///
/// The order of fields is not stable across versions.
pub(crate) fn hash_fields(&self, hasher: &dyn HashAlgorithm) -> Vec<(FieldId, Hash)> {
// CRITICAL: ensure all fields are included! If a new field is added to the struct
// without including it here it will not be verified to be included in the attestation.
// CRITICAL: ensure all fields are included! If a new field is added to the
// struct without including it here it will not be verified to be
// included in the attestation.
let Self {
verifying_key,
connection_info: conn_info,

View File

@@ -2,20 +2,22 @@
//!
//! ## Commitment
//!
//! During the TLS handshake the Notary receives the Server's ephemeral public key, and this key
//! serves as a binding commitment to the identity of the Server. The ephemeral key itself does not
//! reveal the Server's identity, but it is bound to it via a signature created using the Server's
//! During the TLS handshake the Notary receives the Server's ephemeral public
//! key, and this key serves as a binding commitment to the identity of the
//! Server. The ephemeral key itself does not reveal the Server's identity, but
//! it is bound to it via a signature created using the Server's
//! X.509 certificate.
//!
//! A Prover can withhold the Server's signature and certificate chain from the Notary to
//! improve privacy and censorship resistance.
//! A Prover can withhold the Server's signature and certificate chain from the
//! Notary to improve privacy and censorship resistance.
//!
//! ## Proving the Server's identity
//!
//! A Prover can prove the Server's identity to a Verifier by sending a [`ServerIdentityProof`]. This
//! proof contains all the information required to establish the link between the TLS connection
//! and the Server's X.509 certificate. A Verifier checks the Server's certificate against their own trust
//! anchors, the same way a typical TLS client would.
//! A Prover can prove the Server's identity to a Verifier by sending a
//! [`ServerIdentityProof`]. This proof contains all the information required to
//! establish the link between the TLS connection and the Server's X.509
//! certificate. A Verifier checks the Server's certificate against their own
//! trust anchors, the same way a typical TLS client would.
mod commit;
mod proof;

View File

@@ -47,8 +47,8 @@ impl HashProvider {
self.algs.insert(id, algorithm);
}
/// Returns the hash algorithm with the given identifier, or an error if the hash algorithm
/// does not exist.
/// Returns the hash algorithm with the given identifier, or an error if the
/// hash algorithm does not exist.
pub fn get(
&self,
id: &HashAlgId,
@@ -293,7 +293,8 @@ impl<T> Blinded<T> {
}
}
/// A type with a domain separator which is used during hashing to mitigate type confusion attacks.
/// A type with a domain separator which is used during hashing to mitigate type
/// confusion attacks.
pub(crate) trait DomainSeparator {
/// Returns the domain separator for the type.
fn domain(&self) -> &[u8];

View File

@@ -26,7 +26,8 @@ pub(crate) struct MerkleProof {
opaque_debug::implement!(MerkleProof);
impl MerkleProof {
/// Checks if indices, hashes and leaves count are valid for the provided root
/// Checks if indices, hashes and leaves count are valid for the provided
/// root
///
/// # Panics
///
@@ -103,7 +104,8 @@ impl MerkleTree {
///
/// # Panics
///
/// - If the provided hasher is not the same as the one used to create the tree.
/// - If the provided hasher is not the same as the one used to create the
/// tree.
pub(crate) fn insert(&mut self, hasher: &dyn HashAlgorithm, mut leaves: Vec<Hash>) {
assert_eq!(self.alg, hasher.id(), "hash algorithm mismatch");

View File

@@ -12,13 +12,16 @@ use crate::{
///
/// ## Custom Algorithms
///
/// This is the primary interface for extending cryptographic functionality. The various
/// providers can be configured with custom algorithms and implementations.
/// This is the primary interface for extending cryptographic functionality. The
/// various providers can be configured with custom algorithms and
/// implementations.
///
/// Algorithms are uniquely identified using an 8-bit ID, eg. [`HashAlgId`](crate::hash::HashAlgId),
/// half of which is reserved for the officially supported algorithms. If you think that a new
/// algorithm should be added to the official set, please open an issue. Beware that other parties
/// may assign different algorithms to the same ID as you, and we make no effort to mitigate this.
/// Algorithms are uniquely identified using an 8-bit ID, eg.
/// [`HashAlgId`](crate::hash::HashAlgId), half of which is reserved for the
/// officially supported algorithms. If you think that a new algorithm should be
/// added to the official set, please open an issue. Beware that other parties
/// may assign different algorithms to the same ID as you, and we make no effort
/// to mitigate this.
pub struct CryptoProvider {
/// Hash provider.
pub hash: HashProvider,

View File

@@ -1,14 +1,17 @@
//! Attestation requests.
//!
//! After the TLS connection, a Prover can request an attestation from the Notary which contains
//! various information about the connection. During this process the Prover has the opportunity
//! to configure certain aspects of the attestation, such as which signature algorithm the Notary
//! should use to sign the attestation. Or which hash algorithm the Notary should use to merkelize
//! After the TLS connection, a Prover can request an attestation from the
//! Notary which contains various information about the connection. During this
//! process the Prover has the opportunity to configure certain aspects of the
//! attestation, such as which signature algorithm the Notary should use to sign
//! the attestation. Or which hash algorithm the Notary should use to merkelize
//! the fields.
//!
//! A [`Request`] can be created using a [`RequestBuilder`]. The builder will take both configuration
//! via a [`RequestConfig`] as well as the Prover's secret data. The [`Secrets`](crate::Secrets) are of
//! course not shared with the Notary but are used to create commitments which are included in the attestation.
//! A [`Request`] can be created using a [`RequestBuilder`]. The builder will
//! take both configuration via a [`RequestConfig`] as well as the Prover's
//! secret data. The [`Secrets`](crate::Secrets) are of course not shared with
//! the Notary but are used to create commitments which are included in the
//! attestation.
mod builder;
mod config;

View File

@@ -1,26 +1,32 @@
//! Transcript types.
//!
//! All application data communicated over a TLS connection is referred to as a [`Transcript`]. A transcript is essentially
//! just two vectors of bytes, each corresponding to a [`Direction`].
//! All application data communicated over a TLS connection is referred to as a
//! [`Transcript`]. A transcript is essentially just two vectors of bytes, each
//! corresponding to a [`Direction`].
//!
//! TLS operates over a bidirectional byte stream, and thus there are no application layer semantics present in the transcript.
//! For example, HTTPS is an application layer protocol that runs *over TLS* so there is no concept of "requests" or "responses"
//! in the transcript itself. These semantics must be recovered by parsing the application data and relating it to the bytes
//! TLS operates over a bidirectional byte stream, and thus there are no
//! application layer semantics present in the transcript. For example, HTTPS is
//! an application layer protocol that runs *over TLS* so there is no concept of
//! "requests" or "responses" in the transcript itself. These semantics must be
//! recovered by parsing the application data and relating it to the bytes
//! in the transcript.
//!
//! ## Commitments
//!
//! During the attestation process a Prover can generate multiple commitments to various parts of the transcript.
//! These commitments are inserted into the attestation body and can be used by the Verifier to verify transcript proofs
//! During the attestation process a Prover can generate multiple commitments to
//! various parts of the transcript. These commitments are inserted into the
//! attestation body and can be used by the Verifier to verify transcript proofs
//! later.
//!
//! To configure the transcript commitments, use the [`TranscriptCommitConfigBuilder`].
//! To configure the transcript commitments, use the
//! [`TranscriptCommitConfigBuilder`].
//!
//! ## Selective Disclosure
//!
//! Using a [`TranscriptProof`] a Prover can selectively disclose parts of a transcript to a Verifier
//! in the form of a [`PartialTranscript`]. A Verifier always learns the length of the transcript, but sensitive
//! data can be withheld.
//! Using a [`TranscriptProof`] a Prover can selectively disclose parts of a
//! transcript to a Verifier in the form of a [`PartialTranscript`]. A Verifier
//! always learns the length of the transcript, but sensitive data can be
//! withheld.
//!
//! To create a proof, use the [`TranscriptProofBuilder`] which is returned by
//! [`Secrets::transcript_proof_builder`](crate::Secrets::transcript_proof_builder).
@@ -103,8 +109,8 @@ impl Transcript {
}
}
/// Returns the subsequence of the transcript with the provided index, returning `None`
/// if the index is out of bounds.
/// Returns the subsequence of the transcript with the provided index,
/// returning `None` if the index is out of bounds.
pub fn get(&self, direction: Direction, idx: &Idx) -> Option<Subsequence> {
let data = match direction {
Direction::Sent => &self.sent,
@@ -154,7 +160,8 @@ impl Transcript {
/// A partial transcript.
///
/// A partial transcript is a transcript which may not have all the data authenticated.
/// A partial transcript is a transcript which may not have all the data
/// authenticated.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(try_from = "validation::PartialTranscriptUnchecked")]
pub struct PartialTranscript {
@@ -213,7 +220,8 @@ impl PartialTranscript {
/// # Warning
///
/// Not all of the data in the transcript may have been authenticated. See
/// [sent_authed](PartialTranscript::sent_authed) for a set of ranges which have been.
/// [sent_authed](PartialTranscript::sent_authed) for a set of ranges which
/// have been.
pub fn sent_unsafe(&self) -> &[u8] {
&self.sent
}
@@ -223,7 +231,8 @@ impl PartialTranscript {
/// # Warning
///
/// Not all of the data in the transcript may have been authenticated. See
/// [received_authed](PartialTranscript::received_authed) for a set of ranges which have been.
/// [received_authed](PartialTranscript::received_authed) for a set of
/// ranges which have been.
pub fn received_unsafe(&self) -> &[u8] {
&self.received
}
@@ -329,7 +338,8 @@ impl PartialTranscript {
}
}
/// Sets all bytes in the transcript which haven't been authenticated within the given range.
/// Sets all bytes in the transcript which haven't been authenticated within
/// the given range.
///
/// # Arguments
///
@@ -353,8 +363,8 @@ impl PartialTranscript {
/// The direction of data communicated over a TLS connection.
///
/// This is used to differentiate between data sent from the Prover to the TLS peer,
/// and data received by the Prover from the TLS peer (client or server).
/// This is used to differentiate between data sent from the Prover to the TLS
/// peer, and data received by the Prover from the TLS peer (client or server).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Direction {
/// Sent from the Prover to the TLS peer.

View File

@@ -1,6 +1,7 @@
//! Transcript encoding commitments and proofs.
//!
//! This is an internal module that is not intended to be used directly by users.
//! This is an internal module that is not intended to be used directly by
//! users.
mod encoder;
mod proof;
@@ -16,11 +17,13 @@ use serde::{Deserialize, Serialize};
use crate::hash::{impl_domain_separator, TypedHash};
/// 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]).
/// 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]).
///
/// This value must not exceed bcs's MAX_SEQUENCE_LENGTH limit (which is (1 << 31) - 1 by default)
/// 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;
/// Transcript encoding commitment.

View File

@@ -169,7 +169,8 @@ impl<'a> TranscriptProofBuilder<'a> {
self
}
/// Reveals the given ranges in the transcript using the provided kind of commitment.
/// Reveals the given ranges in the transcript using the provided kind of
/// commitment.
///
/// # Arguments
///
@@ -252,7 +253,8 @@ impl<'a> TranscriptProofBuilder<'a> {
Ok(self)
}
/// Reveals the given ranges in the transcript using the default kind of commitment.
/// Reveals the given ranges in the transcript using the default kind of
/// commitment.
///
/// # Arguments
///

View File

@@ -1,5 +1,6 @@
// Runs a simple Prover which connects to the Notary and notarizes a request/response from
// example.com. The Prover then generates a proof and writes it to disk.
// Runs a simple Prover which connects to the Notary and notarizes a
// request/response from example.com. The Prover then generates a proof and
// writes it to disk.
use http_body_util::Empty;
use hyper::{body::Bytes, Request, StatusCode};
@@ -56,8 +57,9 @@ async fn main() {
.unwrap();
// Bind the Prover to the server connection.
// The returned `mpc_tls_connection` is an MPC TLS connection to the Server: all data written
// to/read from it will be encrypted/decrypted using MPC with the Notary.
// The returned `mpc_tls_connection` is an MPC TLS connection to the Server: all
// data written to/read from it will be encrypted/decrypted using MPC with
// the Notary.
let (mpc_tls_connection, prover_fut) = prover.connect(client_socket.compat()).await.unwrap();
let mpc_tls_connection = TokioIo::new(mpc_tls_connection.compat());
@@ -178,7 +180,8 @@ async fn build_proof_without_redactions(mut prover: Prover<Notarize>) -> TlsProo
}
async fn build_proof_with_redactions(mut prover: Prover<Notarize>) -> TlsProof {
// Identify the ranges in the outbound data which contain data which we want to disclose
// Identify the ranges in the outbound data which contain data which we want to
// disclose
let (sent_public_ranges, _) = find_ranges(
prover.sent_transcript().data(),
&[
@@ -187,7 +190,8 @@ async fn build_proof_with_redactions(mut prover: Prover<Notarize>) -> TlsProof {
],
);
// Identify the ranges in the inbound data which contain data which we want to disclose
// Identify the ranges in the inbound data which contain data which we want to
// disclose
let (recv_public_ranges, _) = find_ranges(
prover.recv_transcript().data(),
&[

View File

@@ -4,8 +4,8 @@ use elliptic_curve::pkcs8::DecodePublicKey;
use tlsn_core::proof::{SessionProof, TlsProof};
/// A simple verifier which reads a proof generated by `simple_prover.rs` from "proof.json", verifies
/// it and prints the verified data to the console.
/// A simple verifier which reads a proof generated by `simple_prover.rs` from
/// "proof.json", verifies it and prints the verified data to the console.
fn main() {
// Deserialize the proof
let proof = std::fs::read_to_string("simple_proof.json").unwrap();
@@ -22,14 +22,15 @@ fn main() {
// Verify the session proof against the Notary's public key
//
// This verifies the identity of the server using a default certificate verifier which trusts
// the root certificates from the `webpki-roots` crate.
// This verifies the identity of the server using a default certificate verifier
// which trusts the root certificates from the `webpki-roots` crate.
session
.verify_with_default_cert_verifier(notary_pubkey())
.unwrap();
let SessionProof {
// The session header that was signed by the Notary is a succinct commitment to the TLS transcript.
// The session header that was signed by the Notary is a succinct commitment to the TLS
// transcript.
header,
// This is the session_info, which contains the server_name, that is checked against the
// certificate chain shared in the TLS handshake.

View File

@@ -17,7 +17,8 @@ use tracing::debug;
// Setting of the application server
const SERVER_DOMAIN: &str = "discord.com";
// Setting of the notary server — make sure these are the same with the config in ../../notary/server
// Setting of the notary server — make sure these are the same with the config
// in ../../notary/server
const NOTARY_HOST: &str = "127.0.0.1";
const NOTARY_PORT: u16 = 7047;
@@ -69,7 +70,8 @@ async fn main() {
.build()
.unwrap();
// Configure a new prover with the unique session id returned from notary client.
// Configure a new prover with the unique session id returned from notary
// client.
let prover_config = ProverConfig::builder()
.id(session_id)
.server_name(SERVER_DOMAIN)
@@ -155,7 +157,8 @@ async fn main() {
.map(|range| builder.commit_sent(range).unwrap())
.collect::<Vec<_>>();
// Commit to the full received transcript in one shot, as we don't need to redact anything
// Commit to the full received transcript in one shot, as we don't need to
// redact anything
commitment_ids.push(builder.commit_recv(&(0..recv_len)).unwrap());
// Finalize, returning the notarized session

View File

@@ -4,8 +4,9 @@ use elliptic_curve::pkcs8::DecodePublicKey;
use tlsn_core::proof::{SessionProof, TlsProof};
/// A simple verifier which reads a proof generated by `discord_dm.rs` from "discord_dm_proof.json", verifies
/// it and prints the verified data to the console.
/// A simple verifier which reads a proof generated by `discord_dm.rs` from
/// "discord_dm_proof.json", verifies it and prints the verified data to the
/// console.
fn main() {
// Deserialize the proof
let proof = std::fs::read_to_string("discord_dm_proof.json").unwrap();
@@ -22,14 +23,15 @@ fn main() {
// Verify the session proof against the Notary's public key
//
// This verifies the identity of the server using a default certificate verifier which trusts
// the root certificates from the `webpki-roots` crate.
// This verifies the identity of the server using a default certificate verifier
// which trusts the root certificates from the `webpki-roots` crate.
session
.verify_with_default_cert_verifier(notary_pubkey())
.unwrap();
let SessionProof {
// The session header that was signed by the Notary is a succinct commitment to the TLS transcript.
// The session header that was signed by the Notary is a succinct commitment to the TLS
// transcript.
header,
// This is the session_info, which contains the server_name, that is checked against the
// certificate chain shared in the TLS handshake.

View File

@@ -80,7 +80,8 @@ impl HttpCommitError {
pub trait HttpCommit {
/// Commits to an HTTP transcript.
///
/// The default implementation commits to each request and response in the transcript separately.
/// The default implementation commits to each request and response in the
/// transcript separately.
///
/// # Arguments
///
@@ -104,8 +105,9 @@ pub trait HttpCommit {
/// Commits to a request.
///
/// The default implementation commits to the request excluding the target, headers and body. Additionally,
/// it commits to the target, headers and body separately.
/// The default implementation commits to the request excluding the target,
/// headers and body. Additionally, it commits to the target, headers
/// and body separately.
///
/// # Arguments
///
@@ -181,7 +183,8 @@ pub trait HttpCommit {
/// Commits to a request header.
///
/// The default implementation commits to the entire header, and the header excluding the value.
/// The default implementation commits to the entire header, and the header
/// excluding the value.
///
/// # Arguments
///
@@ -224,9 +227,9 @@ pub trait HttpCommit {
/// Commits to a request body.
///
/// The default implementation commits using the default implementation for the
/// format type of the body. If the format of the body is unknown, it commits to the
/// body as a whole.
/// The default implementation commits using the default implementation for
/// the format type of the body. If the format of the body is unknown,
/// it commits to the body as a whole.
///
/// # Arguments
///
@@ -269,8 +272,9 @@ pub trait HttpCommit {
/// Commits to a response.
///
/// The default implementation commits to the response excluding the headers and body. Additionally,
/// it commits to the headers and body separately.
/// The default implementation commits to the response excluding the headers
/// and body. Additionally, it commits to the headers and body
/// separately.
///
/// # Arguments
///
@@ -316,7 +320,8 @@ pub trait HttpCommit {
/// Commits to a response header.
///
/// The default implementation commits to the entire header, and the header excluding the value.
/// The default implementation commits to the entire header, and the header
/// excluding the value.
///
/// # Arguments
///
@@ -359,9 +364,9 @@ pub trait HttpCommit {
/// Commits to a response body.
///
/// The default implementation commits using the default implementation for the
/// format type of the body. If the format of the body is unknown, it commits to the
/// body as a whole.
/// The default implementation commits using the default implementation for
/// the format type of the body. If the format of the body is unknown,
/// it commits to the body as a whole.
///
/// # Arguments
///

View File

@@ -76,8 +76,8 @@ pub trait JsonCommit {
/// Commits to a JSON object.
///
/// The default implementation commits the object without any of the key-value pairs, then
/// commits each key-value pair individually.
/// The default implementation commits the object without any of the
/// key-value pairs, then commits each key-value pair individually.
///
/// # Arguments
///
@@ -103,8 +103,8 @@ pub trait JsonCommit {
/// Commits to a JSON key-value pair.
///
/// The default implementation commits the pair without the value, and then commits the value
/// separately.
/// The default implementation commits the pair without the value, and then
/// commits the value separately.
///
/// # Arguments
///
@@ -131,8 +131,8 @@ pub trait JsonCommit {
/// Commits to a JSON array.
///
/// The default implementation commits to the entire array, then commits the array
/// excluding all values and separators.
/// The default implementation commits to the entire array, then commits the
/// array excluding all values and separators.
///
/// # Arguments
///

View File

@@ -2,10 +2,11 @@
//!
//! # Warning
//!
//! This library is not yet ready for production use, and should *NOT* be considered secure.
//! This library is not yet ready for production use, and should *NOT* be
//! considered secure.
//!
//! At present, this library does not verify that redacted data does not contain control characters which can
//! be used by a malicious prover to cheat.
//! At present, this library does not verify that redacted data does not contain
//! control characters which can be used by a malicious prover to cheat.
#![deny(missing_docs, unreachable_pub, unused_must_use)]
#![deny(clippy::all)]

View File

@@ -1,6 +1,7 @@
//! Notary client.
//!
//! This module sets up connection to notary server via TCP or TLS for subsequent requests for notarization.
//! This module sets up connection to notary server via TCP or TLS for
//! subsequent requests for notarization.
use http_body_util::{BodyExt as _, Either, Empty, Full};
use hyper::{body::Bytes, client::conn::http1::Parts, Request, StatusCode};
@@ -107,7 +108,8 @@ impl AsyncWrite for NotaryConnection {
/// Client that sets up connection to notary server.
#[derive(Debug, Clone, derive_builder::Builder)]
pub struct NotaryClient {
/// Host of the notary server endpoint, either a DNS name (if TLS is used) or IP address.
/// Host of the notary server endpoint, either a DNS name (if TLS is used)
/// or IP address.
#[builder(setter(into))]
host: String,
/// Port of the notary server endpoint.
@@ -116,10 +118,12 @@ pub struct NotaryClient {
/// Flag to turn on/off using TLS with notary server.
#[builder(setter(name = "enable_tls"), default = "true")]
tls: bool,
/// Root certificate store used for establishing TLS connection with notary server.
/// Root certificate store used for establishing TLS connection with notary
/// server.
#[builder(default = "default_root_store()")]
root_cert_store: RootCertStore,
/// API key used to call notary server endpoints if whitelisting is enabled in notary server.
/// API key used to call notary server endpoints if whitelisting is enabled
/// in notary server.
#[builder(setter(into, strip_option), default)]
api_key: Option<String>,
}
@@ -127,8 +131,9 @@ pub struct NotaryClient {
impl NotaryClientBuilder {
// Default setter of port.
fn default_port(&self) -> u16 {
// If port is not specified, set it to 80 if TLS is off, else 443 since TLS is on
// (including when self.tls = None, which means it's set to default (true)).
// If port is not specified, set it to 80 if TLS is off, else 443 since TLS is
// on (including when self.tls = None, which means it's set to default
// (true)).
if let Some(false) = self.tls {
80
} else {
@@ -143,7 +148,8 @@ impl NotaryClient {
NotaryClientBuilder::default()
}
/// Configures and requests a notarization, returning a connection to the notary server if successful.
/// Configures and requests a notarization, returning a connection to the
/// notary server if successful.
pub async fn request_notarization(
&self,
notarization_request: NotarizationRequest,
@@ -202,7 +208,8 @@ impl NotaryClient {
) -> Result<(S, String), ClientError> {
let http_scheme = if self.tls { "https" } else { "http" };
// Attach the hyper HTTP client to the notary connection to send request to the /session endpoint to configure notarization and obtain session id.
// Attach the hyper HTTP client to the notary connection to send request to the
// /session endpoint to configure notarization and obtain session id.
let (mut notary_request_sender, notary_connection) =
hyper::client::conn::http1::handshake(TokioIo::new(notary_socket))
.await
@@ -211,7 +218,8 @@ impl NotaryClient {
ClientError::new(ErrorKind::Connection, Some(Box::new(err)))
})?;
// Create a future to poll the notary connection to completion before extracting the socket.
// Create a future to poll the notary connection to completion before extracting
// the socket.
let notary_connection_fut = async {
// Claim back notary socket after HTTP exchange is done.
let Parts {
@@ -224,7 +232,8 @@ impl NotaryClient {
Ok(notary_socket)
};
// Create a future to send configuration and notarization requests to the notary server using the connection established above.
// Create a future to send configuration and notarization requests to the notary
// server using the connection established above.
let client_requests_fut = async {
// Build the HTTP request to configure notarization.
let configuration_request_payload =
@@ -311,10 +320,12 @@ impl NotaryClient {
configuration_response_payload_parsed
);
// Send notarization request via HTTP, where the underlying TCP/TLS connection will be extracted later.
// Send notarization request via HTTP, where the underlying TCP/TLS connection
// will be extracted later.
let notarization_request = Request::builder()
// Need to specify the session_id so that notary server knows the right configuration to use
// as the configuration is set in the previous HTTP call.
// Need to specify the session_id so that notary server knows the right
// configuration to use as the configuration is set in the previous
// HTTP call.
.uri(format!(
"{http_scheme}://{}:{}/notarize?sessionId={}",
self.host, self.port, &configuration_response_payload_parsed.session_id
@@ -322,7 +333,8 @@ impl NotaryClient {
.method("GET")
.header("Host", &self.host)
.header("Connection", "Upgrade")
// Need to specify this upgrade header for server to extract TCP/TLS connection later.
// Need to specify this upgrade header for server to extract TCP/TLS connection
// later.
.header("Upgrade", "TCP")
.body(Either::Right(Empty::<Bytes>::new()))
.map_err(|err| {
@@ -358,7 +370,8 @@ impl NotaryClient {
Ok(configuration_response_payload_parsed.session_id)
};
// Poll both futures simultaneously to obtain the resulting socket and session_id.
// Poll both futures simultaneously to obtain the resulting socket and
// session_id.
let (notary_socket, session_id) =
futures::try_join!(notary_connection_fut, client_requests_fut)?;

View File

@@ -1,6 +1,7 @@
//! Notary client errors.
//!
//! This module handles errors that might occur during connection setup and notarization requests.
//! This module handles errors that might occur during connection setup and
//! notarization requests.
use derive_builder::UninitializedFieldError;
use std::{error::Error, fmt};

View File

@@ -1,9 +1,9 @@
//! Notary client library.
//!
//! A notary client's purpose is to establish a connection to the notary server via TCP or TLS, and
//! to configure and request notarization.
//! Note that the actual notarization is not performed by the notary client but by the prover of the
//! TLSNotary protocol.
//! A notary client's purpose is to establish a connection to the notary server
//! via TCP or TLS, and to configure and request notarization.
//! Note that the actual notarization is not performed by the notary client but
//! by the prover of the TLSNotary protocol.
#![deny(missing_docs, unreachable_pub, unused_must_use)]
#![deny(clippy::all)]
#![forbid(unsafe_code)]

View File

@@ -42,15 +42,18 @@ pub struct ServerProperties {
pub name: String,
pub host: String,
pub port: u16,
/// Static html response returned from API root endpoint "/". Default html response contains
/// placeholder strings that will be replaced with actual values in server.rs, e.g. {version}, {public_key}
/// Static html response returned from API root endpoint "/". Default html
/// response contains placeholder strings that will be replaced with
/// actual values in server.rs, e.g. {version}, {public_key}
pub html_info: String,
}
#[derive(Clone, Debug, Deserialize, Default)]
#[serde(rename_all = "kebab-case")]
pub struct TLSProperties {
/// Flag to turn on/off TLS between prover and notary (should always be turned on unless TLS is handled by external setup e.g. reverse proxy, cloud)
/// Flag to turn on/off TLS between prover and notary (should always be
/// turned on unless TLS is handled by external setup e.g. reverse proxy,
/// cloud)
pub enabled: bool,
pub private_key_pem_path: String,
pub certificate_pem_path: String,
@@ -66,8 +69,8 @@ pub struct NotarySigningKeyProperties {
#[derive(Clone, Debug, Deserialize, Default)]
#[serde(rename_all = "kebab-case")]
pub struct LoggingProperties {
/// Log verbosity level of the default filtering logic, which is notary_server=<level>,tlsn_verifier=<level>,tls_mpc=<level>
/// Must be either of <https://docs.rs/tracing/latest/tracing/struct.Level.html#implementations>
/// Log verbosity level of the default filtering logic, which is
/// notary_server=<level>,tlsn_verifier=<level>,tls_mpc=<level> Must be either of <https://docs.rs/tracing/latest/tracing/struct.Level.html#implementations>
pub level: String,
/// Custom filtering logic, refer to the syntax here https://docs.rs/tracing-subscriber/latest/tracing_subscriber/filter/struct.EnvFilter.html#example-syntax
/// This will override the default filtering logic above

View File

@@ -1,7 +1,8 @@
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
/// Structure of each whitelisted record of the API key whitelist for authorization purpose
/// Structure of each whitelisted record of the API key whitelist for
/// authorization purpose
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct AuthorizationWhitelistRecord {
@@ -10,7 +11,8 @@ pub struct AuthorizationWhitelistRecord {
pub created_at: String,
}
/// Convert whitelist data structure from vector to hashmap using api_key as the key to speed up lookup
/// Convert whitelist data structure from vector to hashmap using api_key as the
/// key to speed up lookup
pub fn authorization_whitelist_vec_into_hashmap(
authorization_whitelist: Vec<AuthorizationWhitelistRecord>,
) -> HashMap<String, AuthorizationWhitelistRecord> {

View File

@@ -39,7 +39,8 @@ pub struct NotarizationRequestQuery {
pub enum ClientType {
/// Client that has access to the transport layer
Tcp,
/// Client that cannot directly access transport layer, e.g. browser extension
/// Client that cannot directly access transport layer, e.g. browser
/// extension
Websocket,
}

View File

@@ -46,7 +46,8 @@ use crate::{
util::parse_csv_file,
};
/// Start a TCP server (with or without TLS) to accept notarization request for both TCP and WebSocket clients
/// Start a TCP server (with or without TLS) to accept notarization request for
/// both TCP and WebSocket clients
#[tracing::instrument(skip(config))]
pub async fn run_server(config: &NotaryServerProperties) -> Result<(), NotaryServerError> {
// Load the private key for notarized transcript signing
@@ -161,7 +162,8 @@ pub async fn run_server(config: &NotaryServerProperties) -> Result<(), NotarySer
.with_state(notary_globals);
loop {
// Poll and await for any incoming connection, ensure that all operations inside are infallible to prevent bringing down the server
// Poll and await for any incoming connection, ensure that all operations inside
// are infallible to prevent bringing down the server
let stream = match poll_fn(|cx| Pin::new(&mut listener).poll_accept(cx)).await {
Ok((stream, _)) => stream,
Err(err) => {
@@ -191,8 +193,9 @@ pub async fn run_server(config: &NotaryServerProperties) -> Result<(), NotarySer
// Serve different requests using the same hyper protocol and axum router
let _ = protocol
.serve_connection(io, hyper_service)
// use with_upgrades to upgrade connection to websocket for websocket clients
// and to extract tcp connection for tcp clients
// use with_upgrades to upgrade connection to websocket for websocket
// clients and to extract tcp connection for
// tcp clients
.with_upgrades()
.await;
}
@@ -300,7 +303,8 @@ fn load_authorization_whitelist(
// Setup a watcher to detect any changes to authorization whitelist
// When the list file is modified, the watcher thread will reload the whitelist
// The watcher is setup in a separate thread by the notify library which is synchronous
// The watcher is setup in a separate thread by the notify library which is
// synchronous
fn watch_and_reload_authorization_whitelist(
config: NotaryServerProperties,
authorization_whitelist: Option<Arc<Mutex<HashMap<String, AuthorizationWhitelistRecord>>>>,
@@ -308,7 +312,8 @@ fn watch_and_reload_authorization_whitelist(
// Only setup the watcher if auth whitelist is loaded
let watcher = if let Some(authorization_whitelist) = authorization_whitelist {
let cloned_config = config.clone();
// Setup watcher by giving it a function that will be triggered when an event is detected
// Setup watcher by giving it a function that will be triggered when an event is
// detected
let mut watcher = RecommendedWatcher::new(
move |event: Result<Event, Error>| {
match event {
@@ -351,7 +356,8 @@ fn watch_and_reload_authorization_whitelist(
// Skip setup the watcher if auth whitelist is not loaded
None
};
// Need to return the watcher to parent function, else it will be dropped and stop listening
// Need to return the watcher to parent function, else it will be dropped and
// stop listening
Ok(watcher)
}

View File

@@ -32,8 +32,9 @@ use crate::{
},
};
/// A wrapper enum to facilitate extracting TCP connection for either WebSocket or TCP clients,
/// so that we can use a single endpoint and handler for notarization for both types of clients
/// A wrapper enum to facilitate extracting TCP connection for either WebSocket
/// or TCP clients, so that we can use a single endpoint and handler for
/// notarization for both types of clients
pub enum ProtocolUpgrade {
Tcp(TcpUpgrade),
Ws(WebSocketUpgrade),
@@ -67,9 +68,10 @@ where
}
}
/// Handler to upgrade protocol from http to either websocket or underlying tcp depending on the type of client
/// the session_id parameter is also extracted here to fetch the configuration parameters
/// that have been submitted in the previous request to /session made by the same client
/// Handler to upgrade protocol from http to either websocket or underlying tcp
/// depending on the type of client the session_id parameter is also extracted
/// here to fetch the configuration parameters that have been submitted in the
/// previous request to /session made by the same client
pub async fn upgrade_protocol(
protocol_upgrade: ProtocolUpgrade,
State(notary_globals): State<NotaryGlobals>,
@@ -77,7 +79,8 @@ pub async fn upgrade_protocol(
) -> Response {
info!("Received upgrade protocol request");
let session_id = params.session_id;
// Check if session_id exists in the store, this also removes session_id from the store as each session_id can only be used once
// Check if session_id exists in the store, this also removes session_id from
// the store as each session_id can only be used once
if notary_globals
.store
.lock()
@@ -89,7 +92,8 @@ pub async fn upgrade_protocol(
error!(err_msg);
return NotaryServerError::BadProverRequest(err_msg).into_response();
};
// This completes the HTTP Upgrade request and returns a successful response to the client, meanwhile initiating the websocket or tcp connection
// This completes the HTTP Upgrade request and returns a successful response to
// the client, meanwhile initiating the websocket or tcp connection
match protocol_upgrade {
ProtocolUpgrade::Ws(ws) => {
ws.on_upgrade(move |socket| websocket_notarize(socket, notary_globals, session_id))
@@ -100,7 +104,8 @@ pub async fn upgrade_protocol(
}
}
/// Handler to initialize and configure notarization for both TCP and WebSocket clients
/// Handler to initialize and configure notarization for both TCP and WebSocket
/// clients
#[debug_handler(state = NotaryGlobals)]
pub async fn initialize(
State(notary_globals): State<NotaryGlobals>,
@@ -120,7 +125,8 @@ pub async fn initialize(
}
};
// Ensure that the max_sent_data, max_recv_data submitted is not larger than the global max limits configured in notary server
// Ensure that the max_sent_data, max_recv_data submitted is not larger than the
// global max limits configured in notary server
if payload.max_sent_data.is_some() || payload.max_recv_data.is_some() {
if payload.max_sent_data.unwrap_or_default()
> notary_globals.notarization_config.max_sent_data

View File

@@ -2,7 +2,8 @@
//! where we swapped out tokio_tungstenite (https://docs.rs/tokio-tungstenite/latest/tokio_tungstenite/)
//! with async_tungstenite (https://docs.rs/async-tungstenite/latest/async_tungstenite/) so that we can use
//! ws_stream_tungstenite (https://docs.rs/ws_stream_tungstenite/latest/ws_stream_tungstenite/index.html)
//! to get AsyncRead and AsyncWrite implemented for the WebSocket. Any other modification is commented with the prefix "NOTARY_MODIFICATION:"
//! to get AsyncRead and AsyncWrite implemented for the WebSocket. Any other
//! modification is commented with the prefix "NOTARY_MODIFICATION:"
//!
//! The code is under the following license:
//!
@@ -160,14 +161,15 @@ use tracing::error;
/// Extractor for establishing WebSocket connections.
///
/// Note: This extractor requires the request method to be `GET` so it should
/// always be used with [`get`](crate::routing::get). Requests with other methods will be
/// rejected.
/// always be used with [`get`](crate::routing::get). Requests with other
/// methods will be rejected.
///
/// See the [module docs](self) for an example.
#[cfg_attr(docsrs, doc(cfg(feature = "ws")))]
pub struct WebSocketUpgrade<F = DefaultOnFailedUpgrade> {
config: WebSocketConfig,
/// The chosen protocol sent in the `Sec-WebSocket-Protocol` header of the response.
/// The chosen protocol sent in the `Sec-WebSocket-Protocol` header of the
/// response.
protocol: Option<HeaderValue>,
sec_websocket_key: HeaderValue,
on_upgrade: hyper::upgrade::OnUpgrade,
@@ -187,31 +189,36 @@ impl<F> std::fmt::Debug for WebSocketUpgrade<F> {
}
impl<F> WebSocketUpgrade<F> {
/// The target minimum size of the write buffer to reach before writing the data
/// to the underlying stream.
/// The target minimum size of the write buffer to reach before writing the
/// data to the underlying stream.
///
/// The default value is 128 KiB.
///
/// If set to `0` each message will be eagerly written to the underlying stream.
/// It is often more optimal to allow them to buffer a little, hence the default value.
/// If set to `0` each message will be eagerly written to the underlying
/// stream. It is often more optimal to allow them to buffer a little,
/// hence the default value.
///
/// Note: [`flush`](SinkExt::flush) will always fully write the buffer regardless.
/// Note: [`flush`](SinkExt::flush) will always fully write the buffer
/// regardless.
pub fn write_buffer_size(mut self, size: usize) -> Self {
self.config.write_buffer_size = size;
self
}
/// The max size of the write buffer in bytes. Setting this can provide backpressure
/// in the case the write buffer is filling up due to write errors.
/// The max size of the write buffer in bytes. Setting this can provide
/// backpressure in the case the write buffer is filling up due to write
/// errors.
///
/// The default value is unlimited.
///
/// Note: The write buffer only builds up past [`write_buffer_size`](Self::write_buffer_size)
/// when writes to the underlying stream are failing. So the **write buffer can not
/// fill up if you are not observing write errors even if not flushing**.
/// Note: The write buffer only builds up past
/// [`write_buffer_size`](Self::write_buffer_size) when writes to the
/// underlying stream are failing. So the **write buffer can not fill up
/// if you are not observing write errors even if not flushing**.
///
/// Note: Should always be at least [`write_buffer_size + 1 message`](Self::write_buffer_size)
/// and probably a little more depending on error handling strategy.
/// Note: Should always be at least [`write_buffer_size + 1
/// message`](Self::write_buffer_size) and probably a little more
/// depending on error handling strategy.
pub fn max_write_buffer_size(mut self, max: usize) -> Self {
self.config.max_write_buffer_size = max;
self
@@ -238,12 +245,12 @@ impl<F> WebSocketUpgrade<F> {
/// Set the known protocols.
///
/// If the protocol name specified by `Sec-WebSocket-Protocol` header
/// to match any of them, the upgrade response will include `Sec-WebSocket-Protocol` header and
/// return the protocol name.
/// to match any of them, the upgrade response will include
/// `Sec-WebSocket-Protocol` header and return the protocol name.
///
/// The protocols should be listed in decreasing order of preference: if the client offers
/// multiple protocols that the server could support, the server will pick the first one in
/// this list.
/// The protocols should be listed in decreasing order of preference: if the
/// client offers multiple protocols that the server could support, the
/// server will pick the first one in this list.
///
/// # Examples
///
@@ -296,8 +303,8 @@ impl<F> WebSocketUpgrade<F> {
/// Provide a callback to call if upgrading the connection fails.
///
/// The connection upgrade is performed in a background task. If that fails this callback
/// will be called.
/// The connection upgrade is performed in a background task. If that fails
/// this callback will be called.
///
/// By default any errors will be silently ignored.
///
@@ -359,7 +366,8 @@ impl<F> WebSocketUpgrade<F> {
let upgraded = TokioIo::new(upgraded);
let socket = WebSocketStream::from_raw_socket(
// NOTARY_MODIFICATION: Need to use TokioAdapter to wrap Upgraded which doesn't implement futures crate's AsyncRead and AsyncWrite
// NOTARY_MODIFICATION: Need to use TokioAdapter to wrap Upgraded which doesn't
// implement futures crate's AsyncRead and AsyncWrite
TokioAdapter::new(upgraded),
protocol::Role::Server,
Some(config),
@@ -504,7 +512,8 @@ pub struct WebSocket {
}
impl WebSocket {
/// NOTARY_MODIFICATION: Consume `self` and get the inner [`async_tungstenite::WebSocketStream`].
/// NOTARY_MODIFICATION: Consume `self` and get the inner
/// [`async_tungstenite::WebSocketStream`].
pub fn into_inner(self) -> WebSocketStream<TokioAdapter<TokioIo<hyper::upgrade::Upgraded>>> {
self.inner
}
@@ -575,7 +584,8 @@ impl Sink<Message> for WebSocket {
}
}
/// Status code used to indicate why an endpoint is closing the WebSocket connection.
/// Status code used to indicate why an endpoint is closing the WebSocket
/// connection.
pub type CloseCode = u16;
/// A struct representing the close command.
@@ -620,16 +630,16 @@ pub enum Message {
///
/// The payload here must have a length less than 125 bytes.
///
/// Ping messages will be automatically responded to by the server, so you do not have to worry
/// about dealing with them yourself.
/// Ping messages will be automatically responded to by the server, so you
/// do not have to worry about dealing with them yourself.
Ping(Vec<u8>),
/// A pong message with the specified payload
///
/// The payload here must have a length less than 125 bytes.
///
/// Pong messages will be automatically sent to the client if a ping message is received, so
/// you do not have to worry about constructing them yourself unless you want to implement a
/// [unidirectional heartbeat](https://tools.ietf.org/html/rfc6455#section-5.5.3).
/// Pong messages will be automatically sent to the client if a ping message
/// is received, so you do not have to worry about constructing them
/// yourself unless you want to implement a [unidirectional heartbeat](https://tools.ietf.org/html/rfc6455#section-5.5.3).
Pong(Vec<u8>),
/// A close message with the optional close frame.
Close(Option<CloseFrame<'static>>),
@@ -820,20 +830,22 @@ pub mod close_code {
//!
//! [`CloseCode`]: super::CloseCode
/// Indicates a normal closure, meaning that the purpose for which the connection was
/// established has been fulfilled.
/// Indicates a normal closure, meaning that the purpose for which the
/// connection was established has been fulfilled.
pub const NORMAL: u16 = 1000;
/// Indicates that an endpoint is "going away", such as a server going down or a browser having
/// navigated away from a page.
/// Indicates that an endpoint is "going away", such as a server going down
/// or a browser having navigated away from a page.
pub const AWAY: u16 = 1001;
/// Indicates that an endpoint is terminating the connection due to a protocol error.
/// Indicates that an endpoint is terminating the connection due to a
/// protocol error.
pub const PROTOCOL: u16 = 1002;
/// Indicates that an endpoint is terminating the connection because it has received a type of
/// data it cannot accept (e.g., an endpoint that understands only text data MAY send this if
/// it receives a binary message).
/// Indicates that an endpoint is terminating the connection because it has
/// received a type of data it cannot accept (e.g., an endpoint that
/// understands only text data MAY send this if it receives a binary
/// message).
pub const UNSUPPORTED: u16 = 1003;
/// Indicates that no status code was included in a closing frame.
@@ -842,38 +854,42 @@ pub mod close_code {
/// Indicates an abnormal closure.
pub const ABNORMAL: u16 = 1006;
/// Indicates that an endpoint is terminating the connection because it has received data
/// within a message that was not consistent with the type of the message (e.g., non-UTF-8
/// RFC3629 data within a text message).
/// Indicates that an endpoint is terminating the connection because it has
/// received data within a message that was not consistent with the type
/// of the message (e.g., non-UTF-8 RFC3629 data within a text message).
pub const INVALID: u16 = 1007;
/// Indicates that an endpoint is terminating the connection because it has received a message
/// that violates its policy. This is a generic status code that can be returned when there is
/// no other more suitable status code (e.g., `UNSUPPORTED` or `SIZE`) or if there is a need to
/// hide specific details about the policy.
/// Indicates that an endpoint is terminating the connection because it has
/// received a message that violates its policy. This is a generic
/// status code that can be returned when there is no other more
/// suitable status code (e.g., `UNSUPPORTED` or `SIZE`) or if there is a
/// need to hide specific details about the policy.
pub const POLICY: u16 = 1008;
/// Indicates that an endpoint is terminating the connection because it has received a message
/// that is too big for it to process.
/// Indicates that an endpoint is terminating the connection because it has
/// received a message that is too big for it to process.
pub const SIZE: u16 = 1009;
/// Indicates that an endpoint (client) is terminating the connection because it has expected
/// the server to negotiate one or more extension, but the server didn't return them in the
/// response message of the WebSocket handshake. The list of extensions that are needed should
/// be given as the reason for closing. Note that this status code is not used by the server,
/// because it can fail the WebSocket handshake instead.
/// Indicates that an endpoint (client) is terminating the connection
/// because it has expected the server to negotiate one or more
/// extension, but the server didn't return them in the response message
/// of the WebSocket handshake. The list of extensions that are needed
/// should be given as the reason for closing. Note that this status
/// code is not used by the server, because it can fail the WebSocket
/// handshake instead.
pub const EXTENSION: u16 = 1010;
/// Indicates that a server is terminating the connection because it encountered an unexpected
/// condition that prevented it from fulfilling the request.
/// Indicates that a server is terminating the connection because it
/// encountered an unexpected condition that prevented it from
/// fulfilling the request.
pub const ERROR: u16 = 1011;
/// Indicates that the server is restarting.
pub const RESTART: u16 = 1012;
/// Indicates that the server is overloaded and the client should either connect to a different
/// IP (when multiple targets exist), or reconnect to the same IP when a user has performed an
/// action.
/// Indicates that the server is overloaded and the client should either
/// connect to a different IP (when multiple targets exist), or
/// reconnect to the same IP when a user has performed an action.
pub const AGAIN: u16 = 1013;
}

View File

@@ -12,9 +12,10 @@ use tracing::{debug, error, info};
use crate::{domain::notary::NotaryGlobals, service::notary_service, NotaryServerError};
/// Custom extractor used to extract underlying TCP connection for TCP client — using the same upgrade primitives used by
/// the WebSocket implementation where the underlying TCP connection (wrapped in an Upgraded object) only gets polled as an OnUpgrade future
/// after the ongoing HTTP request is finished (ref: https://github.com/tokio-rs/axum/blob/a6a849bb5b96a2f641fa077fe76f70ad4d20341c/axum/src/extract/ws.rs#L122)
/// Custom extractor used to extract underlying TCP connection for TCP client —
/// using the same upgrade primitives used by the WebSocket implementation where
/// the underlying TCP connection (wrapped in an Upgraded object) only gets
/// polled as an OnUpgrade future after the ongoing HTTP request is finished (ref: https://github.com/tokio-rs/axum/blob/a6a849bb5b96a2f641fa077fe76f70ad4d20341c/axum/src/extract/ws.rs#L122)
///
/// More info on the upgrade primitives: https://docs.rs/hyper/latest/hyper/upgrade/index.html
pub struct TcpUpgrade {
@@ -43,8 +44,9 @@ where
impl TcpUpgrade {
/// Utility function to complete the http upgrade protocol by
/// (1) Return 101 switching protocol response to client to indicate the switching to TCP
/// (2) Spawn a new thread to await on the OnUpgrade object to claim the underlying TCP connection
/// (1) Return 101 switching protocol response to client to indicate the
/// switching to TCP (2) Spawn a new thread to await on the OnUpgrade
/// object to claim the underlying TCP connection
pub fn on_upgrade<C, Fut>(self, callback: C) -> Response
where
C: FnOnce(TokioIo<Upgraded>) -> Fut + Send + 'static,

View File

@@ -13,7 +13,8 @@ pub async fn websocket_notarize(
session_id: String,
) {
debug!(?session_id, "Upgraded to websocket connection");
// Wrap the websocket in WsStream so that we have AsyncRead and AsyncWrite implemented
// Wrap the websocket in WsStream so that we have AsyncRead and AsyncWrite
// implemented
let stream = WsStream::new(socket.into_inner());
match notary_service(
stream,

View File

@@ -157,8 +157,8 @@ async fn tls_prover(notary_config: NotaryServerProperties) -> (NotaryConnection,
}
#[rstest]
// For `tls_without_auth` test to pass, one needs to add "<NOTARY_HOST> <NOTARY_DNS>" in /etc/hosts so that
// this test programme can resolve the self-named NOTARY_DNS to NOTARY_HOST IP successfully.
// For `tls_without_auth` test to pass, one needs to add "<NOTARY_HOST> <NOTARY_DNS>" in /etc/hosts
// so that this test programme can resolve the self-named NOTARY_DNS to NOTARY_HOST IP successfully.
#[case::tls_without_auth(
tls_prover(setup_config_and_server(100, 7047, true, false).await)
)]
@@ -194,7 +194,8 @@ async fn test_tcp_prover<S: AsyncWrite + AsyncRead + Send + Unpin + 'static>(
.build()
.unwrap();
// Prover config using the session_id returned from calling /session endpoint in notary client.
// Prover config using the session_id returned from calling /session endpoint in
// notary client.
let prover_config = ProverConfig::builder()
.server_name(SERVER_DOMAIN)
.protocol_config(protocol_config)
@@ -279,7 +280,8 @@ async fn test_websocket_prover() {
let notary_port = notary_config.server.port;
// Connect to the notary server via TLS-WebSocket
// Try to avoid dealing with transport layer directly to mimic the limitation of a browser extension that uses websocket
// Try to avoid dealing with transport layer directly to mimic the limitation of
// a browser extension that uses websocket
//
// Establish TLS setup for connections later
let certificate =
@@ -336,10 +338,12 @@ async fn test_websocket_prover() {
// Connect to the Notary via TLS-Websocket
//
// Note: This will establish a new TLS-TCP connection instead of reusing the previous TCP connection
// used in the previous HTTP POST request because we cannot claim back the tcp connection used in hyper
// client while using its high level request function — there does not seem to have a crate that can let you
// make a request without establishing TCP connection where you can claim the TCP connection later after making the request
// Note: This will establish a new TLS-TCP connection instead of reusing the
// previous TCP connection used in the previous HTTP POST request because we
// cannot claim back the tcp connection used in hyper client while using its
// high level request function — there does not seem to have a crate that can
// let you make a request without establishing TCP connection where you can
// claim the TCP connection later after making the request
let request = http::Request::builder()
// Need to specify the session_id so that notary server knows the right configuration to use
// as the configuration is set in the previous HTTP call
@@ -365,7 +369,8 @@ async fn test_websocket_prover() {
.await
.unwrap();
// Wrap the socket with the adapter so that we get AsyncRead and AsyncWrite implemented
// Wrap the socket with the adapter so that we get AsyncRead and AsyncWrite
// implemented
let notary_ws_socket = WsStream::new(notary_ws_stream);
// Connect to the Server

View File

@@ -13,8 +13,8 @@ pub struct ProverConfig {
server_name: ServerName,
/// Protocol configuration to be checked with the verifier.
protocol_config: ProtocolConfig,
/// Whether the `deferred decryption` feature is toggled on from the start of the MPC-TLS
/// connection.
/// Whether the `deferred decryption` feature is toggled on from the start
/// of the MPC-TLS connection.
///
/// See `defer_decryption_from_start` in [tls_mpc::MpcTlsLeaderConfig].
#[builder(default = "true")]
@@ -45,8 +45,8 @@ impl ProverConfig {
&self.protocol_config
}
/// Returns whether the `deferred decryption` feature is toggled on from the start of the MPC-TLS
/// connection.
/// Returns whether the `deferred decryption` feature is toggled on from the
/// start of the MPC-TLS connection.
pub fn defer_decryption_from_start(&self) -> bool {
self.defer_decryption_from_start
}

View File

@@ -117,8 +117,8 @@ impl Prover<state::Initialized> {
impl Prover<state::Setup> {
/// Connects to the server using the provided socket.
///
/// Returns a handle to the TLS connection, a future which returns the prover once the connection is
/// closed.
/// Returns a handle to the TLS connection, a future which returns the
/// prover once the connection is closed.
///
/// # Arguments
///
@@ -255,8 +255,9 @@ impl Prover<state::Closed> {
/// Starts notarization of the TLS session.
///
/// Used when the TLS verifier is a Notary to transition the prover to the next state
/// where it can generate commitments to the transcript prior to finalization.
/// Used when the TLS verifier is a Notary to transition the prover to the
/// next state where it can generate commitments to the transcript prior
/// to finalization.
pub fn start_notarize(self) -> Prover<Notarize> {
Prover {
config: self.config,
@@ -267,8 +268,8 @@ impl Prover<state::Closed> {
/// Starts proving the TLS session.
///
/// This function transitions the prover into a state where it can prove content of the
/// transcript.
/// This function transitions the prover into a state where it can prove
/// content of the transcript.
pub fn start_prove(self) -> Prover<Prove> {
Prover {
config: self.config,
@@ -404,15 +405,17 @@ pub struct ProverControl {
}
impl ProverControl {
/// Defers decryption of data from the server until the server has closed the connection.
/// Defers decryption of data from the server until the server has closed
/// the connection.
///
/// This is a performance optimization which will significantly reduce the amount of upload bandwidth
/// used by the prover.
/// This is a performance optimization which will significantly reduce the
/// amount of upload bandwidth used by the prover.
///
/// # Notes
///
/// * The prover may need to close the connection to the server in order for it to close the connection
/// on its end. If neither the prover or server close the connection this will cause a deadlock.
/// * The prover may need to close the connection to the server in order for
/// it to close the connection on its end. If neither the prover or server
/// close the connection this will cause a deadlock.
pub async fn defer_decryption(&self) -> Result<(), ProverError> {
self.mpc_ctrl
.defer_decryption()

View File

@@ -1,7 +1,7 @@
//! This module handles the proving phase of the prover.
//!
//! Here the prover deals with a verifier directly, so there is no notary involved. Instead
//! the verifier directly verifies parts of the transcript.
//! Here the prover deals with a verifier directly, so there is no notary
//! involved. Instead the verifier directly verifies parts of the transcript.
use super::{state::Prove as ProveState, Prover, ProverError};
use mpz_garble::{Memory, Prove};

View File

@@ -1,5 +1,5 @@
//! This library provides the [Backend] trait to encapsulate the cryptography backend of the TLS
//! client.
//! This library provides the [Backend] trait to encapsulate the cryptography
//! backend of the TLS client.
#![deny(missing_docs, unreachable_pub, unused_must_use)]
#![deny(clippy::all)]
@@ -66,8 +66,8 @@ pub enum DecryptMode {
Application,
}
/// Core trait which manages crypto operations for the TLS connection such as key exchange, encryption
/// and decryption.
/// Core trait which manages crypto operations for the TLS connection such as
/// key exchange, encryption and decryption.
#[async_trait]
pub trait Backend: Send {
/// Signals selected protocol version to implementor.
@@ -120,8 +120,8 @@ pub trait Backend: Send {
async fn buffer_incoming(&mut self, msg: OpaqueMessage) -> Result<(), BackendError>;
/// Returns next incoming message ready for decryption.
async fn next_incoming(&mut self) -> Result<Option<OpaqueMessage>, BackendError>;
/// Returns a notification future which resolves when the backend is ready to process
/// the next message.
/// Returns a notification future which resolves when the backend is ready
/// to process the next message.
async fn get_notify(&mut self) -> Result<BackendNotify, BackendError> {
Ok(BackendNotify::dummy())
}

View File

@@ -19,13 +19,15 @@ type CompatSinkWriter =
/// A TLS connection to a server.
///
/// This type implements `AsyncRead` and `AsyncWrite` and can be used to communicate
/// with a server using TLS.
/// This type implements `AsyncRead` and `AsyncWrite` and can be used to
/// communicate with a server using TLS.
///
/// # Note
///
/// This connection is closed on a best-effort basis if this is dropped. To ensure a clean close, you should call
/// [`AsyncWriteExt::close`](futures::io::AsyncWriteExt::close) to close the connection.
/// This connection is closed on a best-effort basis if this is dropped. To
/// ensure a clean close, you should call
/// [`AsyncWriteExt::close`](futures::io::AsyncWriteExt::close) to close the
/// connection.
#[derive(Debug)]
pub struct TlsConnection {
/// The data to be transmitted to the server is sent to this sink.

View File

@@ -1,9 +1,10 @@
//! Provides a TLS client which exposes an async socket.
//!
//! This library provides the [bind_client] function which attaches a TLS client to a socket
//! connection and then exposes a [TlsConnection] object, which provides an async socket API for
//! reading and writing cleartext. The TLS client will then automatically encrypt and decrypt
//! traffic and forward that to the provided socket.
//! This library provides the [bind_client] function which attaches a TLS client
//! to a socket connection and then exposes a [TlsConnection] object, which
//! provides an async socket API for reading and writing cleartext. The TLS
//! client will then automatically encrypt and decrypt traffic and forward that
//! to the provided socket.
#![deny(missing_docs, unreachable_pub, unused_must_use)]
#![deny(clippy::all)]
@@ -71,11 +72,13 @@ impl Future for ConnectionFuture {
/// Binds a client connection to the provided socket.
///
/// Returns a connection handle and a future which runs the connection to completion.
/// Returns a connection handle and a future which runs the connection to
/// completion.
///
/// # Errors
///
/// Any connection errors that occur will be returned from the future, not [`TlsConnection`].
/// Any connection errors that occur will be returned from the future, not
/// [`TlsConnection`].
pub fn bind_client<T: AsyncRead + AsyncWrite + Send + Unpin + 'static>(
socket: T,
mut client: ClientConnection,
@@ -138,7 +141,8 @@ pub fn bind_client<T: AsyncRead + AsyncWrite + Send + Unpin + 'static>(
#[cfg(feature = "tracing")]
debug!("handshake complete");
handshake_done = true;
// Start reading application data that needs to be transmitted from the `TlsConnection`.
// Start reading application data that needs to be transmitted from the
// `TlsConnection`.
tx_recv_fut = tx_receiver.next().fuse();
}

View File

@@ -66,8 +66,8 @@ async fn set_up_tls() -> TlsFixture {
}
}
// Expect the async tls client wrapped in `hyper::client` to make a successful request and receive
// the expected response
// Expect the async tls client wrapped in `hyper::client` to make a successful
// request and receive the expected response
#[tokio::test]
async fn test_hyper_ok() {
let (client_socket, server_socket) = tokio::io::duplex(1 << 16);
@@ -120,8 +120,8 @@ async fn test_hyper_ok() {
assert!(closed_conn.client.received_close_notify());
}
// Expect a clean TLS connection closure when server responds to the client's close_notify but
// doesn't close the socket
// Expect a clean TLS connection closure when server responds to the client's
// close_notify but doesn't close the socket
#[rstest]
#[tokio::test]
async fn test_ok_server_no_socket_close(set_up_tls: impl Future<Output = TlsFixture>) {
@@ -145,8 +145,8 @@ async fn test_ok_server_no_socket_close(set_up_tls: impl Future<Output = TlsFixt
assert!(closed_conn.client.received_close_notify());
}
// Expect a clean TLS connection closure when server responds to the client's close_notify AND
// also closes the socket
// Expect a clean TLS connection closure when server responds to the client's
// close_notify AND also closes the socket
#[rstest]
#[tokio::test]
async fn test_ok_server_socket_close(set_up_tls: impl Future<Output = TlsFixture>) {
@@ -155,7 +155,8 @@ async fn test_ok_server_socket_close(set_up_tls: impl Future<Output = TlsFixture
closed_tls_task,
} = set_up_tls.await;
// instruct the server to send close_notify back to us AND close the socket after 10 ms
// instruct the server to send close_notify back to us AND close the socket
// after 10 ms
client_tls_conn
.write_all(&pad("send_close_notify_and_close_socket".to_string()))
.await
@@ -170,8 +171,8 @@ async fn test_ok_server_socket_close(set_up_tls: impl Future<Output = TlsFixture
assert!(closed_conn.client.received_close_notify());
}
// Expect a clean TLS connection closure when server sends close_notify first but doesn't close
// the socket
// Expect a clean TLS connection closure when server sends close_notify first
// but doesn't close the socket
#[rstest]
#[tokio::test]
async fn test_ok_server_close_notify(set_up_tls: impl Future<Output = TlsFixture>) {
@@ -197,8 +198,8 @@ async fn test_ok_server_close_notify(set_up_tls: impl Future<Output = TlsFixture
assert!(closed_conn.client.received_close_notify());
}
// Expect a clean TLS connection closure when server sends close_notify first AND also closes
// the socket
// Expect a clean TLS connection closure when server sends close_notify first
// AND also closes the socket
#[rstest]
#[tokio::test]
async fn test_ok_server_close_notify_and_socket_close(
@@ -259,7 +260,8 @@ async fn test_ok_read_after_close(set_up_tls: impl Future<Output = TlsFixture>)
assert_eq!(std::str::from_utf8(&buf[0..n]).unwrap(), "hello");
}
// Expect there to be no error when server DOES NOT send close_notify but just closes the socket
// Expect there to be no error when server DOES NOT send close_notify but just
// closes the socket
#[rstest]
#[tokio::test]
async fn test_ok_server_no_close_notify(set_up_tls: impl Future<Output = TlsFixture>) {
@@ -391,7 +393,8 @@ async fn test_err_alert(set_up_tls: impl Future<Output = TlsFixture>) {
);
}
// Expect an error when trying to write data to a connection which server closed abruptly
// Expect an error when trying to write data to a connection which server closed
// abruptly
#[rstest]
#[tokio::test]
async fn test_err_write_after_close(set_up_tls: impl Future<Output = TlsFixture>) {

View File

@@ -11,14 +11,14 @@ const DEFAULT_TRANSCRIPT_MAX_SIZE: usize = 1 << 14;
pub struct TranscriptConfig {
/// The transcript id.
id: String,
/// The "opaque" transcript id, used for parts of the transcript that are not
/// part of the application data.
/// The "opaque" transcript id, used for parts of the transcript that are
/// not part of the application data.
opaque_id: String,
/// The maximum number of bytes that can be written to the transcript during the **online**
/// phase, i.e. while the MPC-TLS connection is active.
/// The maximum number of bytes that can be written to the transcript during
/// the **online** phase, i.e. while the MPC-TLS connection is active.
max_online_size: usize,
/// The maximum number of bytes that can be written to the transcript during the **offline**
/// phase, i.e. after the MPC-TLS connection was closed.
/// The maximum number of bytes that can be written to the transcript during
/// the **offline** phase, i.e. after the MPC-TLS connection was closed.
max_offline_size: usize,
}
@@ -64,14 +64,16 @@ impl TranscriptConfig {
&self.opaque_id
}
/// Returns the maximum number of bytes that can be written to the transcript during the **online**
/// phase, i.e. while the MPC-TLS connection is active.
/// Returns the maximum number of bytes that can be written to the
/// transcript during the **online** phase, i.e. while the MPC-TLS
/// connection is active.
pub fn max_online_size(&self) -> usize {
self.max_online_size
}
/// Returns the maximum number of bytes that can be written to the transcript during the **offline**
/// phase, i.e. after the MPC-TLS connection was closed.
/// Returns the maximum number of bytes that can be written to the
/// transcript during the **offline** phase, i.e. after the MPC-TLS
/// connection was closed.
pub fn max_offline_size(&self) -> usize {
self.max_offline_size
}
@@ -126,16 +128,17 @@ impl MpcTlsCommonConfig {
#[derive(Debug, Clone, Builder)]
pub struct MpcTlsLeaderConfig {
common: MpcTlsCommonConfig,
/// Whether the `deferred decryption` feature is toggled on from the start of the MPC-TLS
/// connection.
/// Whether the `deferred decryption` feature is toggled on from the start
/// of the MPC-TLS connection.
///
/// The received data will be decrypted locally without MPC, thus improving
/// bandwidth usage and performance.
///
/// Decryption of the data received while `deferred decryption` is toggled on will be deferred
/// until after the MPC-TLS connection is closed.
/// If you need to decrypt some subset of data received from the TLS peer while the MPC-TLS
/// connection is active, you must toggle `deferred decryption` **off** for that subset of data.
/// Decryption of the data received while `deferred decryption` is toggled
/// on will be deferred until after the MPC-TLS connection is closed.
/// If you need to decrypt some subset of data received from the TLS peer
/// while the MPC-TLS connection is active, you must toggle `deferred
/// decryption` **off** for that subset of data.
#[builder(default = "true")]
defer_decryption_from_start: bool,
}
@@ -151,8 +154,8 @@ impl MpcTlsLeaderConfig {
&self.common
}
/// Returns whether the `deferred decryption` feature is toggled on from the start of the MPC-TLS
/// connection.
/// Returns whether the `deferred decryption` feature is toggled on from the
/// start of the MPC-TLS connection.
pub fn defer_decryption_from_start(&self) -> bool {
self.defer_decryption_from_start
}

View File

@@ -156,7 +156,8 @@ impl MpcTlsFollower {
/// Runs the follower actor.
///
/// Returns a control handle and a future that resolves when the actor is stopped.
/// Returns a control handle and a future that resolves when the actor is
/// stopped.
///
/// # Note
///
@@ -238,8 +239,8 @@ impl MpcTlsFollower {
/// Returns an error if the follower is not accepting new messages.
///
/// This can happen if the follower has received a CloseNotify alert or if the leader has
/// committed to the transcript.
/// This can happen if the follower has received a CloseNotify alert or if
/// the leader has committed to the transcript.
fn is_accepting_messages(&self) -> Result<(), MpcTlsError> {
if self.close_notify {
return Err(MpcTlsError::new(
@@ -485,9 +486,10 @@ impl MpcTlsFollower {
debug!("decrypting message");
if self.committed {
// At this point the AEAD key was revealed to the leader and the leader locally decrypted
// the TLS message and now is proving to us that they know the plaintext which encrypts
// to the ciphertext of this TLS message.
// At this point the AEAD key was revealed to the leader and the leader locally
// decrypted the TLS message and now is proving to us that they know
// the plaintext which encrypts to the ciphertext of this TLS
// message.
self.decrypter.verify_plaintext(msg).await?;
} else {
self.decrypter.decrypt_blind(msg).await?;
@@ -519,7 +521,8 @@ impl MpcTlsFollower {
self.committed = true;
// Reveal the AEAD key to the leader only if there are TLS messages which need to be decrypted.
// Reveal the AEAD key to the leader only if there are TLS messages which need
// to be decrypted.
if !buffer.is_empty() {
self.decrypter.decode_key_blind().await?;
}
@@ -644,8 +647,9 @@ mod state {
pub(super) server_key: PublicKey,
/// TLS messages purportedly received by the leader from the server.
///
/// The follower must verify the authenticity of these messages with AEAD verification
/// (i.e. by verifying the authentication tag).
/// The follower must verify the authenticity of these messages with
/// AEAD verification (i.e. by verifying the authentication
/// tag).
pub(super) buffer: VecDeque<OpaqueMessage>,
}

View File

@@ -56,7 +56,8 @@ pub struct MpcTlsLeader {
encrypter: Encrypter,
decrypter: Decrypter,
/// When set, notifies the backend that there are TLS messages which need to be decrypted.
/// When set, notifies the backend that there are TLS messages which need to
/// be decrypted.
notifier: BackendNotifier,
/// Whether the backend is ready to decrypt messages.
@@ -151,7 +152,8 @@ impl MpcTlsLeader {
/// Runs the leader actor.
///
/// Returns a control handle and a future that resolves when the actor is stopped.
/// Returns a control handle and a future that resolves when the actor is
/// stopped.
///
/// # Note
///
@@ -322,8 +324,9 @@ impl MpcTlsLeader {
.await?;
let msg = if self.committed {
// At this point the AEAD key was revealed to us. We will locally decrypt the TLS message
// and will prove the knowledge of the plaintext to the follower.
// At this point the AEAD key was revealed to us. We will locally decrypt the
// TLS message and will prove the knowledge of the plaintext to the
// follower.
self.decrypter.prove_plaintext(msg).await?
} else {
self.decrypter.decrypt_private(msg).await?
@@ -390,8 +393,8 @@ impl MpcTlsLeader {
/// Commits the leader to the current transcript.
///
/// This reveals the AEAD key to the leader and disables sending or receiving
/// any further messages.
/// This reveals the AEAD key to the leader and disables sending or
/// receiving any further messages.
#[instrument(name = "finalize", level = "debug", skip_all, err)]
#[msg(skip, name = "Commit")]
pub async fn commit(&mut self) -> Result<(), MpcTlsError> {

View File

@@ -1,7 +1,9 @@
//! This crate provides tooling for instantiating MPC TLS machinery for leader and follower.
//! This crate provides tooling for instantiating MPC TLS machinery for leader
//! and follower.
//! The main API objects are [MpcTlsLeader] and [MpcTlsFollower], which wrap the necessary
//! cryptographic machinery and also an [MpcTlsChannel] for communication.
//! The main API objects are [MpcTlsLeader] and [MpcTlsFollower], which wrap the
//! necessary cryptographic machinery and also an [MpcTlsChannel] for
//! communication.
#![deny(missing_docs, unreachable_pub, unused_must_use)]
#![deny(clippy::all)]

View File

@@ -352,8 +352,9 @@ impl Decrypter {
/// Proves the plaintext of the message to the other party
///
/// This verifies the tag of the message and locally decrypts it. Then, this party
/// commits to the plaintext and proves it encrypts back to the ciphertext.
/// This verifies the tag of the message and locally decrypts it. Then, this
/// party commits to the plaintext and proves it encrypts back to the
/// ciphertext.
pub(crate) async fn prove_plaintext(
&mut self,
msg: OpaqueMessage,
@@ -388,8 +389,9 @@ impl Decrypter {
/// Verifies the plaintext of the message
///
/// This verifies the tag of the message then has the other party decrypt it. Then,
/// the other party commits to the plaintext and proves it encrypts back to the ciphertext.
/// This verifies the tag of the message then has the other party decrypt
/// it. Then, the other party commits to the plaintext and proves it
/// encrypts back to the ciphertext.
pub(crate) async fn verify_plaintext(&mut self, msg: OpaqueMessage) -> Result<(), MpcTlsError> {
let OpaqueMessage {
typ,

View File

@@ -93,8 +93,8 @@ pub async fn bind_test_server<
let mut read_buf = vec![0u8; APP_RECORD_LENGTH];
if conn.read_exact(&mut read_buf).await.is_err() {
// EOF reached because client closed its tx part of the socket.
// The client's rx part of the socket is still open and waiting for a clean server
// shutdown.
// The client's rx part of the socket is still open and waiting for a clean
// server shutdown.
if must_delay_when_closing {
// delay closing the socket
tokio::time::sleep(std::time::Duration::from_millis(CLOSE_DELAY)).await;
@@ -179,8 +179,8 @@ pub async fn bind_test_server<
break;
}
"send_record_with_bad_mac" => {
// send a record which a bad MAC which will trigger the `bad_record_mac` alert on
// the client side
// send a record which a bad MAC which will trigger the `bad_record_mac` alert
// on the client side
let (socket, _tls) = conn.into_inner();

View File

@@ -129,7 +129,8 @@ impl Verifier<state::Initialized> {
/// Runs the TLS verifier to completion, notarizing the TLS session.
///
/// This is a convenience method which runs all the steps needed for notarization.
/// This is a convenience method which runs all the steps needed for
/// notarization.
///
/// # Arguments
///
@@ -152,7 +153,8 @@ impl Verifier<state::Initialized> {
/// Runs the TLS verifier to completion, verifying the TLS session.
///
/// This is a convenience method which runs all the steps needed for verification.
/// This is a convenience method which runs all the steps needed for
/// verification.
///
/// # Arguments
///
@@ -231,8 +233,9 @@ impl Verifier<state::Setup> {
impl Verifier<state::Closed> {
/// Starts notarization of the TLS session.
///
/// If the verifier is a Notary, this function will transition the verifier to the next state
/// where it can sign the prover's commitments to the transcript.
/// If the verifier is a Notary, this function will transition the verifier
/// to the next state where it can sign the prover's commitments to the
/// transcript.
pub fn start_notarize(self) -> Verifier<Notarize> {
Verifier {
config: self.config,
@@ -243,8 +246,8 @@ impl Verifier<state::Closed> {
/// Starts verification of the TLS session.
///
/// This function transitions the verifier into a state where it can verify content of the
/// transcript.
/// This function transitions the verifier into a state where it can verify
/// content of the transcript.
pub fn start_verify(self) -> Verifier<Verify> {
Verifier {
config: self.config,

View File

@@ -19,7 +19,8 @@ impl Verifier<VerifyState> {
///
/// # Warning
///
/// The content of the received transcripts can not be considered authentic until after finalization.
/// The content of the received transcripts can not be considered authentic
/// until after finalization.
#[instrument(parent = &self.span, level = "info", skip_all, err)]
pub async fn receive(&mut self) -> Result<PartialTranscript, VerifierError> {
self.state

View File

@@ -19,8 +19,9 @@ impl<T> FuturesIo<T> {
///
/// # Safety
///
/// This wrapper is only safe to use if the inner I/O object does not under any circumstance
/// read from the buffer passed to `poll_read` in the `futures::AsyncRead` implementation.
/// This wrapper is only safe to use if the inner I/O object does not under
/// any circumstance read from the buffer passed to `poll_read` in the
/// `futures::AsyncRead` implementation.
pub(crate) fn new(inner: T) -> Self {
Self { inner }
}
@@ -68,7 +69,8 @@ where
cx: &mut Context<'_>,
mut buf: hyper::rt::ReadBufCursor<'_>,
) -> Poll<Result<(), std::io::Error>> {
// Safety: buf_slice should only be written to, so it's safe to convert `&mut [MaybeUninit<u8>]` to `&mut [u8]`.
// Safety: buf_slice should only be written to, so it's safe to convert `&mut
// [MaybeUninit<u8>]` to `&mut [u8]`.
let buf_slice = unsafe {
slice::from_raw_parts_mut(buf.as_mut().as_mut_ptr() as *mut u8, buf.as_mut().len())
};

View File

@@ -1,3 +1,4 @@
ignore = ["tls-core/", "tls-client/"]
ignore = ["crates/tls/core", "crates/tls/client"]
imports_granularity = "Crate"
wrap_comments = true