1use aead::Payload as AeadPayload;
4use aes_gcm::{aead::Aead, Aes128Gcm, NewAead};
5use generic_array::GenericArray;
6use rand::{rngs::StdRng, Rng, SeedableRng};
7use tls_core::msgs::{
8 base::Payload,
9 codec::Codec,
10 enums::{ContentType, HandshakeType, ProtocolVersion},
11 handshake::{HandshakeMessagePayload, HandshakePayload},
12 message::{OpaqueMessage, PlainMessage},
13};
14
15use crate::{
16 connection::{TranscriptLength, VerifyData},
17 fixtures::ConnectionFixture,
18 transcript::{Record, TlsTranscript},
19};
20
21pub const KEY: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
23
24pub const IV: [u8; 4] = [1, 3, 3, 7];
26
27pub const RECORD_SIZE: usize = 512;
29
30pub fn transcript_fixture(sent: &[u8], recv: &[u8]) -> TlsTranscript {
32 TranscriptGenerator::new(KEY, IV).generate(sent, recv)
33}
34
35struct TranscriptGenerator {
36 key: [u8; 16],
37 iv: [u8; 4],
38}
39
40impl TranscriptGenerator {
41 fn new(key: [u8; 16], iv: [u8; 4]) -> Self {
42 Self { key, iv }
43 }
44
45 fn generate(&self, sent: &[u8], recv: &[u8]) -> TlsTranscript {
46 let mut rng = StdRng::from_seed([1; 32]);
47
48 let transcript_len = TranscriptLength {
49 sent: sent.len() as u32,
50 received: recv.len() as u32,
51 };
52 let tlsn = ConnectionFixture::tlsnotary(transcript_len);
53
54 let time = tlsn.connection_info.time;
55 let version = tlsn.connection_info.version;
56 let server_cert_chain = tlsn.server_cert_data.certs;
57 let server_signature = tlsn.server_cert_data.sig;
58 let cert_binding = tlsn.server_cert_data.binding;
59
60 let cf_vd: [u8; 12] = rng.random();
61 let sf_vd: [u8; 12] = rng.random();
62
63 let verify_data = VerifyData {
64 client_finished: cf_vd.to_vec(),
65 server_finished: sf_vd.to_vec(),
66 };
67
68 let sent = self.gen_records(cf_vd, sent);
69 let recv = self.gen_records(sf_vd, recv);
70
71 TlsTranscript::new(
72 time,
73 version,
74 Some(server_cert_chain),
75 Some(server_signature),
76 cert_binding,
77 verify_data,
78 sent,
79 recv,
80 )
81 .unwrap()
82 }
83
84 fn gen_records(&self, vd: [u8; 12], plaintext: &[u8]) -> Vec<Record> {
85 let mut records = Vec::new();
86
87 let handshake = self.gen_handshake(vd);
88 records.push(handshake);
89
90 for (seq, msg) in (1_u64..).zip(plaintext.chunks(RECORD_SIZE)) {
91 let record = self.gen_app_data(seq, msg);
92 records.push(record);
93 }
94
95 records
96 }
97
98 fn gen_app_data(&self, seq: u64, plaintext: &[u8]) -> Record {
99 assert!(
100 plaintext.len() <= 1 << 14,
101 "plaintext len per record must be smaller than 2^14 bytes"
102 );
103
104 let explicit_nonce: [u8; 8] = seq.to_be_bytes();
105 let msg = PlainMessage {
106 typ: ContentType::ApplicationData,
107 version: ProtocolVersion::TLSv1_2,
108 payload: Payload::new(plaintext),
109 };
110 let opaque = aes_gcm_encrypt(self.key, self.iv, seq, explicit_nonce, &msg);
111
112 let mut payload = opaque.payload.0;
113 let mut ciphertext = payload.split_off(8);
114 let tag = ciphertext.split_off(ciphertext.len() - 16);
115
116 Record {
117 seq,
118 typ: ContentType::ApplicationData,
119 plaintext: Some(plaintext.to_vec()),
120 explicit_nonce: explicit_nonce.to_vec(),
121 ciphertext,
122 tag: Some(tag),
123 }
124 }
125
126 fn gen_handshake(&self, vd: [u8; 12]) -> Record {
127 let seq = 0_u64;
128 let explicit_nonce = seq.to_be_bytes();
129
130 let mut plaintext = Vec::new();
131
132 let payload = Payload(vd.to_vec());
133 let hs_payload = HandshakePayload::Finished(payload);
134 let handshake_message = HandshakeMessagePayload {
135 typ: HandshakeType::Finished,
136 payload: hs_payload,
137 };
138 handshake_message.encode(&mut plaintext);
139
140 let msg = PlainMessage {
141 typ: ContentType::Handshake,
142 version: ProtocolVersion::TLSv1_2,
143 payload: Payload::new(plaintext.clone()),
144 };
145
146 let opaque = aes_gcm_encrypt(self.key, self.iv, seq, explicit_nonce, &msg);
147 let mut payload = opaque.payload.0;
148 let mut ciphertext = payload.split_off(8);
149 let tag = ciphertext.split_off(ciphertext.len() - 16);
150
151 Record {
152 seq,
153 typ: ContentType::Handshake,
154 plaintext: Some(plaintext),
155 explicit_nonce: explicit_nonce.to_vec(),
156 ciphertext,
157 tag: Some(tag),
158 }
159 }
160}
161
162fn aes_gcm_encrypt(
163 key: [u8; 16],
164 iv: [u8; 4],
165 seq: u64,
166 explicit_nonce: [u8; 8],
167 msg: &PlainMessage,
168) -> OpaqueMessage {
169 let mut aad = [0u8; 13];
170
171 aad[..8].copy_from_slice(&seq.to_be_bytes());
172 aad[8] = msg.typ.get_u8();
173 aad[9..11].copy_from_slice(&msg.version.get_u16().to_be_bytes());
174 aad[11..13].copy_from_slice(&(msg.payload.0.len() as u16).to_be_bytes());
175 let payload = AeadPayload {
176 msg: &msg.payload.0,
177 aad: &aad,
178 };
179
180 let mut nonce = [0u8; 12];
181 nonce[..4].copy_from_slice(&iv);
182 nonce[4..].copy_from_slice(&explicit_nonce);
183 let nonce = GenericArray::from_slice(&nonce);
184 let cipher = Aes128Gcm::new_from_slice(&key).unwrap();
185
186 let ciphertext = cipher.encrypt(nonce, payload).unwrap();
188
189 let mut nonce_ct_mac = vec![0u8; 0];
191 nonce_ct_mac.extend(explicit_nonce.iter());
192 nonce_ct_mac.extend(ciphertext.iter());
193
194 OpaqueMessage {
195 typ: msg.typ,
196 version: msg.version,
197 payload: Payload::new(nonce_ct_mac),
198 }
199}