]> git.ipfire.org Git - thirdparty/openssl.git/blame - util/perl/TLSProxy/Record.pm
Update copyright year
[thirdparty/openssl.git] / util / perl / TLSProxy / Record.pm
CommitLineData
6738bf14 1# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
631c1206 2#
ac3d0e13
RS
3# Licensed under the OpenSSL license (the "License"). You may not use
4# this file except in compliance with the License. You can obtain a copy
5# in the file LICENSE in the source distribution or at
6# https://www.openssl.org/source/license.html
631c1206
MC
7
8use strict;
9
10use TLSProxy::Proxy;
11
12package TLSProxy::Record;
13
9970290e
MC
14my $server_encrypting = 0;
15my $client_encrypting = 0;
631c1206
MC
16my $etm = 0;
17
18use constant TLS_RECORD_HEADER_LENGTH => 5;
19
20#Record types
21use constant {
22 RT_APPLICATION_DATA => 23,
23 RT_HANDSHAKE => 22,
24 RT_ALERT => 21,
1f3e70a4
MC
25 RT_CCS => 20,
26 RT_UNKNOWN => 100
631c1206
MC
27};
28
29my %record_type = (
30 RT_APPLICATION_DATA, "APPLICATION DATA",
31 RT_HANDSHAKE, "HANDSHAKE",
32 RT_ALERT, "ALERT",
1f3e70a4
MC
33 RT_CCS, "CCS",
34 RT_UNKNOWN, "UNKNOWN"
631c1206
MC
35);
36
37use constant {
e984b535 38 VERS_TLS_1_4 => 0x0305,
3b16c664 39 VERS_TLS_1_3_DRAFT => 0x7f17,
e984b535
MC
40 VERS_TLS_1_3 => 0x0304,
41 VERS_TLS_1_2 => 0x0303,
42 VERS_TLS_1_1 => 0x0302,
43 VERS_TLS_1_0 => 0x0301,
44 VERS_SSL_3_0 => 0x0300,
45 VERS_SSL_LT_3_0 => 0x02ff
631c1206
MC
46};
47
48my %tls_version = (
49 VERS_TLS_1_3, "TLS1.3",
50 VERS_TLS_1_2, "TLS1.2",
51 VERS_TLS_1_1, "TLS1.1",
52 VERS_TLS_1_0, "TLS1.0",
00bf5001
RL
53 VERS_SSL_3_0, "SSL3",
54 VERS_SSL_LT_3_0, "SSL<3"
631c1206
MC
55);
56
57#Class method to extract records from a packet of data
58sub get_records
59{
60 my $class = shift;
61 my $server = shift;
62 my $flight = shift;
63 my $packet = shift;
64 my @record_list = ();
65 my @message_list = ();
66 my $data;
67 my $content_type;
68 my $version;
69 my $len;
70 my $len_real;
71 my $decrypt_len;
72
73 my $recnum = 1;
74 while (length ($packet) > 0) {
75 print " Record $recnum";
76 if ($server) {
77 print " (server -> client)\n";
78 } else {
79 print " (client -> server)\n";
80 }
81 #Get the record header
82 if (length($packet) < TLS_RECORD_HEADER_LENGTH) {
83 print "Partial data : ".length($packet)." bytes\n";
84 $packet = "";
85 } else {
86 ($content_type, $version, $len) = unpack('CnnC*', $packet);
87 $data = substr($packet, 5, $len);
88
89 print " Content type: ".$record_type{$content_type}."\n";
90 print " Version: $tls_version{$version}\n";
91 print " Length: $len";
92 if ($len == length($data)) {
93 print "\n";
94 $decrypt_len = $len_real = $len;
95 } else {
96 print " (expected), ".length($data)." (actual)\n";
97 $decrypt_len = $len_real = length($data);
98 }
99
100 my $record = TLSProxy::Record->new(
101 $flight,
102 $content_type,
103 $version,
104 $len,
a2a0c86b 105 0,
631c1206
MC
106 $len_real,
107 $decrypt_len,
108 substr($packet, TLS_RECORD_HEADER_LENGTH, $len_real),
109 substr($packet, TLS_RECORD_HEADER_LENGTH, $len_real)
110 );
111
be60b10a 112 if ($content_type != RT_CCS) {
4d02f870
MC
113 if (($server && $server_encrypting)
114 || (!$server && $client_encrypting)) {
115 if (!TLSProxy::Proxy->is_tls13() && $etm) {
116 $record->decryptETM();
117 } else {
118 $record->decrypt();
119 }
120 $record->encrypted(1);
e60ce9c4 121
be60b10a
MC
122 if (TLSProxy::Proxy->is_tls13()) {
123 print " Inner content type: "
124 .$record_type{$record->content_type()}."\n";
125 }
4d02f870 126 }
631c1206
MC
127 }
128
129 push @record_list, $record;
130
131 #Now figure out what messages are contained within this record
132 my @messages = TLSProxy::Message->get_messages($server, $record);
133 push @message_list, @messages;
134
135 $packet = substr($packet, TLS_RECORD_HEADER_LENGTH + $len_real);
136 $recnum++;
137 }
138 }
139
140 return (\@record_list, \@message_list);
141}
142
143sub clear
144{
9970290e
MC
145 $server_encrypting = 0;
146 $client_encrypting = 0;
631c1206
MC
147}
148
149#Class level accessors
9970290e 150sub server_encrypting
631c1206
MC
151{
152 my $class = shift;
153 if (@_) {
9970290e 154 $server_encrypting = shift;
631c1206 155 }
9970290e 156 return $server_encrypting;
631c1206 157}
9970290e 158sub client_encrypting
631c1206
MC
159{
160 my $class = shift;
161 if (@_) {
9970290e 162 $client_encrypting= shift;
631c1206 163 }
9970290e 164 return $client_encrypting;
631c1206
MC
165}
166#Enable/Disable Encrypt-then-MAC
167sub etm
168{
169 my $class = shift;
170 if (@_) {
171 $etm = shift;
172 }
173 return $etm;
174}
175
176sub new
177{
178 my $class = shift;
179 my ($flight,
180 $content_type,
181 $version,
182 $len,
a2a0c86b 183 $sslv2,
631c1206
MC
184 $len_real,
185 $decrypt_len,
186 $data,
187 $decrypt_data) = @_;
188
189 my $self = {
190 flight => $flight,
191 content_type => $content_type,
192 version => $version,
193 len => $len,
a2a0c86b 194 sslv2 => $sslv2,
631c1206
MC
195 len_real => $len_real,
196 decrypt_len => $decrypt_len,
197 data => $data,
198 decrypt_data => $decrypt_data,
e60ce9c4 199 orig_decrypt_data => $decrypt_data,
b4c6e37e
MC
200 encrypted => 0,
201 outer_content_type => RT_APPLICATION_DATA
631c1206
MC
202 };
203
204 return bless $self, $class;
205}
206
207#Decrypt using encrypt-then-MAC
208sub decryptETM
209{
210 my ($self) = shift;
211
212 my $data = $self->data;
213
214 if($self->version >= VERS_TLS_1_1()) {
215 #TLS1.1+ has an explicit IV. Throw it away
216 $data = substr($data, 16);
217 }
218
219 #Throw away the MAC (assumes MAC is 20 bytes for now. FIXME)
220 $data = substr($data, 0, length($data) - 20);
221
222 #Find out what the padding byte is
223 my $padval = unpack("C", substr($data, length($data) - 1));
224
225 #Throw away the padding
226 $data = substr($data, 0, length($data) - ($padval + 1));
227
228 $self->decrypt_data($data);
229 $self->decrypt_len(length($data));
230
231 return $data;
232}
233
234#Standard decrypt
235sub decrypt()
236{
237 my ($self) = shift;
837e591d 238 my $mactaglen = 20;
631c1206
MC
239 my $data = $self->data;
240
837e591d 241 #Throw away any IVs
20b65c7b
MC
242 if (TLSProxy::Proxy->is_tls13()) {
243 #A TLS1.3 client, when processing the server's initial flight, could
244 #respond with either an encrypted or an unencrypted alert.
245 if ($self->content_type() == RT_ALERT) {
246 #TODO(TLS1.3): Eventually it is sufficient just to check the record
247 #content type. If an alert is encrypted it will have a record
248 #content type of application data. However we haven't done the
249 #record layer changes yet, so it's a bit more complicated. For now
250 #we will additionally check if the data length is 2 (1 byte for
251 #alert level, 1 byte for alert description). If it is, then this is
69687aa8 252 #an unencrypted alert, so don't try to decrypt
20b65c7b
MC
253 return $data if (length($data) == 2);
254 }
837e591d
MC
255 $mactaglen = 16;
256 } elsif ($self->version >= VERS_TLS_1_1()) {
257 #16 bytes for a standard IV
631c1206 258 $data = substr($data, 16);
631c1206 259
837e591d
MC
260 #Find out what the padding byte is
261 my $padval = unpack("C", substr($data, length($data) - 1));
631c1206 262
837e591d
MC
263 #Throw away the padding
264 $data = substr($data, 0, length($data) - ($padval + 1));
265 }
631c1206 266
837e591d
MC
267 #Throw away the MAC or TAG
268 $data = substr($data, 0, length($data) - $mactaglen);
631c1206 269
e60ce9c4
MC
270 if (TLSProxy::Proxy->is_tls13()) {
271 #Get the content type
272 my $content_type = unpack("C", substr($data, length($data) - 1));
273 $self->content_type($content_type);
274 $data = substr($data, 0, length($data) - 1);
275 }
276
631c1206
MC
277 $self->decrypt_data($data);
278 $self->decrypt_len(length($data));
279
280 return $data;
281}
282
283#Reconstruct the on-the-wire record representation
284sub reconstruct_record
285{
286 my $self = shift;
e60ce9c4 287 my $server = shift;
631c1206 288 my $data;
e60ce9c4 289 my $tls13_enc = 0;
631c1206 290
a2a0c86b
MC
291 if ($self->sslv2) {
292 $data = pack('n', $self->len | 0x8000);
293 } else {
e60ce9c4 294 if (TLSProxy::Proxy->is_tls13() && $self->encrypted) {
b4c6e37e 295 $data = pack('Cnn', $self->outer_content_type, $self->version,
e60ce9c4
MC
296 $self->len + 1);
297 $tls13_enc = 1;
298 } else {
299 $data = pack('Cnn', $self->content_type, $self->version,
300 $self->len);
301 }
302
a2a0c86b 303 }
631c1206
MC
304 $data .= $self->data;
305
e60ce9c4
MC
306 if ($tls13_enc) {
307 $data .= pack('C', $self->content_type);
308 }
309
631c1206
MC
310 return $data;
311}
312
313#Read only accessors
314sub flight
315{
316 my $self = shift;
317 return $self->{flight};
318}
a2a0c86b
MC
319sub sslv2
320{
321 my $self = shift;
322 return $self->{sslv2};
323}
631c1206
MC
324sub len_real
325{
326 my $self = shift;
327 return $self->{len_real};
328}
329sub orig_decrypt_data
330{
331 my $self = shift;
332 return $self->{orig_decrypt_data};
333}
334
335#Read/write accessors
336sub decrypt_len
337{
338 my $self = shift;
339 if (@_) {
340 $self->{decrypt_len} = shift;
341 }
342 return $self->{decrypt_len};
343}
344sub data
345{
346 my $self = shift;
347 if (@_) {
348 $self->{data} = shift;
349 }
350 return $self->{data};
351}
352sub decrypt_data
353{
354 my $self = shift;
355 if (@_) {
356 $self->{decrypt_data} = shift;
357 }
358 return $self->{decrypt_data};
359}
360sub len
361{
362 my $self = shift;
363 if (@_) {
364 $self->{len} = shift;
365 }
366 return $self->{len};
367}
8e47ee18
MC
368sub version
369{
370 my $self = shift;
371 if (@_) {
372 $self->{version} = shift;
373 }
374 return $self->{version};
375}
e60ce9c4
MC
376sub content_type
377{
378 my $self = shift;
379 if (@_) {
380 $self->{content_type} = shift;
381 }
382 return $self->{content_type};
383}
384sub encrypted
385{
386 my $self = shift;
387 if (@_) {
388 $self->{encrypted} = shift;
389 }
390 return $self->{encrypted};
391}
b4c6e37e
MC
392sub outer_content_type
393{
394 my $self = shift;
395 if (@_) {
396 $self->{outer_content_type} = shift;
397 }
398 return $self->{outer_content_type};
399}
631c1206 4001;