xref: /netbsd-src/crypto/external/bsd/openssl.old/dist/util/perl/TLSProxy/ClientHello.pm (revision 4724848cf0da353df257f730694b7882798e5daf)
1*4724848cSchristos# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
2*4724848cSchristos#
3*4724848cSchristos# Licensed under the OpenSSL license (the "License").  You may not use
4*4724848cSchristos# this file except in compliance with the License.  You can obtain a copy
5*4724848cSchristos# in the file LICENSE in the source distribution or at
6*4724848cSchristos# https://www.openssl.org/source/license.html
7*4724848cSchristos
8*4724848cSchristosuse strict;
9*4724848cSchristos
10*4724848cSchristospackage TLSProxy::ClientHello;
11*4724848cSchristos
12*4724848cSchristosuse vars '@ISA';
13*4724848cSchristospush @ISA, 'TLSProxy::Message';
14*4724848cSchristos
15*4724848cSchristossub new
16*4724848cSchristos{
17*4724848cSchristos    my $class = shift;
18*4724848cSchristos    my ($server,
19*4724848cSchristos        $data,
20*4724848cSchristos        $records,
21*4724848cSchristos        $startoffset,
22*4724848cSchristos        $message_frag_lens) = @_;
23*4724848cSchristos
24*4724848cSchristos    my $self = $class->SUPER::new(
25*4724848cSchristos        $server,
26*4724848cSchristos        1,
27*4724848cSchristos        $data,
28*4724848cSchristos        $records,
29*4724848cSchristos        $startoffset,
30*4724848cSchristos        $message_frag_lens);
31*4724848cSchristos
32*4724848cSchristos    $self->{client_version} = 0;
33*4724848cSchristos    $self->{random} = [];
34*4724848cSchristos    $self->{session_id_len} = 0;
35*4724848cSchristos    $self->{session} = "";
36*4724848cSchristos    $self->{ciphersuite_len} = 0;
37*4724848cSchristos    $self->{ciphersuites} = [];
38*4724848cSchristos    $self->{comp_meth_len} = 0;
39*4724848cSchristos    $self->{comp_meths} = [];
40*4724848cSchristos    $self->{extensions_len} = 0;
41*4724848cSchristos    $self->{extension_data} = "";
42*4724848cSchristos
43*4724848cSchristos    return $self;
44*4724848cSchristos}
45*4724848cSchristos
46*4724848cSchristossub parse
47*4724848cSchristos{
48*4724848cSchristos    my $self = shift;
49*4724848cSchristos    my $ptr = 2;
50*4724848cSchristos    my ($client_version) = unpack('n', $self->data);
51*4724848cSchristos    my $random = substr($self->data, $ptr, 32);
52*4724848cSchristos    $ptr += 32;
53*4724848cSchristos    my $session_id_len = unpack('C', substr($self->data, $ptr));
54*4724848cSchristos    $ptr++;
55*4724848cSchristos    my $session = substr($self->data, $ptr, $session_id_len);
56*4724848cSchristos    $ptr += $session_id_len;
57*4724848cSchristos    my $ciphersuite_len = unpack('n', substr($self->data, $ptr));
58*4724848cSchristos    $ptr += 2;
59*4724848cSchristos    my @ciphersuites = unpack('n*', substr($self->data, $ptr,
60*4724848cSchristos                                           $ciphersuite_len));
61*4724848cSchristos    $ptr += $ciphersuite_len;
62*4724848cSchristos    my $comp_meth_len = unpack('C', substr($self->data, $ptr));
63*4724848cSchristos    $ptr++;
64*4724848cSchristos    my @comp_meths = unpack('C*', substr($self->data, $ptr, $comp_meth_len));
65*4724848cSchristos    $ptr += $comp_meth_len;
66*4724848cSchristos    my $extensions_len = unpack('n', substr($self->data, $ptr));
67*4724848cSchristos    $ptr += 2;
68*4724848cSchristos    #For now we just deal with this as a block of data. In the future we will
69*4724848cSchristos    #want to parse this
70*4724848cSchristos    my $extension_data = substr($self->data, $ptr);
71*4724848cSchristos
72*4724848cSchristos    if (length($extension_data) != $extensions_len) {
73*4724848cSchristos        die "Invalid extension length\n";
74*4724848cSchristos    }
75*4724848cSchristos    my %extensions = ();
76*4724848cSchristos    while (length($extension_data) >= 4) {
77*4724848cSchristos        my ($type, $size) = unpack("nn", $extension_data);
78*4724848cSchristos        my $extdata = substr($extension_data, 4, $size);
79*4724848cSchristos        $extension_data = substr($extension_data, 4 + $size);
80*4724848cSchristos        $extensions{$type} = $extdata;
81*4724848cSchristos    }
82*4724848cSchristos
83*4724848cSchristos    $self->client_version($client_version);
84*4724848cSchristos    $self->random($random);
85*4724848cSchristos    $self->session_id_len($session_id_len);
86*4724848cSchristos    $self->session($session);
87*4724848cSchristos    $self->ciphersuite_len($ciphersuite_len);
88*4724848cSchristos    $self->ciphersuites(\@ciphersuites);
89*4724848cSchristos    $self->comp_meth_len($comp_meth_len);
90*4724848cSchristos    $self->comp_meths(\@comp_meths);
91*4724848cSchristos    $self->extensions_len($extensions_len);
92*4724848cSchristos    $self->extension_data(\%extensions);
93*4724848cSchristos
94*4724848cSchristos    $self->process_extensions();
95*4724848cSchristos
96*4724848cSchristos    print "    Client Version:".$client_version."\n";
97*4724848cSchristos    print "    Session ID Len:".$session_id_len."\n";
98*4724848cSchristos    print "    Ciphersuite len:".$ciphersuite_len."\n";
99*4724848cSchristos    print "    Compression Method Len:".$comp_meth_len."\n";
100*4724848cSchristos    print "    Extensions Len:".$extensions_len."\n";
101*4724848cSchristos}
102*4724848cSchristos
103*4724848cSchristos#Perform any actions necessary based on the extensions we've seen
104*4724848cSchristossub process_extensions
105*4724848cSchristos{
106*4724848cSchristos    my $self = shift;
107*4724848cSchristos    my %extensions = %{$self->extension_data};
108*4724848cSchristos
109*4724848cSchristos    #Clear any state from a previous run
110*4724848cSchristos    TLSProxy::Record->etm(0);
111*4724848cSchristos
112*4724848cSchristos    if (exists $extensions{TLSProxy::Message::EXT_ENCRYPT_THEN_MAC}) {
113*4724848cSchristos        TLSProxy::Record->etm(1);
114*4724848cSchristos    }
115*4724848cSchristos}
116*4724848cSchristos
117*4724848cSchristossub extension_contents
118*4724848cSchristos{
119*4724848cSchristos    my $self = shift;
120*4724848cSchristos    my $key = shift;
121*4724848cSchristos    my $extension = "";
122*4724848cSchristos
123*4724848cSchristos    my $extdata = ${$self->extension_data}{$key};
124*4724848cSchristos    $extension .= pack("n", $key);
125*4724848cSchristos    $extension .= pack("n", length($extdata));
126*4724848cSchristos    $extension .= $extdata;
127*4724848cSchristos    return $extension;
128*4724848cSchristos}
129*4724848cSchristos
130*4724848cSchristos#Reconstruct the on-the-wire message data following changes
131*4724848cSchristossub set_message_contents
132*4724848cSchristos{
133*4724848cSchristos    my $self = shift;
134*4724848cSchristos    my $data;
135*4724848cSchristos    my $extensions = "";
136*4724848cSchristos
137*4724848cSchristos    $data = pack('n', $self->client_version);
138*4724848cSchristos    $data .= $self->random;
139*4724848cSchristos    $data .= pack('C', $self->session_id_len);
140*4724848cSchristos    $data .= $self->session;
141*4724848cSchristos    $data .= pack('n', $self->ciphersuite_len);
142*4724848cSchristos    $data .= pack("n*", @{$self->ciphersuites});
143*4724848cSchristos    $data .= pack('C', $self->comp_meth_len);
144*4724848cSchristos    $data .= pack("C*", @{$self->comp_meths});
145*4724848cSchristos
146*4724848cSchristos    foreach my $key (keys %{$self->extension_data}) {
147*4724848cSchristos        next if ($key == TLSProxy::Message::EXT_PSK);
148*4724848cSchristos        $extensions .= $self->extension_contents($key);
149*4724848cSchristos        #Add extension twice if we are duplicating that extension
150*4724848cSchristos        $extensions .= $self->extension_contents($key) if ($key == $self->dupext);
151*4724848cSchristos    }
152*4724848cSchristos    #PSK extension always goes last...
153*4724848cSchristos    if (defined ${$self->extension_data}{TLSProxy::Message::EXT_PSK}) {
154*4724848cSchristos        $extensions .= $self->extension_contents(TLSProxy::Message::EXT_PSK);
155*4724848cSchristos    }
156*4724848cSchristos    #unless we have EXT_FORCE_LAST
157*4724848cSchristos    if (defined ${$self->extension_data}{TLSProxy::Message::EXT_FORCE_LAST}) {
158*4724848cSchristos        $extensions .= $self->extension_contents(TLSProxy::Message::EXT_FORCE_LAST);
159*4724848cSchristos    }
160*4724848cSchristos
161*4724848cSchristos    $data .= pack('n', length($extensions));
162*4724848cSchristos    $data .= $extensions;
163*4724848cSchristos
164*4724848cSchristos    $self->data($data);
165*4724848cSchristos}
166*4724848cSchristos
167*4724848cSchristos#Read/write accessors
168*4724848cSchristossub client_version
169*4724848cSchristos{
170*4724848cSchristos    my $self = shift;
171*4724848cSchristos    if (@_) {
172*4724848cSchristos      $self->{client_version} = shift;
173*4724848cSchristos    }
174*4724848cSchristos    return $self->{client_version};
175*4724848cSchristos}
176*4724848cSchristossub random
177*4724848cSchristos{
178*4724848cSchristos    my $self = shift;
179*4724848cSchristos    if (@_) {
180*4724848cSchristos      $self->{random} = shift;
181*4724848cSchristos    }
182*4724848cSchristos    return $self->{random};
183*4724848cSchristos}
184*4724848cSchristossub session_id_len
185*4724848cSchristos{
186*4724848cSchristos    my $self = shift;
187*4724848cSchristos    if (@_) {
188*4724848cSchristos      $self->{session_id_len} = shift;
189*4724848cSchristos    }
190*4724848cSchristos    return $self->{session_id_len};
191*4724848cSchristos}
192*4724848cSchristossub session
193*4724848cSchristos{
194*4724848cSchristos    my $self = shift;
195*4724848cSchristos    if (@_) {
196*4724848cSchristos      $self->{session} = shift;
197*4724848cSchristos    }
198*4724848cSchristos    return $self->{session};
199*4724848cSchristos}
200*4724848cSchristossub ciphersuite_len
201*4724848cSchristos{
202*4724848cSchristos    my $self = shift;
203*4724848cSchristos    if (@_) {
204*4724848cSchristos      $self->{ciphersuite_len} = shift;
205*4724848cSchristos    }
206*4724848cSchristos    return $self->{ciphersuite_len};
207*4724848cSchristos}
208*4724848cSchristossub ciphersuites
209*4724848cSchristos{
210*4724848cSchristos    my $self = shift;
211*4724848cSchristos    if (@_) {
212*4724848cSchristos      $self->{ciphersuites} = shift;
213*4724848cSchristos    }
214*4724848cSchristos    return $self->{ciphersuites};
215*4724848cSchristos}
216*4724848cSchristossub comp_meth_len
217*4724848cSchristos{
218*4724848cSchristos    my $self = shift;
219*4724848cSchristos    if (@_) {
220*4724848cSchristos      $self->{comp_meth_len} = shift;
221*4724848cSchristos    }
222*4724848cSchristos    return $self->{comp_meth_len};
223*4724848cSchristos}
224*4724848cSchristossub comp_meths
225*4724848cSchristos{
226*4724848cSchristos    my $self = shift;
227*4724848cSchristos    if (@_) {
228*4724848cSchristos      $self->{comp_meths} = shift;
229*4724848cSchristos    }
230*4724848cSchristos    return $self->{comp_meths};
231*4724848cSchristos}
232*4724848cSchristossub extensions_len
233*4724848cSchristos{
234*4724848cSchristos    my $self = shift;
235*4724848cSchristos    if (@_) {
236*4724848cSchristos      $self->{extensions_len} = shift;
237*4724848cSchristos    }
238*4724848cSchristos    return $self->{extensions_len};
239*4724848cSchristos}
240*4724848cSchristossub extension_data
241*4724848cSchristos{
242*4724848cSchristos    my $self = shift;
243*4724848cSchristos    if (@_) {
244*4724848cSchristos      $self->{extension_data} = shift;
245*4724848cSchristos    }
246*4724848cSchristos    return $self->{extension_data};
247*4724848cSchristos}
248*4724848cSchristossub set_extension
249*4724848cSchristos{
250*4724848cSchristos    my ($self, $ext_type, $ext_data) = @_;
251*4724848cSchristos    $self->{extension_data}{$ext_type} = $ext_data;
252*4724848cSchristos}
253*4724848cSchristossub delete_extension
254*4724848cSchristos{
255*4724848cSchristos    my ($self, $ext_type) = @_;
256*4724848cSchristos    delete $self->{extension_data}{$ext_type};
257*4724848cSchristos}
258*4724848cSchristos1;
259