]> git.ipfire.org Git - thirdparty/openssl.git/blob - util/perl/TLSProxy/ServerHello.pm
Update ServerHello to new draft-22 format
[thirdparty/openssl.git] / util / perl / TLSProxy / ServerHello.pm
1 # Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
2 #
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
7
8 use strict;
9
10 package TLSProxy::ServerHello;
11
12 use vars '@ISA';
13 push @ISA, 'TLSProxy::Message';
14
15 sub new
16 {
17 my $class = shift;
18 my ($server,
19 $data,
20 $records,
21 $startoffset,
22 $message_frag_lens) = @_;
23
24 my $self = $class->SUPER::new(
25 $server,
26 TLSProxy::Message::MT_SERVER_HELLO,
27 $data,
28 $records,
29 $startoffset,
30 $message_frag_lens);
31
32 $self->{server_version} = 0;
33 $self->{random} = [];
34 $self->{session_id_len} = 0;
35 $self->{session} = "";
36 $self->{ciphersuite} = 0;
37 $self->{comp_meth} = 0;
38 $self->{extension_data} = "";
39
40 return $self;
41 }
42
43 sub parse
44 {
45 my $self = shift;
46 my $ptr = 2;
47 my ($server_version) = unpack('n', $self->data);
48
49 my $random = substr($self->data, $ptr, 32);
50 $ptr += 32;
51 my $session_id_len = 0;
52 my $session = "";
53 $session_id_len = unpack('C', substr($self->data, $ptr));
54 $ptr++;
55 $session = substr($self->data, $ptr, $session_id_len);
56 $ptr += $session_id_len;
57
58 my $ciphersuite = unpack('n', substr($self->data, $ptr));
59 $ptr += 2;
60 my $comp_meth = 0;
61 $comp_meth = unpack('C', substr($self->data, $ptr));
62 $ptr++;
63
64 my $extensions_len = unpack('n', substr($self->data, $ptr));
65 if (!defined $extensions_len) {
66 $extensions_len = 0;
67 } else {
68 $ptr += 2;
69 }
70 #For now we just deal with this as a block of data. In the future we will
71 #want to parse this
72 my $extension_data;
73 if ($extensions_len != 0) {
74 $extension_data = substr($self->data, $ptr);
75
76 if (length($extension_data) != $extensions_len) {
77 die "Invalid extension length\n";
78 }
79 } else {
80 if (length($self->data) != $ptr) {
81 die "Invalid extension length\n";
82 }
83 $extension_data = "";
84 }
85 my %extensions = ();
86 while (length($extension_data) >= 4) {
87 my ($type, $size) = unpack("nn", $extension_data);
88 my $extdata = substr($extension_data, 4, $size);
89 $extension_data = substr($extension_data, 4 + $size);
90 $extensions{$type} = $extdata;
91 if ($type == TLSProxy::Message::EXT_SUPPORTED_VERSIONS) {
92 $server_version = unpack('n', $extdata);
93 }
94 }
95
96 # TODO(TLS1.3): Replace this reference to draft version before release
97 if ($server_version == TLSProxy::Record::VERS_TLS_1_3_DRAFT) {
98 $server_version = TLSProxy::Record::VERS_TLS_1_3;
99 TLSProxy::Proxy->is_tls13(1);
100 }
101
102 $self->server_version($server_version);
103 $self->random($random);
104 $self->session_id_len($session_id_len);
105 $self->session($session);
106 $self->ciphersuite($ciphersuite);
107 TLSProxy::Proxy->ciphersuite($ciphersuite);
108 $self->comp_meth($comp_meth);
109 $self->extension_data(\%extensions);
110
111 $self->process_data();
112
113 if (TLSProxy::Proxy->is_tls13()) {
114 TLSProxy::Record->server_encrypting(1);
115 TLSProxy::Record->client_encrypting(1);
116 }
117
118 print " Server Version:".$server_version."\n";
119 print " Session ID Len:".$session_id_len."\n";
120 print " Ciphersuite:".$ciphersuite."\n";
121 print " Compression Method:".$comp_meth."\n";
122 print " Extensions Len:".$extensions_len."\n";
123 }
124
125 #Perform any actions necessary based on the data we've seen
126 sub process_data
127 {
128 my $self = shift;
129
130 TLSProxy::Message->ciphersuite($self->ciphersuite);
131 }
132
133 #Reconstruct the on-the-wire message data following changes
134 sub set_message_contents
135 {
136 my $self = shift;
137 my $data;
138 my $extensions = "";
139
140 $data = pack('n', $self->server_version);
141 $data .= $self->random;
142 $data .= pack('C', $self->session_id_len);
143 $data .= $self->session;
144 $data .= pack('n', $self->ciphersuite);
145 $data .= pack('C', $self->comp_meth);
146
147 foreach my $key (keys %{$self->extension_data}) {
148 my $extdata = ${$self->extension_data}{$key};
149 $extensions .= pack("n", $key);
150 $extensions .= pack("n", length($extdata));
151 $extensions .= $extdata;
152 if ($key == TLSProxy::Message::EXT_DUPLICATE_EXTENSION) {
153 $extensions .= pack("n", $key);
154 $extensions .= pack("n", length($extdata));
155 $extensions .= $extdata;
156 }
157 }
158
159 $data .= pack('n', length($extensions));
160 $data .= $extensions;
161 $self->data($data);
162 }
163
164 #Read/write accessors
165 sub server_version
166 {
167 my $self = shift;
168 if (@_) {
169 $self->{server_version} = shift;
170 }
171 return $self->{server_version};
172 }
173 sub random
174 {
175 my $self = shift;
176 if (@_) {
177 $self->{random} = shift;
178 }
179 return $self->{random};
180 }
181 sub session_id_len
182 {
183 my $self = shift;
184 if (@_) {
185 $self->{session_id_len} = shift;
186 }
187 return $self->{session_id_len};
188 }
189 sub session
190 {
191 my $self = shift;
192 if (@_) {
193 $self->{session} = shift;
194 }
195 return $self->{session};
196 }
197 sub ciphersuite
198 {
199 my $self = shift;
200 if (@_) {
201 $self->{ciphersuite} = shift;
202 }
203 return $self->{ciphersuite};
204 }
205 sub comp_meth
206 {
207 my $self = shift;
208 if (@_) {
209 $self->{comp_meth} = shift;
210 }
211 return $self->{comp_meth};
212 }
213 sub extension_data
214 {
215 my $self = shift;
216 if (@_) {
217 $self->{extension_data} = shift;
218 }
219 return $self->{extension_data};
220 }
221 sub set_extension
222 {
223 my ($self, $ext_type, $ext_data) = @_;
224 $self->{extension_data}{$ext_type} = $ext_data;
225 }
226 sub delete_extension
227 {
228 my ($self, $ext_type) = @_;
229 delete $self->{extension_data}{$ext_type};
230 }
231 1;