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