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