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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//! Fixtures for testing

/// Certificate fixtures
pub mod cert;

use std::collections::HashMap;

use hex::FromHex;
use mpz_circuits::types::ValueType;
use mpz_core::{commit::HashCommit, hash::Hash, utils::blake3};
use mpz_garble_core::{ChaChaEncoder, Encoder};
use tls_core::{
    cert::ServerCertDetails,
    handshake::HandshakeData,
    ke::ServerKxDetails,
    key::{Certificate, PublicKey},
    msgs::{
        codec::Codec,
        enums::{NamedGroup, SignatureScheme},
        handshake::{DigitallySignedStruct, Random, ServerECDHParams},
    },
};

use p256::ecdsa::SigningKey;

use crate::{
    merkle::MerkleRoot,
    session::{HandshakeSummary, SessionHeader},
    EncodingProvider,
};

fn value_id(id: &str) -> u64 {
    let hash = blake3(id.as_bytes());
    u64::from_be_bytes(hash[..8].try_into().unwrap())
}

/// Returns a session header fixture using the given transcript lengths and merkle root.
///
/// # Arguments
///
/// * `root` - The merkle root of the transcript commitments.
/// * `sent_len` - The length of the sent transcript.
/// * `recv_len` - The length of the received transcript.
pub fn session_header(root: MerkleRoot, sent_len: usize, recv_len: usize) -> SessionHeader {
    SessionHeader::new(
        encoder_seed(),
        root,
        sent_len,
        recv_len,
        handshake_summary(),
    )
}

/// Returns an encoding provider fixture using the given transcripts.
pub fn encoding_provider(transcript_tx: &[u8], transcript_rx: &[u8]) -> EncodingProvider {
    let encoder = encoder();
    let mut active_encodings = HashMap::new();
    for (idx, byte) in transcript_tx.iter().enumerate() {
        let id = format!("tx/{idx}");
        let enc = encoder.encode_by_type(value_id(&id), &ValueType::U8);
        active_encodings.insert(id, enc.select(*byte).unwrap());
    }
    for (idx, byte) in transcript_rx.iter().enumerate() {
        let id = format!("rx/{idx}");
        let enc = encoder.encode_by_type(value_id(&id), &ValueType::U8);
        active_encodings.insert(id, enc.select(*byte).unwrap());
    }

    Box::new(move |ids: &[&str]| {
        ids.iter()
            .map(|id| active_encodings.get(*id).cloned())
            .collect()
    })
}

/// Returns a handshake summary fixture.
pub fn handshake_summary() -> HandshakeSummary {
    HandshakeSummary::new(1671637529, server_ephemeral_key(), handshake_commitment())
}

/// Returns a handshake commitment fixture.
pub fn handshake_commitment() -> Hash {
    let (_, hash) = handshake_data().hash_commit();
    hash
}

/// Returns a handshake data fixture.
pub fn handshake_data() -> HandshakeData {
    HandshakeData::new(
        server_cert_details(),
        server_kx_details(),
        client_random(),
        server_random(),
    )
}

/// Returns a server certificate details fixture.
pub fn server_cert_details() -> ServerCertDetails {
    ServerCertDetails::new(
        vec![
            Certificate(include_bytes!("testdata/key_exchange/tlsnotary.org/ee.der").to_vec()),
            Certificate(include_bytes!("testdata/key_exchange/tlsnotary.org/inter.der").to_vec()),
            Certificate(include_bytes!("testdata/key_exchange/tlsnotary.org/ca.der").to_vec()),
        ],
        vec![],
        None,
    )
}

/// Returns a server key exchange details fixture.
pub fn server_kx_details() -> ServerKxDetails {
    let mut params = Vec::new();
    let ecdh_params = ServerECDHParams::new(NamedGroup::secp256r1, &server_ephemeral_key().key);
    ecdh_params.encode(&mut params);

    ServerKxDetails::new(
        params,
        DigitallySignedStruct::new(
            SignatureScheme::RSA_PKCS1_SHA256,
            Vec::<u8>::from_hex(include_bytes!(
                "testdata/key_exchange/tlsnotary.org/signature"
            ))
            .unwrap(),
        ),
    )
}

/// Returns a client random fixture.
pub fn client_random() -> Random {
    Random(
        <[u8; 32]>::from_hex(include_bytes!(
            "testdata/key_exchange/tlsnotary.org/client_random"
        ))
        .unwrap(),
    )
}

/// Returns a server random fixture.
pub fn server_random() -> Random {
    Random(
        <[u8; 32]>::from_hex(include_bytes!(
            "testdata/key_exchange/tlsnotary.org/server_random"
        ))
        .unwrap(),
    )
}

/// Returns an encoder fixture.
pub fn encoder() -> ChaChaEncoder {
    ChaChaEncoder::new(encoder_seed())
}

/// Returns an encoder seed fixture.
pub fn encoder_seed() -> [u8; 32] {
    [0u8; 32]
}

/// Returns a server ephemeral key fixture.
pub fn server_ephemeral_key() -> PublicKey {
    PublicKey::new(
        NamedGroup::secp256r1,
        &Vec::<u8>::from_hex(include_bytes!("testdata/key_exchange/tlsnotary.org/pubkey")).unwrap(),
    )
}

/// Returns a notary signing key fixture.
pub fn notary_signing_key() -> SigningKey {
    SigningKey::from_slice(&[1; 32]).unwrap()
}