tlsn_verifier/
verify.rs

1//! This module handles the verification phase of the verifier.
2//!
3//! The TLS verifier is an application-specific verifier.
4
5use crate::SessionInfo;
6
7use super::{state::Verify as VerifyState, Verifier, VerifierError};
8use mpz_memory_core::MemoryExt;
9use mpz_vm_core::Execute;
10use serio::stream::IoStreamExt;
11use tlsn_common::msg::ServerIdentityProof;
12use tlsn_core::transcript::{Direction, PartialTranscript};
13
14use tracing::{info, instrument};
15
16impl Verifier<VerifyState> {
17    /// Receives the **purported** transcript from the Prover.
18    ///
19    /// # Warning
20    ///
21    /// The content of the received transcript can not be considered authentic
22    /// until after finalization.
23    #[instrument(parent = &self.span, level = "info", skip_all, err)]
24    pub async fn receive(&mut self) -> Result<PartialTranscript, VerifierError> {
25        self.state
26            .mux_fut
27            .poll_with(async {
28                // Receive partial transcript from the prover.
29                let partial_transcript: PartialTranscript =
30                    self.state.ctx.io_mut().expect_next().await?;
31
32                info!("Received partial transcript from prover");
33
34                // Check ranges.
35                if partial_transcript.len_sent()
36                    != self.state.connection_info.transcript_length.sent as usize
37                    || partial_transcript.len_received()
38                        != self.state.connection_info.transcript_length.received as usize
39                {
40                    return Err(VerifierError::verify(
41                        "prover sent transcript with incorrect length",
42                    ));
43                }
44
45                // Now verify the transcript parts which the prover wants to reveal.
46                let sent_refs = self
47                    .state
48                    .transcript_refs
49                    .get(Direction::Sent, partial_transcript.sent_authed())
50                    .expect("index is in bounds");
51                let recv_refs = self
52                    .state
53                    .transcript_refs
54                    .get(Direction::Received, partial_transcript.received_authed())
55                    .expect("index is in bounds");
56
57                let plaintext_futs = sent_refs
58                    .into_iter()
59                    .chain(recv_refs)
60                    .map(|slice| self.state.vm.decode(slice).map_err(VerifierError::zk))
61                    .collect::<Result<Vec<_>, _>>()?;
62
63                self.state.vm.flush(&mut self.state.ctx).await.unwrap();
64
65                let mut authenticated_data = Vec::new();
66                for mut fut in plaintext_futs {
67                    let plaintext = fut
68                        .try_recv()
69                        .map_err(VerifierError::zk)?
70                        .expect("plaintext should be decoded");
71                    authenticated_data.extend_from_slice(&plaintext);
72                }
73
74                // Check that the purported data in the partial transcript is
75                // correct.
76                if authenticated_data
77                    .into_iter()
78                    .zip(
79                        partial_transcript
80                            .iter(Direction::Sent)
81                            .chain(partial_transcript.iter(Direction::Received)),
82                    )
83                    .any(|(a, b)| a != b)
84                {
85                    return Err(VerifierError::verify("purported transcript is incorrect"));
86                }
87
88                info!("Successfully verified purported transcript");
89
90                Ok::<_, VerifierError>(partial_transcript)
91            })
92            .await
93    }
94
95    /// Verifies the TLS session.
96    #[instrument(parent = &self.span, level = "info", skip_all, err)]
97    pub async fn finalize(self) -> Result<SessionInfo, VerifierError> {
98        let VerifyState {
99            mux_ctrl,
100            mut mux_fut,
101            mut ctx,
102            server_ephemeral_key,
103            connection_info,
104            ..
105        } = self.state;
106
107        let ServerIdentityProof {
108            name: server_name,
109            data,
110        } = mux_fut.poll_with(ctx.io_mut().expect_next()).await?;
111
112        // Verify the server identity data.
113        data.verify_with_provider(
114            self.config.crypto_provider(),
115            connection_info.time,
116            &server_ephemeral_key,
117            &server_name,
118        )
119        .map_err(VerifierError::verify)?;
120
121        info!("Successfully verified session");
122
123        if !mux_fut.is_complete() {
124            mux_ctrl.close();
125            mux_fut.await?;
126        }
127
128        Ok(SessionInfo {
129            server_name,
130            connection_info,
131        })
132    }
133}