# verifier.rs - source
Source of the Rust file `crates/tlsn/src/verifier.rs`.

Skip to main content

#
tlsn/
verifier.rs

    1//! Verifier.
    2
    3pub mod state;
    4mod verify;
    5
    6use std::sync::Arc;
    7
    8use mpz_common::Context;
    9pub use tlsn_core::{VerifierOutput, webpki::ServerCertVerifier};
    10
    11use crate::{
    12    Error, Result,
    13    mpz::{VerifierDeps, build_verifier_deps, translate_keys},
    14    msg::{ProveRequestMsg, Response, TlsCommitRequestMsg},
    15    tag::verify_tags,
    16};
    17use mpz_vm_core::prelude::*;
    18use serio::{SinkExt, stream::IoStreamExt};
    19use tlsn_core::{
    20    config::{
    21        prove::ProveRequest,
    22        tls_commit::{TlsCommitProtocolConfig, TlsCommitRequest},
    23        verifier::VerifierConfig,
    24    },
    25    connection::{ConnectionInfo, ServerName},
    26    transcript::TlsTranscript,
    27};
    28
    29use tracing::{Span, debug, info, info_span, instrument};
    30
    31/// Information about the TLS session.
    32#[derive(Debug)]
    33pub struct SessionInfo {
    34    /// Server's name.
    35    pub server_name: ServerName,
    36    /// Connection information.
    37    pub connection_info: ConnectionInfo,
    38}
    39
    40/// A Verifier instance.
    41pub struct Verifier<T: state::VerifierState = state::Initialized> {
    42    config: VerifierConfig,
    43    span: Span,
    44    ctx: Option<Context>,
    45    state: T,
    46}
    47
    48impl Verifier<state::Initialized> {
    49    /// Creates a new verifier.
    50    pub(crate) fn new(ctx: Context, config: VerifierConfig) -> Self {
    51        let span = info_span!("verifier");
    52        Self {
    53            config,
    54            span,
    55            ctx: Some(ctx),
    56            state: state::Initialized,
    57        }
    58    }
    59
    60    /// Starts the TLS commitment protocol.
    61    ///
    62    /// This initiates the TLS commitment protocol, receiving the prover's
    63    /// configuration and providing the opportunity to accept or reject it.
    64    #[instrument(parent = &self.span, level = "info", skip_all, err)]
    65    pub async fn commit(mut self) -> Result<Verifier<state::CommitStart>> {
    66        let mut ctx = self
    67            .ctx
    68            .take()
    69            .ok_or_else(|| Error::internal().with_msg("commitment protocol context was dropped"))?;
    70
    71        // Receives protocol configuration from prover to perform compatibility check.
    72        let TlsCommitRequestMsg { request, version } =
    73            ctx.io_mut().expect_next().await.map_err(|e| {
    74                Error::io()
    75                    .with_msg("commitment protocol failed to receive request")
    76                    .with_source(e)
    77            })?;
    78
    79        if version != *crate::VERSION {
    80            let msg = format!(
    81                "prover version does not match with verifier: {version} != {}",
    82                *crate::VERSION
    83            );
    84            ctx.io_mut()
    85                .send(Response::err(Some(msg.clone())))
    86                .await
    87                .map_err(|e| {
    88                    Error::io()
    89                        .with_msg("commitment protocol failed to send version mismatch response")
    90                        .with_source(e)
    91                })?;
    92
    93            return Err(Error::config().with_msg(msg));
    94        }
    95
    96        Ok(Verifier {
    97            config: self.config,
    98            span: self.span,
    99            ctx: Some(ctx),
    100            state: state::CommitStart { request },
    101        })
    102    }
    103}
    104
    105impl Verifier<state::CommitStart> {
    106    /// Returns the TLS commitment request.
    107    pub fn request(&self) -> &TlsCommitRequest {
    108        &self.state.request
    109    }
    110
    111    /// Accepts the proposed protocol configuration.
    112    #[instrument(parent = &self.span, level = "info", skip_all, err)]
    113    pub async fn accept(mut self) -> Result<Verifier<state::CommitAccepted>> {
    114        let mut ctx = self
    115            .ctx
    116            .take()
    117            .ok_or_else(|| Error::internal().with_msg("commitment protocol context was dropped"))?;
    118        let state::CommitStart { request } = self.state;
    119
    120        ctx.io_mut().send(Response::ok()).await.map_err(|e| {
    121            Error::io()
    122                .with_msg("commitment protocol failed to send acceptance")
    123                .with_source(e)
    124        })?;
    125
    126        let TlsCommitProtocolConfig::Mpc(mpc_tls_config) = request.protocol().clone() else {
    127            unreachable!("only MPC TLS is supported");
    128        };
    129
    130        let VerifierDeps { vm, mut mpc_tls } = build_verifier_deps(mpc_tls_config, ctx);
    131
    132        // Allocate resources for MPC-TLS in the VM.
    133        let mut keys = mpc_tls.alloc().map_err(|e| {
    134            Error::internal()
    135                .with_msg("commitment protocol failed to allocate mpc-tls resources")
    136                .with_source(e)
    137        })?;
    138        let vm_lock = vm.try_lock().expect("VM is not locked");
    139        translate_keys(&mut keys, &vm_lock);
    140        drop(vm_lock);
    141
    142        debug!("setting up mpc-tls");
    143
    144        mpc_tls.preprocess().await.map_err(|e| {
    145            Error::internal()
    146                .with_msg("commitment protocol failed during mpc-tls preprocessing")
    147                .with_source(e)
    148        })?;
    149
    150        debug!("mpc-tls setup complete");
    151
    152        Ok(Verifier {
    153            config: self.config,
    154            span: self.span,
    155            ctx: None,
    156            state: state::CommitAccepted { mpc_tls, keys, vm },
    157        })
    158    }
    159
    160    /// Rejects the proposed protocol configuration.
    161    #[instrument(parent = &self.span, level = "info", skip_all, err)]
    162    pub async fn reject(mut self, msg: Option<&str>) -> Result<()> {
    163        let mut ctx = self
    164            .ctx
    165            .take()
    166            .ok_or_else(|| Error::internal().with_msg("commitment protocol context was dropped"))?;
    167
    168        ctx.io_mut().send(Response::err(msg)).await.map_err(|e| {
    169            Error::io()
    170                .with_msg("commitment protocol failed to send rejection")
    171                .with_source(e)
    172        })?;
    173
    174        Ok(())
    175    }
    176}
    177
    178impl Verifier<state::CommitAccepted> {
    179    /// Runs the verifier until the TLS connection is closed.
    180    #[instrument(parent = &self.span, level = "info", skip_all, err)]
    181    pub async fn run(self) -> Result<Verifier<state::Committed>> {
    182        let state::CommitAccepted { mpc_tls, vm, keys } = self.state;
    183
    184        info!("starting MPC-TLS");
    185
    186        let (mut ctx, tls_transcript) = mpc_tls.run().await.map_err(|e| {
    187            Error::internal()
    188                .with_msg("mpc-tls execution failed")
    189                .with_source(e)
    190        })?;
    191
    192        info!("finished MPC-TLS");
    193
    194        {
    195            let mut vm = vm.try_lock().expect("VM should not be locked");
    196
    197            debug!("finalizing mpc");
    198
    199            vm.finalize(&mut ctx).await.map_err(|e| {
    200                Error::internal()
    201                    .with_msg("mpc finalization failed")
    202                    .with_source(e)
    203            })?;
    204
    205            debug!("mpc finalized");
    206        }
    207
    208        // Pull out ZK VM.
    209        let (_, mut vm) = Arc::into_inner(vm)
    210            .expect("vm should have only 1 reference")
    211            .into_inner()
    212            .into_inner();
    213
    214        // Prepare for the prover to prove tag verification of the received
    215        // records.
    216        let tag_proof = verify_tags(
    217            &mut vm,
    218            (keys.server_write_key, keys.server_write_iv),
    219            keys.server_write_mac_key,
    220            *tls_transcript.version(),
    221            tls_transcript.recv().to_vec(),
    222        )
    223        .map_err(|e| {
    224            Error::internal()
    225                .with_msg("tag verification setup failed")
    226                .with_source(e)
    227        })?;
    228
    229        vm.execute_all(&mut ctx).await.map_err(|e| {
    230            Error::internal()
    231                .with_msg("tag verification zk execution failed")
    232                .with_source(e)
    233        })?;
    234
    235        // Verify the tags.
    236        // After the verification, the entire TLS trancript becomes
    237        // authenticated from the verifier's perspective.
    238        tag_proof.verify().map_err(|e| {
    239            Error::internal()
    240                .with_msg("tag verification failed")
    241                .with_source(e)
    242        })?;
    243        debug!("MPC-TLS done");
    244
    245        Ok(Verifier {
    246            config: self.config,
    247            span: self.span,
    248            ctx: Some(ctx),
    249            state: state::Committed {
    250                vm,
    251                keys,
    252                tls_transcript,
    253            },
    254        })
    255    }
    256}
    257
    258impl Verifier<state::Committed> {
    259    /// Returns the TLS transcript.
    260    pub fn tls_transcript(&self) -> &TlsTranscript {
    261        &self.state.tls_transcript
    262    }
    263
    264    /// Begins verification of statements from the prover.
    265    #[instrument(parent = &self.span, level = "info", skip_all, err)]
    266    pub async fn verify(mut self) -> Result<Verifier<state::Verify>> {
    267        let mut ctx = self
    268            .ctx
    269            .take()
    270            .ok_or_else(|| Error::internal().with_msg("verification context was dropped"))?;
    271        let state::Committed {
    272            vm,
    273            keys,
    274            tls_transcript,
    275        } = self.state;
    276
    277        let ProveRequestMsg {
    278            request,
    279            handshake,
    280            transcript,
    281        } = ctx.io_mut().expect_next().await.map_err(|e| {
    282            Error::io()
    283                .with_msg("verification failed to receive prove request")
    284                .with_source(e)
    285        })?;
    286
    287        Ok(Verifier {
    288            config: self.config,
    289            span: self.span,
    290            ctx: Some(ctx),
    291            state: state::Verify {
    292                vm,
    293                keys,
    294                tls_transcript,
    295                request,
    296                handshake,
    297                transcript,
    298            },
    299        })
    300    }
    301
    302    /// Closes the connection with the prover.
    303    #[instrument(parent = &self.span, level = "info", skip_all, err)]
    304    pub async fn close(self) -> Result<()> {
    305        Ok(())
    306    }
    307}
    308
    309impl Verifier<state::Verify> {
    310    /// Returns the proving request.
    311    pub fn request(&self) -> &ProveRequest {
    312        &self.state.request
    313    }
    314
    315    /// Accepts the proving request.
    316    pub async fn accept(mut self) -> Result<(VerifierOutput, Verifier<state::Committed>)> {
    317        let mut ctx = self
    318            .ctx
    319            .take()
    320            .ok_or_else(|| Error::internal().with_msg("verification context was dropped"))?;
    321        let state::Verify {
    322            mut vm,
    323            keys,
    324            tls_transcript,
    325            request,
    326            handshake,
    327            transcript,
    328        } = self.state;
    329
    330        ctx.io_mut().send(Response::ok()).await.map_err(|e| {
    331            Error::io()
    332                .with_msg("verification failed to send acceptance")
    333                .with_source(e)
    334        })?;
    335
    336        let cert_verifier = ServerCertVerifier::new(self.config.root_store()).map_err(|e| {
    337            Error::config()
    338                .with_msg("failed to create certificate verifier")
    339                .with_source(e)
    340        })?;
    341
    342        let output = verify::verify(
    343            &mut ctx,
    344            &mut vm,
    345            &keys,
    346            &cert_verifier,
    347            &tls_transcript,
    348            request,
    349            handshake,
    350            transcript,
    351        )
    352        .await?;
    353
    354        Ok((
    355            output,
    356            Verifier {
    357                config: self.config,
    358                span: self.span,
    359                ctx: Some(ctx),
    360                state: state::Committed {
    361                    vm,
    362                    keys,
    363                    tls_transcript,
    364                },
    365            },
    366        ))
    367    }
    368
    369    /// Rejects the proving request.
    370    pub async fn reject(mut self, msg: Option<&str>) -> Result<Verifier<state::Committed>> {
    371        let mut ctx = self
    372            .ctx
    373            .take()
    374            .ok_or_else(|| Error::internal().with_msg("verification context was dropped"))?;
    375        let state::Verify {
    376            vm,
    377            keys,
    378            tls_transcript,
    379            ..
    380        } = self.state;
    381
    382        ctx.io_mut().send(Response::err(msg)).await.map_err(|e| {
    383            Error::io()
    384                .with_msg("verification failed to send rejection")
    385                .with_source(e)
    386        })?;
    387
    388        Ok(Verifier {
    389            config: self.config,
    390            span: self.span,
    391            ctx: Some(ctx),
    392            state: state::Committed {
    393                vm,
    394                keys,
    395                tls_transcript,
    396            },
    397        })
    398    }
    399}