tlsn_core/connection/
proof.rs

1//! Types for proving details of a connection.
2
3use serde::{Deserialize, Serialize};
4
5use crate::{
6    connection::{
7        commit::{ServerCertCommitment, ServerCertOpening},
8        CertificateVerificationError, ServerEphemKey, ServerName,
9    },
10    hash::{HashAlgorithmExt, HashProviderError},
11    CryptoProvider,
12};
13
14/// TLS server identity proof.
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct ServerIdentityProof {
17    name: ServerName,
18    opening: ServerCertOpening,
19}
20
21impl ServerIdentityProof {
22    pub(crate) fn new(name: ServerName, opening: ServerCertOpening) -> Self {
23        Self { name, opening }
24    }
25
26    /// Verifies the server identity proof.
27    ///
28    /// # Arguments
29    ///
30    /// * `provider` - The crypto provider to use for verification.
31    /// * `time` - The time of the connection.
32    /// * `server_ephemeral_key` - The server's ephemeral key.
33    /// * `commitment` - Commitment to the server certificate.
34    pub fn verify_with_provider(
35        self,
36        provider: &CryptoProvider,
37        time: u64,
38        server_ephemeral_key: &ServerEphemKey,
39        commitment: &ServerCertCommitment,
40    ) -> Result<ServerName, ServerIdentityProofError> {
41        let hasher = provider.hash.get(&commitment.0.alg)?;
42
43        if commitment.0.value != hasher.hash_separated(&self.opening) {
44            return Err(ServerIdentityProofError {
45                kind: ErrorKind::Commitment,
46                message: "certificate opening does not match commitment".to_string(),
47            });
48        }
49
50        // Verify certificate and identity.
51        self.opening.data().verify_with_provider(
52            provider,
53            time,
54            server_ephemeral_key,
55            &self.name,
56        )?;
57
58        Ok(self.name)
59    }
60}
61
62/// Error for [`ServerIdentityProof`].
63#[derive(Debug, thiserror::Error)]
64#[error("server identity proof error: {kind}: {message}")]
65pub struct ServerIdentityProofError {
66    kind: ErrorKind,
67    message: String,
68}
69
70impl From<HashProviderError> for ServerIdentityProofError {
71    fn from(err: HashProviderError) -> Self {
72        Self {
73            kind: ErrorKind::Provider,
74            message: err.to_string(),
75        }
76    }
77}
78
79impl From<CertificateVerificationError> for ServerIdentityProofError {
80    fn from(err: CertificateVerificationError) -> Self {
81        Self {
82            kind: ErrorKind::Certificate,
83            message: err.to_string(),
84        }
85    }
86}
87
88#[derive(Debug)]
89enum ErrorKind {
90    Provider,
91    Commitment,
92    Certificate,
93}
94
95impl std::fmt::Display for ErrorKind {
96    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97        match self {
98            ErrorKind::Provider => write!(f, "provider"),
99            ErrorKind::Commitment => write!(f, "commitment"),
100            ErrorKind::Certificate => write!(f, "certificate"),
101        }
102    }
103}