1# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
2#
3# Licensed under the Apache License 2.0 (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
8use strict;
9
10package TLSProxy::ServerKeyExchange;
11
12use vars '@ISA';
13push @ISA, 'TLSProxy::Message';
14
15sub 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_KEY_EXCHANGE,
27        $data,
28        $records,
29        $startoffset,
30        $message_frag_lens);
31
32    #DHE
33    $self->{p} = "";
34    $self->{g} = "";
35    $self->{pub_key} = "";
36    $self->{sigalg} = -1;
37    $self->{sig} = "";
38
39    return $self;
40}
41
42sub parse
43{
44    my $self = shift;
45    my $sigalg = -1;
46
47    #Minimal SKE parsing. Only supports one known DHE ciphersuite at the moment
48    return if TLSProxy::Proxy->ciphersuite()
49                 != TLSProxy::Message::CIPHER_ADH_AES_128_SHA
50              && TLSProxy::Proxy->ciphersuite()
51                 != TLSProxy::Message::CIPHER_DHE_RSA_AES_128_SHA;
52
53    my $p_len = unpack('n', $self->data);
54    my $ptr = 2;
55    my $p = substr($self->data, $ptr, $p_len);
56    $ptr += $p_len;
57
58    my $g_len = unpack('n', substr($self->data, $ptr));
59    $ptr += 2;
60    my $g = substr($self->data, $ptr, $g_len);
61    $ptr += $g_len;
62
63    my $pub_key_len = unpack('n', substr($self->data, $ptr));
64    $ptr += 2;
65    my $pub_key = substr($self->data, $ptr, $pub_key_len);
66    $ptr += $pub_key_len;
67
68    #We assume its signed
69    my $record = ${$self->records}[0];
70
71    if (TLSProxy::Proxy->is_tls13()
72            || $record->version() == TLSProxy::Record::VERS_TLS_1_2) {
73        $sigalg = unpack('n', substr($self->data, $ptr));
74        $ptr += 2;
75    }
76    my $sig = "";
77    if (defined $sigalg) {
78        my $sig_len = unpack('n', substr($self->data, $ptr));
79        if (defined $sig_len) {
80            $ptr += 2;
81            $sig = substr($self->data, $ptr, $sig_len);
82            $ptr += $sig_len;
83        }
84    }
85
86    $self->p($p);
87    $self->g($g);
88    $self->pub_key($pub_key);
89    $self->sigalg($sigalg) if defined $sigalg;
90    $self->signature($sig);
91}
92
93
94#Reconstruct the on-the-wire message data following changes
95sub set_message_contents
96{
97    my $self = shift;
98    my $data;
99
100    $data = pack('n', length($self->p));
101    $data .= $self->p;
102    $data .= pack('n', length($self->g));
103    $data .= $self->g;
104    $data .= pack('n', length($self->pub_key));
105    $data .= $self->pub_key;
106    $data .= pack('n', $self->sigalg) if ($self->sigalg != -1);
107    if (length($self->signature) > 0) {
108        $data .= pack('n', length($self->signature));
109        $data .= $self->signature;
110    }
111
112    $self->data($data);
113}
114
115#Read/write accessors
116#DHE
117sub p
118{
119    my $self = shift;
120    if (@_) {
121      $self->{p} = shift;
122    }
123    return $self->{p};
124}
125sub g
126{
127    my $self = shift;
128    if (@_) {
129      $self->{g} = shift;
130    }
131    return $self->{g};
132}
133sub pub_key
134{
135    my $self = shift;
136    if (@_) {
137      $self->{pub_key} = shift;
138    }
139    return $self->{pub_key};
140}
141sub sigalg
142{
143    my $self = shift;
144    if (@_) {
145      $self->{sigalg} = shift;
146    }
147    return $self->{sigalg};
148}
149sub signature
150{
151    my $self = shift;
152    if (@_) {
153      $self->{sig} = shift;
154    }
155    return $self->{sig};
156}
1571;
158