Fix the tests following the state machine changes for TLSv1.3
[oweals/openssl.git] / util / 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     my $random = substr($self->data, $ptr, 32);
49     $ptr += 32;
50     my $session_id_len = unpack('C', substr($self->data, $ptr));
51     $ptr++;
52     my $session = substr($self->data, $ptr, $session_id_len);
53     $ptr += $session_id_len;
54     my $ciphersuite = unpack('n', substr($self->data, $ptr));
55     $ptr += 2;
56     my $comp_meth = unpack('C', substr($self->data, $ptr));
57     $ptr++;
58     my $extensions_len = unpack('n', substr($self->data, $ptr));
59     if (!defined $extensions_len) {
60         $extensions_len = 0;
61     } else {
62         $ptr += 2;
63     }
64     #For now we just deal with this as a block of data. In the future we will
65     #want to parse this
66     my $extension_data;
67     if ($extensions_len != 0) {
68         $extension_data = substr($self->data, $ptr);
69     
70         if (length($extension_data) != $extensions_len) {
71             die "Invalid extension length\n";
72         }
73     } else {
74         if (length($self->data) != $ptr) {
75             die "Invalid extension length\n";
76         }
77         $extension_data = "";
78     }
79     my %extensions = ();
80     while (length($extension_data) >= 4) {
81         my ($type, $size) = unpack("nn", $extension_data);
82         my $extdata = substr($extension_data, 4, $size);
83         $extension_data = substr($extension_data, 4 + $size);
84         $extensions{$type} = $extdata;
85     }
86
87     $self->server_version($server_version);
88     $self->random($random);
89     $self->session_id_len($session_id_len);
90     $self->session($session);
91     $self->ciphersuite($ciphersuite);
92     $self->comp_meth($comp_meth);
93     $self->extension_data(\%extensions);
94
95     $self->process_data();
96
97     # TODO(TLS1.3): Replace this reference to draft version before release
98     if ($server_version == TLSProxy::Record::VERS_TLS_1_3_DRAFT) {
99         TLSProxy::Record->server_encrypting(1);
100         TLSProxy::Record->client_encrypting(1);
101     }
102
103     print "    Server Version:".$server_version."\n";
104     print "    Session ID Len:".$session_id_len."\n";
105     print "    Ciphersuite:".$ciphersuite."\n";
106     print "    Compression Method:".$comp_meth."\n";
107     print "    Extensions Len:".$extensions_len."\n";
108 }
109
110 #Perform any actions necessary based on the data we've seen
111 sub process_data
112 {
113     my $self = shift;
114
115     TLSProxy::Message->ciphersuite($self->ciphersuite);
116 }
117
118 #Reconstruct the on-the-wire message data following changes
119 sub set_message_contents
120 {
121     my $self = shift;
122     my $data;
123     my $extensions = "";
124
125     $data = pack('n', $self->server_version);
126     $data .= $self->random;
127     $data .= pack('C', $self->session_id_len);
128     $data .= $self->session;
129     $data .= pack('n', $self->ciphersuite);
130     $data .= pack('C', $self->comp_meth);
131
132     foreach my $key (keys %{$self->extension_data}) {
133         my $extdata = ${$self->extension_data}{$key};
134         $extensions .= pack("n", $key);
135         $extensions .= pack("n", length($extdata));
136         $extensions .= $extdata;
137         if ($key == TLSProxy::Message::EXT_DUPLICATE_EXTENSION) {
138           $extensions .= pack("n", $key);
139           $extensions .= pack("n", length($extdata));
140           $extensions .= $extdata;
141         }
142     }
143
144     $data .= pack('n', length($extensions));
145     $data .= $extensions;
146     $self->data($data);
147 }
148
149 #Read/write accessors
150 sub server_version
151 {
152     my $self = shift;
153     if (@_) {
154       $self->{client_version} = shift;
155     }
156     return $self->{client_version};
157 }
158 sub random
159 {
160     my $self = shift;
161     if (@_) {
162       $self->{random} = shift;
163     }
164     return $self->{random};
165 }
166 sub session_id_len
167 {
168     my $self = shift;
169     if (@_) {
170       $self->{session_id_len} = shift;
171     }
172     return $self->{session_id_len};
173 }
174 sub session
175 {
176     my $self = shift;
177     if (@_) {
178       $self->{session} = shift;
179     }
180     return $self->{session};
181 }
182 sub ciphersuite
183 {
184     my $self = shift;
185     if (@_) {
186       $self->{ciphersuite} = shift;
187     }
188     return $self->{ciphersuite};
189 }
190 sub comp_meth
191 {
192     my $self = shift;
193     if (@_) {
194       $self->{comp_meth} = shift;
195     }
196     return $self->{comp_meth};
197 }
198 sub extension_data
199 {
200     my $self = shift;
201     if (@_) {
202       $self->{extension_data} = shift;
203     }
204     return $self->{extension_data};
205 }
206 sub set_extension
207 {
208     my ($self, $ext_type, $ext_data) = @_;
209     $self->{extension_data}{$ext_type} = $ext_data;
210 }
211 sub delete_extension
212 {
213     my ($self, $ext_type) = @_;
214     delete $self->{extension_data}{$ext_type};
215 }
216 1;