xref: /netbsd-src/crypto/external/bsd/openssl.old/dist/util/perl/TLSProxy/ServerHello.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::ServerHello;
11*4724848cSchristos
12*4724848cSchristosuse vars '@ISA';
13*4724848cSchristospush @ISA, 'TLSProxy::Message';
14*4724848cSchristos
15*4724848cSchristosmy $hrrrandom = pack("C*", 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, 0xBE,
16*4724848cSchristos                           0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, 0xC2, 0xA2,
17*4724848cSchristos                           0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, 0x07, 0x9E, 0x09,
18*4724848cSchristos                           0xE2, 0xC8, 0xA8, 0x33, 0x9C);
19*4724848cSchristos
20*4724848cSchristossub new
21*4724848cSchristos{
22*4724848cSchristos    my $class = shift;
23*4724848cSchristos    my ($server,
24*4724848cSchristos        $data,
25*4724848cSchristos        $records,
26*4724848cSchristos        $startoffset,
27*4724848cSchristos        $message_frag_lens) = @_;
28*4724848cSchristos
29*4724848cSchristos    my $self = $class->SUPER::new(
30*4724848cSchristos        $server,
31*4724848cSchristos        TLSProxy::Message::MT_SERVER_HELLO,
32*4724848cSchristos        $data,
33*4724848cSchristos        $records,
34*4724848cSchristos        $startoffset,
35*4724848cSchristos        $message_frag_lens);
36*4724848cSchristos
37*4724848cSchristos    $self->{server_version} = 0;
38*4724848cSchristos    $self->{random} = [];
39*4724848cSchristos    $self->{session_id_len} = 0;
40*4724848cSchristos    $self->{session} = "";
41*4724848cSchristos    $self->{ciphersuite} = 0;
42*4724848cSchristos    $self->{comp_meth} = 0;
43*4724848cSchristos    $self->{extension_data} = "";
44*4724848cSchristos
45*4724848cSchristos    return $self;
46*4724848cSchristos}
47*4724848cSchristos
48*4724848cSchristossub parse
49*4724848cSchristos{
50*4724848cSchristos    my $self = shift;
51*4724848cSchristos    my $ptr = 2;
52*4724848cSchristos    my ($server_version) = unpack('n', $self->data);
53*4724848cSchristos    my $neg_version = $server_version;
54*4724848cSchristos
55*4724848cSchristos    my $random = substr($self->data, $ptr, 32);
56*4724848cSchristos    $ptr += 32;
57*4724848cSchristos    my $session_id_len = 0;
58*4724848cSchristos    my $session = "";
59*4724848cSchristos    $session_id_len = unpack('C', substr($self->data, $ptr));
60*4724848cSchristos    $ptr++;
61*4724848cSchristos    $session = substr($self->data, $ptr, $session_id_len);
62*4724848cSchristos    $ptr += $session_id_len;
63*4724848cSchristos
64*4724848cSchristos    my $ciphersuite = unpack('n', substr($self->data, $ptr));
65*4724848cSchristos    $ptr += 2;
66*4724848cSchristos    my $comp_meth = 0;
67*4724848cSchristos    $comp_meth = unpack('C', substr($self->data, $ptr));
68*4724848cSchristos    $ptr++;
69*4724848cSchristos
70*4724848cSchristos    my $extensions_len = unpack('n', substr($self->data, $ptr));
71*4724848cSchristos    if (!defined $extensions_len) {
72*4724848cSchristos        $extensions_len = 0;
73*4724848cSchristos    } else {
74*4724848cSchristos        $ptr += 2;
75*4724848cSchristos    }
76*4724848cSchristos    #For now we just deal with this as a block of data. In the future we will
77*4724848cSchristos    #want to parse this
78*4724848cSchristos    my $extension_data;
79*4724848cSchristos    if ($extensions_len != 0) {
80*4724848cSchristos        $extension_data = substr($self->data, $ptr);
81*4724848cSchristos
82*4724848cSchristos        if (length($extension_data) != $extensions_len) {
83*4724848cSchristos            die "Invalid extension length\n";
84*4724848cSchristos        }
85*4724848cSchristos    } else {
86*4724848cSchristos        if (length($self->data) != $ptr) {
87*4724848cSchristos            die "Invalid extension length\n";
88*4724848cSchristos        }
89*4724848cSchristos        $extension_data = "";
90*4724848cSchristos    }
91*4724848cSchristos    my %extensions = ();
92*4724848cSchristos    while (length($extension_data) >= 4) {
93*4724848cSchristos        my ($type, $size) = unpack("nn", $extension_data);
94*4724848cSchristos        my $extdata = substr($extension_data, 4, $size);
95*4724848cSchristos        $extension_data = substr($extension_data, 4 + $size);
96*4724848cSchristos        $extensions{$type} = $extdata;
97*4724848cSchristos        if ($type == TLSProxy::Message::EXT_SUPPORTED_VERSIONS) {
98*4724848cSchristos            $neg_version = unpack('n', $extdata);
99*4724848cSchristos        }
100*4724848cSchristos    }
101*4724848cSchristos
102*4724848cSchristos    if ($random eq $hrrrandom) {
103*4724848cSchristos        TLSProxy::Proxy->is_tls13(1);
104*4724848cSchristos    } elsif ($neg_version == TLSProxy::Record::VERS_TLS_1_3) {
105*4724848cSchristos        TLSProxy::Proxy->is_tls13(1);
106*4724848cSchristos
107*4724848cSchristos        TLSProxy::Record->server_encrypting(1);
108*4724848cSchristos        TLSProxy::Record->client_encrypting(1);
109*4724848cSchristos    }
110*4724848cSchristos
111*4724848cSchristos    $self->server_version($server_version);
112*4724848cSchristos    $self->random($random);
113*4724848cSchristos    $self->session_id_len($session_id_len);
114*4724848cSchristos    $self->session($session);
115*4724848cSchristos    $self->ciphersuite($ciphersuite);
116*4724848cSchristos    TLSProxy::Proxy->ciphersuite($ciphersuite);
117*4724848cSchristos    $self->comp_meth($comp_meth);
118*4724848cSchristos    $self->extension_data(\%extensions);
119*4724848cSchristos
120*4724848cSchristos    $self->process_data();
121*4724848cSchristos
122*4724848cSchristos
123*4724848cSchristos    print "    Server Version:".$server_version."\n";
124*4724848cSchristos    print "    Session ID Len:".$session_id_len."\n";
125*4724848cSchristos    print "    Ciphersuite:".$ciphersuite."\n";
126*4724848cSchristos    print "    Compression Method:".$comp_meth."\n";
127*4724848cSchristos    print "    Extensions Len:".$extensions_len."\n";
128*4724848cSchristos}
129*4724848cSchristos
130*4724848cSchristos#Perform any actions necessary based on the data we've seen
131*4724848cSchristossub process_data
132*4724848cSchristos{
133*4724848cSchristos    my $self = shift;
134*4724848cSchristos
135*4724848cSchristos    TLSProxy::Message->ciphersuite($self->ciphersuite);
136*4724848cSchristos}
137*4724848cSchristos
138*4724848cSchristos#Reconstruct the on-the-wire message data following changes
139*4724848cSchristossub set_message_contents
140*4724848cSchristos{
141*4724848cSchristos    my $self = shift;
142*4724848cSchristos    my $data;
143*4724848cSchristos    my $extensions = "";
144*4724848cSchristos
145*4724848cSchristos    $data = pack('n', $self->server_version);
146*4724848cSchristos    $data .= $self->random;
147*4724848cSchristos    $data .= pack('C', $self->session_id_len);
148*4724848cSchristos    $data .= $self->session;
149*4724848cSchristos    $data .= pack('n', $self->ciphersuite);
150*4724848cSchristos    $data .= pack('C', $self->comp_meth);
151*4724848cSchristos
152*4724848cSchristos    foreach my $key (keys %{$self->extension_data}) {
153*4724848cSchristos        my $extdata = ${$self->extension_data}{$key};
154*4724848cSchristos        $extensions .= pack("n", $key);
155*4724848cSchristos        $extensions .= pack("n", length($extdata));
156*4724848cSchristos        $extensions .= $extdata;
157*4724848cSchristos        if ($key == $self->dupext) {
158*4724848cSchristos          $extensions .= pack("n", $key);
159*4724848cSchristos          $extensions .= pack("n", length($extdata));
160*4724848cSchristos          $extensions .= $extdata;
161*4724848cSchristos        }
162*4724848cSchristos    }
163*4724848cSchristos
164*4724848cSchristos    $data .= pack('n', length($extensions));
165*4724848cSchristos    $data .= $extensions;
166*4724848cSchristos    $self->data($data);
167*4724848cSchristos}
168*4724848cSchristos
169*4724848cSchristos#Read/write accessors
170*4724848cSchristossub server_version
171*4724848cSchristos{
172*4724848cSchristos    my $self = shift;
173*4724848cSchristos    if (@_) {
174*4724848cSchristos      $self->{server_version} = shift;
175*4724848cSchristos    }
176*4724848cSchristos    return $self->{server_version};
177*4724848cSchristos}
178*4724848cSchristossub random
179*4724848cSchristos{
180*4724848cSchristos    my $self = shift;
181*4724848cSchristos    if (@_) {
182*4724848cSchristos      $self->{random} = shift;
183*4724848cSchristos    }
184*4724848cSchristos    return $self->{random};
185*4724848cSchristos}
186*4724848cSchristossub session_id_len
187*4724848cSchristos{
188*4724848cSchristos    my $self = shift;
189*4724848cSchristos    if (@_) {
190*4724848cSchristos      $self->{session_id_len} = shift;
191*4724848cSchristos    }
192*4724848cSchristos    return $self->{session_id_len};
193*4724848cSchristos}
194*4724848cSchristossub session
195*4724848cSchristos{
196*4724848cSchristos    my $self = shift;
197*4724848cSchristos    if (@_) {
198*4724848cSchristos      $self->{session} = shift;
199*4724848cSchristos    }
200*4724848cSchristos    return $self->{session};
201*4724848cSchristos}
202*4724848cSchristossub ciphersuite
203*4724848cSchristos{
204*4724848cSchristos    my $self = shift;
205*4724848cSchristos    if (@_) {
206*4724848cSchristos      $self->{ciphersuite} = shift;
207*4724848cSchristos    }
208*4724848cSchristos    return $self->{ciphersuite};
209*4724848cSchristos}
210*4724848cSchristossub comp_meth
211*4724848cSchristos{
212*4724848cSchristos    my $self = shift;
213*4724848cSchristos    if (@_) {
214*4724848cSchristos      $self->{comp_meth} = shift;
215*4724848cSchristos    }
216*4724848cSchristos    return $self->{comp_meth};
217*4724848cSchristos}
218*4724848cSchristossub extension_data
219*4724848cSchristos{
220*4724848cSchristos    my $self = shift;
221*4724848cSchristos    if (@_) {
222*4724848cSchristos      $self->{extension_data} = shift;
223*4724848cSchristos    }
224*4724848cSchristos    return $self->{extension_data};
225*4724848cSchristos}
226*4724848cSchristossub set_extension
227*4724848cSchristos{
228*4724848cSchristos    my ($self, $ext_type, $ext_data) = @_;
229*4724848cSchristos    $self->{extension_data}{$ext_type} = $ext_data;
230*4724848cSchristos}
231*4724848cSchristossub delete_extension
232*4724848cSchristos{
233*4724848cSchristos    my ($self, $ext_type) = @_;
234*4724848cSchristos    delete $self->{extension_data}{$ext_type};
235*4724848cSchristos}
236*4724848cSchristos1;
237