tlsn_verifier/
verify.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! This module handles the verification phase of the verifier.
//!
//! The TLS verifier is an application-specific verifier.

use crate::SessionInfo;

use super::{state::Verify as VerifyState, Verifier, VerifierError};
use mpz_memory_core::MemoryExt;
use mpz_vm_core::Execute;
use serio::stream::IoStreamExt;
use tlsn_common::msg::ServerIdentityProof;
use tlsn_core::transcript::{Direction, PartialTranscript};

use tracing::{info, instrument};

impl Verifier<VerifyState> {
    /// Receives the **purported** transcript from the Prover.
    ///
    /// # Warning
    ///
    /// The content of the received transcript 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
            .mux_fut
            .poll_with(async {
                // Receive partial transcript from the prover.
                let partial_transcript: PartialTranscript =
                    self.state.ctx.io_mut().expect_next().await?;

                info!("Received partial transcript from prover");

                // Check ranges.
                if partial_transcript.len_sent()
                    != self.state.connection_info.transcript_length.sent as usize
                    || partial_transcript.len_received()
                        != self.state.connection_info.transcript_length.received as usize
                {
                    return Err(VerifierError::verify(
                        "prover sent transcript with incorrect length",
                    ));
                }

                // Now verify the transcript parts which the prover wants to reveal.
                let sent_refs = self
                    .state
                    .transcript_refs
                    .get(Direction::Sent, partial_transcript.sent_authed())
                    .expect("index is in bounds");
                let recv_refs = self
                    .state
                    .transcript_refs
                    .get(Direction::Received, partial_transcript.received_authed())
                    .expect("index is in bounds");

                let plaintext_futs = sent_refs
                    .into_iter()
                    .chain(recv_refs)
                    .map(|slice| self.state.vm.decode(slice).map_err(VerifierError::zk))
                    .collect::<Result<Vec<_>, _>>()?;

                self.state.vm.flush(&mut self.state.ctx).await.unwrap();

                let mut purported_data = Vec::new();
                for mut fut in plaintext_futs {
                    let plaintext = fut
                        .try_recv()
                        .map_err(VerifierError::zk)?
                        .expect("plaintext should be decoded");
                    purported_data.extend_from_slice(&plaintext);
                }

                // Check that purported values are correct.
                if purported_data
                    .into_iter()
                    .zip(
                        partial_transcript
                            .iter(Direction::Sent)
                            .chain(partial_transcript.iter(Direction::Received)),
                    )
                    .any(|(a, b)| a != b)
                {
                    return Err(VerifierError::verify("purported transcript is incorrect"));
                }

                info!("Successfully verified purported transcript");

                Ok::<_, VerifierError>(partial_transcript)
            })
            .await
    }

    /// Verifies the TLS session.
    #[instrument(parent = &self.span, level = "info", skip_all, err)]
    pub async fn finalize(self) -> Result<SessionInfo, VerifierError> {
        let VerifyState {
            mux_ctrl,
            mut mux_fut,
            mut ctx,
            server_ephemeral_key,
            connection_info,
            ..
        } = self.state;

        let ServerIdentityProof {
            name: server_name,
            data,
        } = mux_fut.poll_with(ctx.io_mut().expect_next()).await?;

        // Verify the server identity data.
        data.verify_with_provider(
            self.config.crypto_provider(),
            connection_info.time,
            &server_ephemeral_key,
            &server_name,
        )
        .map_err(VerifierError::verify)?;

        info!("Successfully verified session");

        if !mux_fut.is_complete() {
            mux_ctrl.close();
            mux_fut.await?;
        }

        Ok(SessionInfo {
            server_name,
            connection_info,
        })
    }
}