1e1051a39Sopenharmony_ci#! /usr/bin/env perl
2e1051a39Sopenharmony_ci# Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci#
4e1051a39Sopenharmony_ci# Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci# this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci# in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci# https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci
9e1051a39Sopenharmony_ciuse strict;
10e1051a39Sopenharmony_ciuse feature 'state';
11e1051a39Sopenharmony_ci
12e1051a39Sopenharmony_ciuse OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/;
13e1051a39Sopenharmony_ciuse OpenSSL::Test::Utils;
14e1051a39Sopenharmony_ciuse TLSProxy::Proxy;
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_cimy $test_name = "test_sslrecords";
17e1051a39Sopenharmony_cisetup($test_name);
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ciplan skip_all => "TLSProxy isn't usable on $^O"
20e1051a39Sopenharmony_ci    if $^O =~ /^(VMS)$/;
21e1051a39Sopenharmony_ci
22e1051a39Sopenharmony_ciplan skip_all => "$test_name needs the dynamic engine feature enabled"
23e1051a39Sopenharmony_ci    if disabled("engine") || disabled("dynamic-engine");
24e1051a39Sopenharmony_ci
25e1051a39Sopenharmony_ciplan skip_all => "$test_name needs the sock feature enabled"
26e1051a39Sopenharmony_ci    if disabled("sock");
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_ciplan skip_all => "$test_name needs TLSv1.2 enabled"
29e1051a39Sopenharmony_ci    if disabled("tls1_2");
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_ci$ENV{OPENSSL_ia32cap} = '~0x200000200000000';
32e1051a39Sopenharmony_cimy $proxy = TLSProxy::Proxy->new(
33e1051a39Sopenharmony_ci    \&add_empty_recs_filter,
34e1051a39Sopenharmony_ci    cmdstr(app(["openssl"]), display => 1),
35e1051a39Sopenharmony_ci    srctop_file("apps", "server.pem"),
36e1051a39Sopenharmony_ci    (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE})
37e1051a39Sopenharmony_ci);
38e1051a39Sopenharmony_ci
39e1051a39Sopenharmony_cimy $boundary_test_type;
40e1051a39Sopenharmony_cimy $fatal_alert = 0;    # set by filters at expected fatal alerts
41e1051a39Sopenharmony_ci
42e1051a39Sopenharmony_ci#Test 1: Injecting out of context empty records should fail
43e1051a39Sopenharmony_cimy $content_type = TLSProxy::Record::RT_APPLICATION_DATA;
44e1051a39Sopenharmony_cimy $inject_recs_num = 1;
45e1051a39Sopenharmony_ci$proxy->serverflags("-tls1_2");
46e1051a39Sopenharmony_ci$proxy->clientflags("-no_tls1_3");
47e1051a39Sopenharmony_ci$proxy->start() or plan skip_all => "Unable to start up Proxy for tests";
48e1051a39Sopenharmony_ciplan tests => 20;
49e1051a39Sopenharmony_ciok($fatal_alert, "Out of context empty records test");
50e1051a39Sopenharmony_ci
51e1051a39Sopenharmony_ci#Test 2: Injecting in context empty records should succeed
52e1051a39Sopenharmony_ci$proxy->clear();
53e1051a39Sopenharmony_ci$content_type = TLSProxy::Record::RT_HANDSHAKE;
54e1051a39Sopenharmony_ci$proxy->serverflags("-tls1_2");
55e1051a39Sopenharmony_ci$proxy->clientflags("-no_tls1_3");
56e1051a39Sopenharmony_ci$proxy->start();
57e1051a39Sopenharmony_ciok(TLSProxy::Message->success(), "In context empty records test");
58e1051a39Sopenharmony_ci
59e1051a39Sopenharmony_ci#Test 3: Injecting too many in context empty records should fail
60e1051a39Sopenharmony_ci$fatal_alert = 0;
61e1051a39Sopenharmony_ci$proxy->clear();
62e1051a39Sopenharmony_ci#We allow 32 consecutive in context empty records
63e1051a39Sopenharmony_ci$inject_recs_num = 33;
64e1051a39Sopenharmony_ci$proxy->serverflags("-tls1_2");
65e1051a39Sopenharmony_ci$proxy->clientflags("-no_tls1_3");
66e1051a39Sopenharmony_ci$proxy->start();
67e1051a39Sopenharmony_ciok($fatal_alert, "Too many in context empty records test");
68e1051a39Sopenharmony_ci
69e1051a39Sopenharmony_ci#Test 4: Injecting a fragmented fatal alert should fail. We expect the server to
70e1051a39Sopenharmony_ci#        send back an alert of its own because it cannot handle fragmented
71e1051a39Sopenharmony_ci#        alerts
72e1051a39Sopenharmony_ci$fatal_alert = 0;
73e1051a39Sopenharmony_ci$proxy->clear();
74e1051a39Sopenharmony_ci$proxy->filter(\&add_frag_alert_filter);
75e1051a39Sopenharmony_ci$proxy->serverflags("-tls1_2");
76e1051a39Sopenharmony_ci$proxy->clientflags("-no_tls1_3");
77e1051a39Sopenharmony_ci$proxy->start();
78e1051a39Sopenharmony_ciok($fatal_alert, "Fragmented alert records test");
79e1051a39Sopenharmony_ci
80e1051a39Sopenharmony_ci#Run some SSLv2 ClientHello tests
81e1051a39Sopenharmony_ci
82e1051a39Sopenharmony_ciuse constant {
83e1051a39Sopenharmony_ci    TLSV1_2_IN_SSLV2 => 0,
84e1051a39Sopenharmony_ci    SSLV2_IN_SSLV2 => 1,
85e1051a39Sopenharmony_ci    FRAGMENTED_IN_TLSV1_2 => 2,
86e1051a39Sopenharmony_ci    FRAGMENTED_IN_SSLV2 => 3,
87e1051a39Sopenharmony_ci    ALERT_BEFORE_SSLV2 => 4
88e1051a39Sopenharmony_ci};
89e1051a39Sopenharmony_ci
90e1051a39Sopenharmony_ci# The TLSv1.2 in SSLv2 ClientHello need to run at security level 0
91e1051a39Sopenharmony_ci# because in a SSLv2 ClientHello we can't send extentions to indicate
92e1051a39Sopenharmony_ci# which signature algorithm we want to use, and the default is SHA1.
93e1051a39Sopenharmony_ci
94e1051a39Sopenharmony_ci#Test 5: Inject an SSLv2 style record format for a TLSv1.2 ClientHello
95e1051a39Sopenharmony_cimy $sslv2testtype = TLSV1_2_IN_SSLV2;
96e1051a39Sopenharmony_ci$proxy->clear();
97e1051a39Sopenharmony_ci$proxy->filter(\&add_sslv2_filter);
98e1051a39Sopenharmony_ci$proxy->serverflags("-tls1_2");
99e1051a39Sopenharmony_ci$proxy->clientflags("-no_tls1_3 -legacy_renegotiation");
100e1051a39Sopenharmony_ci$proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
101e1051a39Sopenharmony_ci$proxy->start();
102e1051a39Sopenharmony_ciok(TLSProxy::Message->success(), "TLSv1.2 in SSLv2 ClientHello test");
103e1051a39Sopenharmony_ci
104e1051a39Sopenharmony_ci#Test 6: Inject an SSLv2 style record format for an SSLv2 ClientHello. We don't
105e1051a39Sopenharmony_ci#        support this so it should fail. We actually treat it as an unknown
106e1051a39Sopenharmony_ci#        protocol so we don't even send an alert in this case.
107e1051a39Sopenharmony_ci$sslv2testtype = SSLV2_IN_SSLV2;
108e1051a39Sopenharmony_ci$proxy->clear();
109e1051a39Sopenharmony_ci$proxy->serverflags("-tls1_2");
110e1051a39Sopenharmony_ci$proxy->clientflags("-no_tls1_3");
111e1051a39Sopenharmony_ci$proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
112e1051a39Sopenharmony_ci$proxy->start();
113e1051a39Sopenharmony_ciok(TLSProxy::Message->fail(), "SSLv2 in SSLv2 ClientHello test");
114e1051a39Sopenharmony_ci
115e1051a39Sopenharmony_ci#Test 7: Sanity check ClientHello fragmentation. This isn't really an SSLv2 test
116e1051a39Sopenharmony_ci#        at all, but it gives us confidence that Test 8 fails for the right
117e1051a39Sopenharmony_ci#        reasons
118e1051a39Sopenharmony_ci$sslv2testtype = FRAGMENTED_IN_TLSV1_2;
119e1051a39Sopenharmony_ci$proxy->clear();
120e1051a39Sopenharmony_ci$proxy->serverflags("-tls1_2");
121e1051a39Sopenharmony_ci$proxy->clientflags("-no_tls1_3");
122e1051a39Sopenharmony_ci$proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
123e1051a39Sopenharmony_ci$proxy->start();
124e1051a39Sopenharmony_ciok(TLSProxy::Message->success(), "Fragmented ClientHello in TLSv1.2 test");
125e1051a39Sopenharmony_ci
126e1051a39Sopenharmony_ci#Test 8: Fragment a TLSv1.2 ClientHello across a TLS1.2 record; an SSLv2
127e1051a39Sopenharmony_ci#        record; and another TLS1.2 record. This isn't allowed so should fail
128e1051a39Sopenharmony_ci$sslv2testtype = FRAGMENTED_IN_SSLV2;
129e1051a39Sopenharmony_ci$proxy->clear();
130e1051a39Sopenharmony_ci$proxy->serverflags("-tls1_2");
131e1051a39Sopenharmony_ci$proxy->clientflags("-no_tls1_3");
132e1051a39Sopenharmony_ci$proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
133e1051a39Sopenharmony_ci$proxy->start();
134e1051a39Sopenharmony_ciok(TLSProxy::Message->fail(), "Fragmented ClientHello in TLSv1.2/SSLv2 test");
135e1051a39Sopenharmony_ci
136e1051a39Sopenharmony_ci#Test 9: Send a TLS warning alert before an SSLv2 ClientHello. This should
137e1051a39Sopenharmony_ci#        fail because an SSLv2 ClientHello must be the first record.
138e1051a39Sopenharmony_ci$sslv2testtype = ALERT_BEFORE_SSLV2;
139e1051a39Sopenharmony_ci$proxy->clear();
140e1051a39Sopenharmony_ci$proxy->serverflags("-tls1_2");
141e1051a39Sopenharmony_ci$proxy->clientflags("-no_tls1_3");
142e1051a39Sopenharmony_ci$proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
143e1051a39Sopenharmony_ci$proxy->start();
144e1051a39Sopenharmony_ciok(TLSProxy::Message->fail(), "Alert before SSLv2 ClientHello test");
145e1051a39Sopenharmony_ci
146e1051a39Sopenharmony_ci#Unrecognised record type tests
147e1051a39Sopenharmony_ci
148e1051a39Sopenharmony_ci#Test 10: Sending an unrecognised record type in TLS1.2 should fail
149e1051a39Sopenharmony_ci$fatal_alert = 0;
150e1051a39Sopenharmony_ci$proxy->clear();
151e1051a39Sopenharmony_ci$proxy->serverflags("-tls1_2");
152e1051a39Sopenharmony_ci$proxy->clientflags("-no_tls1_3");
153e1051a39Sopenharmony_ci$proxy->filter(\&add_unknown_record_type);
154e1051a39Sopenharmony_ci$proxy->start();
155e1051a39Sopenharmony_ciok($fatal_alert, "Unrecognised record type in TLS1.2");
156e1051a39Sopenharmony_ci
157e1051a39Sopenharmony_ciSKIP: {
158e1051a39Sopenharmony_ci    skip "TLSv1.1 disabled", 1 if disabled("tls1_1");
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_ci    #Test 11: Sending an unrecognised record type in TLS1.1 should fail
161e1051a39Sopenharmony_ci    $fatal_alert = 0;
162e1051a39Sopenharmony_ci    $proxy->clear();
163e1051a39Sopenharmony_ci    $proxy->clientflags("-tls1_1 -cipher DEFAULT:\@SECLEVEL=0");
164e1051a39Sopenharmony_ci    $proxy->ciphers("AES128-SHA:\@SECLEVEL=0");
165e1051a39Sopenharmony_ci    $proxy->start();
166e1051a39Sopenharmony_ci    ok($fatal_alert, "Unrecognised record type in TLS1.1");
167e1051a39Sopenharmony_ci}
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci#Test 12: Sending a different record version in TLS1.2 should fail
170e1051a39Sopenharmony_ci$fatal_alert = 0;
171e1051a39Sopenharmony_ci$proxy->clear();
172e1051a39Sopenharmony_ci$proxy->clientflags("-tls1_2");
173e1051a39Sopenharmony_ci$proxy->filter(\&change_version);
174e1051a39Sopenharmony_ci$proxy->start();
175e1051a39Sopenharmony_ciok($fatal_alert, "Changed record version in TLS1.2");
176e1051a39Sopenharmony_ci
177e1051a39Sopenharmony_ci#TLS1.3 specific tests
178e1051a39Sopenharmony_ciSKIP: {
179e1051a39Sopenharmony_ci    skip "TLSv1.3 disabled", 8
180e1051a39Sopenharmony_ci        if disabled("tls1_3") || (disabled("ec") && disabled("dh"));
181e1051a39Sopenharmony_ci
182e1051a39Sopenharmony_ci    #Test 13: Sending a different record version in TLS1.3 should fail
183e1051a39Sopenharmony_ci    $proxy->clear();
184e1051a39Sopenharmony_ci    $proxy->filter(\&change_version);
185e1051a39Sopenharmony_ci    $proxy->start();
186e1051a39Sopenharmony_ci    ok(TLSProxy::Message->fail(), "Changed record version in TLS1.3");
187e1051a39Sopenharmony_ci
188e1051a39Sopenharmony_ci    #Test 14: Sending an unrecognised record type in TLS1.3 should fail
189e1051a39Sopenharmony_ci    $fatal_alert = 0;
190e1051a39Sopenharmony_ci    $proxy->clear();
191e1051a39Sopenharmony_ci    $proxy->filter(\&add_unknown_record_type);
192e1051a39Sopenharmony_ci    $proxy->start();
193e1051a39Sopenharmony_ci    ok($fatal_alert, "Unrecognised record type in TLS1.3");
194e1051a39Sopenharmony_ci
195e1051a39Sopenharmony_ci    #Test 15: Sending an outer record type other than app data once encrypted
196e1051a39Sopenharmony_ci    #should fail
197e1051a39Sopenharmony_ci    $fatal_alert = 0;
198e1051a39Sopenharmony_ci    $proxy->clear();
199e1051a39Sopenharmony_ci    $proxy->filter(\&change_outer_record_type);
200e1051a39Sopenharmony_ci    $proxy->start();
201e1051a39Sopenharmony_ci    ok($fatal_alert, "Wrong outer record type in TLS1.3");
202e1051a39Sopenharmony_ci
203e1051a39Sopenharmony_ci    use constant {
204e1051a39Sopenharmony_ci        DATA_AFTER_SERVER_HELLO => 0,
205e1051a39Sopenharmony_ci        DATA_AFTER_FINISHED => 1,
206e1051a39Sopenharmony_ci        DATA_AFTER_KEY_UPDATE => 2,
207e1051a39Sopenharmony_ci        DATA_BETWEEN_KEY_UPDATE => 3,
208e1051a39Sopenharmony_ci        NO_DATA_BETWEEN_KEY_UPDATE => 4,
209e1051a39Sopenharmony_ci    };
210e1051a39Sopenharmony_ci
211e1051a39Sopenharmony_ci    #Test 16: Sending a ServerHello which doesn't end on a record boundary
212e1051a39Sopenharmony_ci    #         should fail
213e1051a39Sopenharmony_ci    $fatal_alert = 0;
214e1051a39Sopenharmony_ci    $proxy->clear();
215e1051a39Sopenharmony_ci    $boundary_test_type = DATA_AFTER_SERVER_HELLO;
216e1051a39Sopenharmony_ci    $proxy->filter(\&not_on_record_boundary);
217e1051a39Sopenharmony_ci    $proxy->start();
218e1051a39Sopenharmony_ci    ok($fatal_alert, "Record not on boundary in TLS1.3 (ServerHello)");
219e1051a39Sopenharmony_ci
220e1051a39Sopenharmony_ci    #Test 17: Sending a Finished which doesn't end on a record boundary
221e1051a39Sopenharmony_ci    #         should fail
222e1051a39Sopenharmony_ci    $fatal_alert = 0;
223e1051a39Sopenharmony_ci    $proxy->clear();
224e1051a39Sopenharmony_ci    $boundary_test_type = DATA_AFTER_FINISHED;
225e1051a39Sopenharmony_ci    $proxy->start();
226e1051a39Sopenharmony_ci    ok($fatal_alert, "Record not on boundary in TLS1.3 (Finished)");
227e1051a39Sopenharmony_ci
228e1051a39Sopenharmony_ci    #Test 18: Sending a KeyUpdate which doesn't end on a record boundary
229e1051a39Sopenharmony_ci    #         should fail
230e1051a39Sopenharmony_ci    $fatal_alert = 0;
231e1051a39Sopenharmony_ci    $proxy->clear();
232e1051a39Sopenharmony_ci    $boundary_test_type = DATA_AFTER_KEY_UPDATE;
233e1051a39Sopenharmony_ci    $proxy->start();
234e1051a39Sopenharmony_ci    ok($fatal_alert, "Record not on boundary in TLS1.3 (KeyUpdate)");
235e1051a39Sopenharmony_ci
236e1051a39Sopenharmony_ci    #Test 19: Sending application data in the middle of a fragmented KeyUpdate
237e1051a39Sopenharmony_ci    #         should fail. Strictly speaking this is not a record boundary test
238e1051a39Sopenharmony_ci    #         but we use the same filter.
239e1051a39Sopenharmony_ci    $fatal_alert = 0;
240e1051a39Sopenharmony_ci    $proxy->clear();
241e1051a39Sopenharmony_ci    $boundary_test_type = DATA_BETWEEN_KEY_UPDATE;
242e1051a39Sopenharmony_ci    $proxy->start();
243e1051a39Sopenharmony_ci    ok($fatal_alert, "Data between KeyUpdate");
244e1051a39Sopenharmony_ci
245e1051a39Sopenharmony_ci    #Test 20: Fragmented KeyUpdate. This should succeed. Strictly speaking this
246e1051a39Sopenharmony_ci    #         is not a record boundary test but we use the same filter.
247e1051a39Sopenharmony_ci    $proxy->clear();
248e1051a39Sopenharmony_ci    $boundary_test_type = NO_DATA_BETWEEN_KEY_UPDATE;
249e1051a39Sopenharmony_ci    $proxy->start();
250e1051a39Sopenharmony_ci    ok(TLSProxy::Message->success(), "No data between KeyUpdate");
251e1051a39Sopenharmony_ci }
252e1051a39Sopenharmony_ci
253e1051a39Sopenharmony_ci
254e1051a39Sopenharmony_cisub add_empty_recs_filter
255e1051a39Sopenharmony_ci{
256e1051a39Sopenharmony_ci    my $proxy = shift;
257e1051a39Sopenharmony_ci    my $records = $proxy->record_list;
258e1051a39Sopenharmony_ci
259e1051a39Sopenharmony_ci    # We're only interested in the initial ClientHello
260e1051a39Sopenharmony_ci    if ($proxy->flight != 0) {
261e1051a39Sopenharmony_ci        $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == 10;
262e1051a39Sopenharmony_ci        return;
263e1051a39Sopenharmony_ci    }
264e1051a39Sopenharmony_ci
265e1051a39Sopenharmony_ci    for (my $i = 0; $i < $inject_recs_num; $i++) {
266e1051a39Sopenharmony_ci        my $record = TLSProxy::Record->new(
267e1051a39Sopenharmony_ci            0,
268e1051a39Sopenharmony_ci            $content_type,
269e1051a39Sopenharmony_ci            TLSProxy::Record::VERS_TLS_1_2,
270e1051a39Sopenharmony_ci            0,
271e1051a39Sopenharmony_ci            0,
272e1051a39Sopenharmony_ci            0,
273e1051a39Sopenharmony_ci            0,
274e1051a39Sopenharmony_ci            "",
275e1051a39Sopenharmony_ci            ""
276e1051a39Sopenharmony_ci        );
277e1051a39Sopenharmony_ci        push @{$records}, $record;
278e1051a39Sopenharmony_ci    }
279e1051a39Sopenharmony_ci}
280e1051a39Sopenharmony_ci
281e1051a39Sopenharmony_cisub add_frag_alert_filter
282e1051a39Sopenharmony_ci{
283e1051a39Sopenharmony_ci    my $proxy = shift;
284e1051a39Sopenharmony_ci    my $records = $proxy->record_list;
285e1051a39Sopenharmony_ci    my $byte;
286e1051a39Sopenharmony_ci
287e1051a39Sopenharmony_ci    # We're only interested in the initial ClientHello
288e1051a39Sopenharmony_ci    if ($proxy->flight != 0) {
289e1051a39Sopenharmony_ci        $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(1) == 10;
290e1051a39Sopenharmony_ci        return;
291e1051a39Sopenharmony_ci    }
292e1051a39Sopenharmony_ci
293e1051a39Sopenharmony_ci    # Add a zero length fragment first
294e1051a39Sopenharmony_ci    #my $record = TLSProxy::Record->new(
295e1051a39Sopenharmony_ci    #    0,
296e1051a39Sopenharmony_ci    #    TLSProxy::Record::RT_ALERT,
297e1051a39Sopenharmony_ci    #    TLSProxy::Record::VERS_TLS_1_2,
298e1051a39Sopenharmony_ci    #    0,
299e1051a39Sopenharmony_ci    #    0,
300e1051a39Sopenharmony_ci    #    0,
301e1051a39Sopenharmony_ci    #    "",
302e1051a39Sopenharmony_ci    #    ""
303e1051a39Sopenharmony_ci    #);
304e1051a39Sopenharmony_ci    #push @{$proxy->record_list}, $record;
305e1051a39Sopenharmony_ci
306e1051a39Sopenharmony_ci    # Now add the alert level (Fatal) as a separate record
307e1051a39Sopenharmony_ci    $byte = pack('C', TLSProxy::Message::AL_LEVEL_FATAL);
308e1051a39Sopenharmony_ci    my $record = TLSProxy::Record->new(
309e1051a39Sopenharmony_ci        0,
310e1051a39Sopenharmony_ci        TLSProxy::Record::RT_ALERT,
311e1051a39Sopenharmony_ci        TLSProxy::Record::VERS_TLS_1_2,
312e1051a39Sopenharmony_ci        1,
313e1051a39Sopenharmony_ci        0,
314e1051a39Sopenharmony_ci        1,
315e1051a39Sopenharmony_ci        1,
316e1051a39Sopenharmony_ci        $byte,
317e1051a39Sopenharmony_ci        $byte
318e1051a39Sopenharmony_ci    );
319e1051a39Sopenharmony_ci    push @{$records}, $record;
320e1051a39Sopenharmony_ci
321e1051a39Sopenharmony_ci    # And finally the description (Unexpected message) in a third record
322e1051a39Sopenharmony_ci    $byte = pack('C', TLSProxy::Message::AL_DESC_UNEXPECTED_MESSAGE);
323e1051a39Sopenharmony_ci    $record = TLSProxy::Record->new(
324e1051a39Sopenharmony_ci        0,
325e1051a39Sopenharmony_ci        TLSProxy::Record::RT_ALERT,
326e1051a39Sopenharmony_ci        TLSProxy::Record::VERS_TLS_1_2,
327e1051a39Sopenharmony_ci        1,
328e1051a39Sopenharmony_ci        0,
329e1051a39Sopenharmony_ci        1,
330e1051a39Sopenharmony_ci        1,
331e1051a39Sopenharmony_ci        $byte,
332e1051a39Sopenharmony_ci        $byte
333e1051a39Sopenharmony_ci    );
334e1051a39Sopenharmony_ci    push @{$records}, $record;
335e1051a39Sopenharmony_ci}
336e1051a39Sopenharmony_ci
337e1051a39Sopenharmony_cisub add_sslv2_filter
338e1051a39Sopenharmony_ci{
339e1051a39Sopenharmony_ci    my $proxy = shift;
340e1051a39Sopenharmony_ci    my $clienthello;
341e1051a39Sopenharmony_ci    my $record;
342e1051a39Sopenharmony_ci
343e1051a39Sopenharmony_ci    # We're only interested in the initial ClientHello
344e1051a39Sopenharmony_ci    if ($proxy->flight != 0) {
345e1051a39Sopenharmony_ci        return;
346e1051a39Sopenharmony_ci    }
347e1051a39Sopenharmony_ci
348e1051a39Sopenharmony_ci    # Ditch the real ClientHello - we're going to replace it with our own
349e1051a39Sopenharmony_ci    shift @{$proxy->record_list};
350e1051a39Sopenharmony_ci
351e1051a39Sopenharmony_ci    if ($sslv2testtype == ALERT_BEFORE_SSLV2) {
352e1051a39Sopenharmony_ci        my $alert = pack('CC', TLSProxy::Message::AL_LEVEL_FATAL,
353e1051a39Sopenharmony_ci                               TLSProxy::Message::AL_DESC_NO_RENEGOTIATION);
354e1051a39Sopenharmony_ci        my $alertlen = length $alert;
355e1051a39Sopenharmony_ci        $record = TLSProxy::Record->new(
356e1051a39Sopenharmony_ci            0,
357e1051a39Sopenharmony_ci            TLSProxy::Record::RT_ALERT,
358e1051a39Sopenharmony_ci            TLSProxy::Record::VERS_TLS_1_2,
359e1051a39Sopenharmony_ci            $alertlen,
360e1051a39Sopenharmony_ci            0,
361e1051a39Sopenharmony_ci            $alertlen,
362e1051a39Sopenharmony_ci            $alertlen,
363e1051a39Sopenharmony_ci            $alert,
364e1051a39Sopenharmony_ci            $alert
365e1051a39Sopenharmony_ci        );
366e1051a39Sopenharmony_ci
367e1051a39Sopenharmony_ci        push @{$proxy->record_list}, $record;
368e1051a39Sopenharmony_ci    }
369e1051a39Sopenharmony_ci
370e1051a39Sopenharmony_ci    if ($sslv2testtype == ALERT_BEFORE_SSLV2
371e1051a39Sopenharmony_ci            || $sslv2testtype == TLSV1_2_IN_SSLV2
372e1051a39Sopenharmony_ci            || $sslv2testtype == SSLV2_IN_SSLV2) {
373e1051a39Sopenharmony_ci        # This is an SSLv2 format ClientHello
374e1051a39Sopenharmony_ci        $clienthello =
375e1051a39Sopenharmony_ci            pack "C44",
376e1051a39Sopenharmony_ci            0x01, # ClientHello
377e1051a39Sopenharmony_ci            0x03, 0x03, #TLSv1.2
378e1051a39Sopenharmony_ci            0x00, 0x03, # Ciphersuites len
379e1051a39Sopenharmony_ci            0x00, 0x00, # Session id len
380e1051a39Sopenharmony_ci            0x00, 0x20, # Challenge len
381e1051a39Sopenharmony_ci            0x00, 0x00, 0x2f, #AES128-SHA
382e1051a39Sopenharmony_ci            0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
383e1051a39Sopenharmony_ci            0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
384e1051a39Sopenharmony_ci            0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6; # Challenge
385e1051a39Sopenharmony_ci
386e1051a39Sopenharmony_ci        if ($sslv2testtype == SSLV2_IN_SSLV2) {
387e1051a39Sopenharmony_ci            # Set the version to "real" SSLv2
388e1051a39Sopenharmony_ci            vec($clienthello, 1, 8) = 0x00;
389e1051a39Sopenharmony_ci            vec($clienthello, 2, 8) = 0x02;
390e1051a39Sopenharmony_ci        }
391e1051a39Sopenharmony_ci
392e1051a39Sopenharmony_ci        my $chlen = length $clienthello;
393e1051a39Sopenharmony_ci
394e1051a39Sopenharmony_ci        $record = TLSProxy::Record->new(
395e1051a39Sopenharmony_ci            0,
396e1051a39Sopenharmony_ci            TLSProxy::Record::RT_HANDSHAKE,
397e1051a39Sopenharmony_ci            TLSProxy::Record::VERS_TLS_1_2,
398e1051a39Sopenharmony_ci            $chlen,
399e1051a39Sopenharmony_ci            1, #SSLv2
400e1051a39Sopenharmony_ci            $chlen,
401e1051a39Sopenharmony_ci            $chlen,
402e1051a39Sopenharmony_ci            $clienthello,
403e1051a39Sopenharmony_ci            $clienthello
404e1051a39Sopenharmony_ci        );
405e1051a39Sopenharmony_ci
406e1051a39Sopenharmony_ci        push @{$proxy->record_list}, $record;
407e1051a39Sopenharmony_ci    } else {
408e1051a39Sopenharmony_ci        # For this test we're using a real TLS ClientHello
409e1051a39Sopenharmony_ci        $clienthello =
410e1051a39Sopenharmony_ci            pack "C49",
411e1051a39Sopenharmony_ci            0x01, # ClientHello
412e1051a39Sopenharmony_ci            0x00, 0x00, 0x2D, # Message length
413e1051a39Sopenharmony_ci            0x03, 0x03, # TLSv1.2
414e1051a39Sopenharmony_ci            0x01, 0x18, 0x9F, 0x76, 0xEC, 0x57, 0xCE, 0xE5, 0xB3, 0xAB, 0x79, 0x90,
415e1051a39Sopenharmony_ci            0xAD, 0xAC, 0x6E, 0xD1, 0x58, 0x35, 0x03, 0x97, 0x16, 0x10, 0x82, 0x56,
416e1051a39Sopenharmony_ci            0xD8, 0x55, 0xFF, 0xE1, 0x8A, 0xA3, 0x2E, 0xF6, # Random
417e1051a39Sopenharmony_ci            0x00, # Session id len
418e1051a39Sopenharmony_ci            0x00, 0x04, # Ciphersuites len
419e1051a39Sopenharmony_ci            0x00, 0x2f, # AES128-SHA
420e1051a39Sopenharmony_ci            0x00, 0xff, # Empty reneg info SCSV
421e1051a39Sopenharmony_ci            0x01, # Compression methods len
422e1051a39Sopenharmony_ci            0x00, # Null compression
423e1051a39Sopenharmony_ci            0x00, 0x00; # Extensions len
424e1051a39Sopenharmony_ci
425e1051a39Sopenharmony_ci        # Split this into 3: A TLS record; a SSLv2 record and a TLS record.
426e1051a39Sopenharmony_ci        # We deliberately split the second record prior to the Challenge/Random
427e1051a39Sopenharmony_ci        # and set the first byte of the random to 1. This makes the second SSLv2
428e1051a39Sopenharmony_ci        # record look like an SSLv2 ClientHello
429e1051a39Sopenharmony_ci        my $frag1 = substr $clienthello, 0, 6;
430e1051a39Sopenharmony_ci        my $frag2 = substr $clienthello, 6, 32;
431e1051a39Sopenharmony_ci        my $frag3 = substr $clienthello, 38;
432e1051a39Sopenharmony_ci
433e1051a39Sopenharmony_ci        my $fraglen = length $frag1;
434e1051a39Sopenharmony_ci        $record = TLSProxy::Record->new(
435e1051a39Sopenharmony_ci            0,
436e1051a39Sopenharmony_ci            TLSProxy::Record::RT_HANDSHAKE,
437e1051a39Sopenharmony_ci            TLSProxy::Record::VERS_TLS_1_2,
438e1051a39Sopenharmony_ci            $fraglen,
439e1051a39Sopenharmony_ci            0,
440e1051a39Sopenharmony_ci            $fraglen,
441e1051a39Sopenharmony_ci            $fraglen,
442e1051a39Sopenharmony_ci            $frag1,
443e1051a39Sopenharmony_ci            $frag1
444e1051a39Sopenharmony_ci        );
445e1051a39Sopenharmony_ci        push @{$proxy->record_list}, $record;
446e1051a39Sopenharmony_ci
447e1051a39Sopenharmony_ci        $fraglen = length $frag2;
448e1051a39Sopenharmony_ci        my $recvers;
449e1051a39Sopenharmony_ci        if ($sslv2testtype == FRAGMENTED_IN_SSLV2) {
450e1051a39Sopenharmony_ci            $recvers = 1;
451e1051a39Sopenharmony_ci        } else {
452e1051a39Sopenharmony_ci            $recvers = 0;
453e1051a39Sopenharmony_ci        }
454e1051a39Sopenharmony_ci        $record = TLSProxy::Record->new(
455e1051a39Sopenharmony_ci            0,
456e1051a39Sopenharmony_ci            TLSProxy::Record::RT_HANDSHAKE,
457e1051a39Sopenharmony_ci            TLSProxy::Record::VERS_TLS_1_2,
458e1051a39Sopenharmony_ci            $fraglen,
459e1051a39Sopenharmony_ci            $recvers,
460e1051a39Sopenharmony_ci            $fraglen,
461e1051a39Sopenharmony_ci            $fraglen,
462e1051a39Sopenharmony_ci            $frag2,
463e1051a39Sopenharmony_ci            $frag2
464e1051a39Sopenharmony_ci        );
465e1051a39Sopenharmony_ci        push @{$proxy->record_list}, $record;
466e1051a39Sopenharmony_ci
467e1051a39Sopenharmony_ci        $fraglen = length $frag3;
468e1051a39Sopenharmony_ci        $record = TLSProxy::Record->new(
469e1051a39Sopenharmony_ci            0,
470e1051a39Sopenharmony_ci            TLSProxy::Record::RT_HANDSHAKE,
471e1051a39Sopenharmony_ci            TLSProxy::Record::VERS_TLS_1_2,
472e1051a39Sopenharmony_ci            $fraglen,
473e1051a39Sopenharmony_ci            0,
474e1051a39Sopenharmony_ci            $fraglen,
475e1051a39Sopenharmony_ci            $fraglen,
476e1051a39Sopenharmony_ci            $frag3,
477e1051a39Sopenharmony_ci            $frag3
478e1051a39Sopenharmony_ci        );
479e1051a39Sopenharmony_ci        push @{$proxy->record_list}, $record;
480e1051a39Sopenharmony_ci    }
481e1051a39Sopenharmony_ci
482e1051a39Sopenharmony_ci}
483e1051a39Sopenharmony_ci
484e1051a39Sopenharmony_cisub add_unknown_record_type
485e1051a39Sopenharmony_ci{
486e1051a39Sopenharmony_ci    my $proxy = shift;
487e1051a39Sopenharmony_ci    my $records = $proxy->record_list;
488e1051a39Sopenharmony_ci    state $added_record;
489e1051a39Sopenharmony_ci
490e1051a39Sopenharmony_ci    # We'll change a record after the initial version neg has taken place
491e1051a39Sopenharmony_ci    if ($proxy->flight == 0) {
492e1051a39Sopenharmony_ci        $added_record = 0;
493e1051a39Sopenharmony_ci        return;
494e1051a39Sopenharmony_ci    } elsif ($proxy->flight != 1 || $added_record) {
495e1051a39Sopenharmony_ci        $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
496e1051a39Sopenharmony_ci        return;
497e1051a39Sopenharmony_ci    }
498e1051a39Sopenharmony_ci
499e1051a39Sopenharmony_ci    my $record = TLSProxy::Record->new(
500e1051a39Sopenharmony_ci        1,
501e1051a39Sopenharmony_ci        TLSProxy::Record::RT_UNKNOWN,
502e1051a39Sopenharmony_ci        @{$records}[-1]->version(),
503e1051a39Sopenharmony_ci        1,
504e1051a39Sopenharmony_ci        0,
505e1051a39Sopenharmony_ci        1,
506e1051a39Sopenharmony_ci        1,
507e1051a39Sopenharmony_ci        "X",
508e1051a39Sopenharmony_ci        "X"
509e1051a39Sopenharmony_ci    );
510e1051a39Sopenharmony_ci
511e1051a39Sopenharmony_ci    #Find ServerHello record and insert after that
512e1051a39Sopenharmony_ci    my $i;
513e1051a39Sopenharmony_ci    for ($i = 0; ${$proxy->record_list}[$i]->flight() < 1; $i++) {
514e1051a39Sopenharmony_ci        next;
515e1051a39Sopenharmony_ci    }
516e1051a39Sopenharmony_ci    $i++;
517e1051a39Sopenharmony_ci
518e1051a39Sopenharmony_ci    splice @{$proxy->record_list}, $i, 0, $record;
519e1051a39Sopenharmony_ci    $added_record = 1;
520e1051a39Sopenharmony_ci}
521e1051a39Sopenharmony_ci
522e1051a39Sopenharmony_cisub change_version
523e1051a39Sopenharmony_ci{
524e1051a39Sopenharmony_ci    my $proxy = shift;
525e1051a39Sopenharmony_ci    my $records = $proxy->record_list;
526e1051a39Sopenharmony_ci
527e1051a39Sopenharmony_ci    # We'll change a version after the initial version neg has taken place
528e1051a39Sopenharmony_ci    if ($proxy->flight != 1) {
529e1051a39Sopenharmony_ci        $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 70;
530e1051a39Sopenharmony_ci        return;
531e1051a39Sopenharmony_ci    }
532e1051a39Sopenharmony_ci
533e1051a39Sopenharmony_ci    if ($#{$records} > 1) {
534e1051a39Sopenharmony_ci        # ... typically in ServerHelloDone
535e1051a39Sopenharmony_ci        @{$records}[-1]->version(TLSProxy::Record::VERS_TLS_1_1);
536e1051a39Sopenharmony_ci    }
537e1051a39Sopenharmony_ci}
538e1051a39Sopenharmony_ci
539e1051a39Sopenharmony_cisub change_outer_record_type
540e1051a39Sopenharmony_ci{
541e1051a39Sopenharmony_ci    my $proxy = shift;
542e1051a39Sopenharmony_ci    my $records = $proxy->record_list;
543e1051a39Sopenharmony_ci
544e1051a39Sopenharmony_ci    # We'll change a record after the initial version neg has taken place
545e1051a39Sopenharmony_ci    if ($proxy->flight != 1) {
546e1051a39Sopenharmony_ci        $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
547e1051a39Sopenharmony_ci        return;
548e1051a39Sopenharmony_ci    }
549e1051a39Sopenharmony_ci
550e1051a39Sopenharmony_ci    # Find CCS record and change record after that
551e1051a39Sopenharmony_ci    my $i = 0;
552e1051a39Sopenharmony_ci    foreach my $record (@{$records}) {
553e1051a39Sopenharmony_ci        last if $record->content_type == TLSProxy::Record::RT_CCS;
554e1051a39Sopenharmony_ci        $i++;
555e1051a39Sopenharmony_ci    }
556e1051a39Sopenharmony_ci    if (defined(${$records}[++$i])) {
557e1051a39Sopenharmony_ci        ${$records}[$i]->outer_content_type(TLSProxy::Record::RT_HANDSHAKE);
558e1051a39Sopenharmony_ci    }
559e1051a39Sopenharmony_ci}
560e1051a39Sopenharmony_ci
561e1051a39Sopenharmony_cisub not_on_record_boundary
562e1051a39Sopenharmony_ci{
563e1051a39Sopenharmony_ci    my $proxy = shift;
564e1051a39Sopenharmony_ci    my $records = $proxy->record_list;
565e1051a39Sopenharmony_ci    my $data;
566e1051a39Sopenharmony_ci
567e1051a39Sopenharmony_ci    #Find server's first flight
568e1051a39Sopenharmony_ci    if ($proxy->flight != 1) {
569e1051a39Sopenharmony_ci        $fatal_alert = 1 if @{$records}[-1]->is_fatal_alert(0) == 10;
570e1051a39Sopenharmony_ci        return;
571e1051a39Sopenharmony_ci    }
572e1051a39Sopenharmony_ci
573e1051a39Sopenharmony_ci    if ($boundary_test_type == DATA_AFTER_SERVER_HELLO) {
574e1051a39Sopenharmony_ci        #Merge the ServerHello and EncryptedExtensions records into one
575e1051a39Sopenharmony_ci        my $i = 0;
576e1051a39Sopenharmony_ci        foreach my $record (@{$records}) {
577e1051a39Sopenharmony_ci            if ($record->content_type == TLSProxy::Record::RT_HANDSHAKE) {
578e1051a39Sopenharmony_ci                $record->{sent} = 1;    # pretend it's sent already
579e1051a39Sopenharmony_ci                last;
580e1051a39Sopenharmony_ci            }
581e1051a39Sopenharmony_ci            $i++;
582e1051a39Sopenharmony_ci        }
583e1051a39Sopenharmony_ci
584e1051a39Sopenharmony_ci        if (defined(${$records}[$i+1])) {
585e1051a39Sopenharmony_ci            $data = ${$records}[$i]->data();
586e1051a39Sopenharmony_ci            $data .= ${$records}[$i+1]->decrypt_data();
587e1051a39Sopenharmony_ci            ${$records}[$i+1]->data($data);
588e1051a39Sopenharmony_ci            ${$records}[$i+1]->len(length $data);
589e1051a39Sopenharmony_ci
590e1051a39Sopenharmony_ci            #Delete the old ServerHello record
591e1051a39Sopenharmony_ci            splice @{$records}, $i, 1;
592e1051a39Sopenharmony_ci        }
593e1051a39Sopenharmony_ci    } elsif ($boundary_test_type == DATA_AFTER_FINISHED) {
594e1051a39Sopenharmony_ci        return if @{$proxy->{message_list}}[-1]->{mt}
595e1051a39Sopenharmony_ci                  != TLSProxy::Message::MT_FINISHED;
596e1051a39Sopenharmony_ci
597e1051a39Sopenharmony_ci        my $last_record = @{$records}[-1];
598e1051a39Sopenharmony_ci        $data = $last_record->decrypt_data;
599e1051a39Sopenharmony_ci
600e1051a39Sopenharmony_ci        #Add a KeyUpdate message onto the end of the Finished record
601e1051a39Sopenharmony_ci        my $keyupdate = pack "C5",
602e1051a39Sopenharmony_ci            0x18, # KeyUpdate
603e1051a39Sopenharmony_ci            0x00, 0x00, 0x01, # Message length
604e1051a39Sopenharmony_ci            0x00; # Update not requested
605e1051a39Sopenharmony_ci
606e1051a39Sopenharmony_ci        $data .= $keyupdate;
607e1051a39Sopenharmony_ci
608e1051a39Sopenharmony_ci        #Add content type and tag
609e1051a39Sopenharmony_ci        $data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
610e1051a39Sopenharmony_ci
611e1051a39Sopenharmony_ci        #Update the record
612e1051a39Sopenharmony_ci        $last_record->data($data);
613e1051a39Sopenharmony_ci        $last_record->len(length $data);
614e1051a39Sopenharmony_ci    } elsif ($boundary_test_type == DATA_AFTER_KEY_UPDATE) {
615e1051a39Sopenharmony_ci        return if @{$proxy->{message_list}}[-1]->{mt}
616e1051a39Sopenharmony_ci                  != TLSProxy::Message::MT_FINISHED;
617e1051a39Sopenharmony_ci
618e1051a39Sopenharmony_ci        #KeyUpdates must end on a record boundary
619e1051a39Sopenharmony_ci
620e1051a39Sopenharmony_ci        my $record = TLSProxy::Record->new(
621e1051a39Sopenharmony_ci            1,
622e1051a39Sopenharmony_ci            TLSProxy::Record::RT_APPLICATION_DATA,
623e1051a39Sopenharmony_ci            TLSProxy::Record::VERS_TLS_1_2,
624e1051a39Sopenharmony_ci            0,
625e1051a39Sopenharmony_ci            0,
626e1051a39Sopenharmony_ci            0,
627e1051a39Sopenharmony_ci            0,
628e1051a39Sopenharmony_ci            "",
629e1051a39Sopenharmony_ci            ""
630e1051a39Sopenharmony_ci        );
631e1051a39Sopenharmony_ci
632e1051a39Sopenharmony_ci        #Add two KeyUpdate messages into a single record
633e1051a39Sopenharmony_ci        my $keyupdate = pack "C5",
634e1051a39Sopenharmony_ci            0x18, # KeyUpdate
635e1051a39Sopenharmony_ci            0x00, 0x00, 0x01, # Message length
636e1051a39Sopenharmony_ci            0x00; # Update not requested
637e1051a39Sopenharmony_ci
638e1051a39Sopenharmony_ci        $data = $keyupdate.$keyupdate;
639e1051a39Sopenharmony_ci
640e1051a39Sopenharmony_ci        #Add content type and tag
641e1051a39Sopenharmony_ci        $data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
642e1051a39Sopenharmony_ci
643e1051a39Sopenharmony_ci        $record->data($data);
644e1051a39Sopenharmony_ci        $record->len(length $data);
645e1051a39Sopenharmony_ci        push @{$records}, $record;
646e1051a39Sopenharmony_ci    } else {
647e1051a39Sopenharmony_ci        return if @{$proxy->{message_list}}[-1]->{mt}
648e1051a39Sopenharmony_ci                  != TLSProxy::Message::MT_FINISHED;
649e1051a39Sopenharmony_ci
650e1051a39Sopenharmony_ci        my $record = TLSProxy::Record->new(
651e1051a39Sopenharmony_ci            1,
652e1051a39Sopenharmony_ci            TLSProxy::Record::RT_APPLICATION_DATA,
653e1051a39Sopenharmony_ci            TLSProxy::Record::VERS_TLS_1_2,
654e1051a39Sopenharmony_ci            0,
655e1051a39Sopenharmony_ci            0,
656e1051a39Sopenharmony_ci            0,
657e1051a39Sopenharmony_ci            0,
658e1051a39Sopenharmony_ci            "",
659e1051a39Sopenharmony_ci            ""
660e1051a39Sopenharmony_ci        );
661e1051a39Sopenharmony_ci
662e1051a39Sopenharmony_ci        #Add a partial KeyUpdate message into the record
663e1051a39Sopenharmony_ci        $data = pack "C1",
664e1051a39Sopenharmony_ci            0x18; # KeyUpdate message type. Omit the rest of the message header
665e1051a39Sopenharmony_ci
666e1051a39Sopenharmony_ci        #Add content type and tag
667e1051a39Sopenharmony_ci        $data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
668e1051a39Sopenharmony_ci
669e1051a39Sopenharmony_ci        $record->data($data);
670e1051a39Sopenharmony_ci        $record->len(length $data);
671e1051a39Sopenharmony_ci        push @{$records}, $record;
672e1051a39Sopenharmony_ci
673e1051a39Sopenharmony_ci        if ($boundary_test_type == DATA_BETWEEN_KEY_UPDATE) {
674e1051a39Sopenharmony_ci            #Now add an app data record
675e1051a39Sopenharmony_ci            $record = TLSProxy::Record->new(
676e1051a39Sopenharmony_ci                1,
677e1051a39Sopenharmony_ci                TLSProxy::Record::RT_APPLICATION_DATA,
678e1051a39Sopenharmony_ci                TLSProxy::Record::VERS_TLS_1_2,
679e1051a39Sopenharmony_ci                0,
680e1051a39Sopenharmony_ci                0,
681e1051a39Sopenharmony_ci                0,
682e1051a39Sopenharmony_ci                0,
683e1051a39Sopenharmony_ci                "",
684e1051a39Sopenharmony_ci                ""
685e1051a39Sopenharmony_ci            );
686e1051a39Sopenharmony_ci
687e1051a39Sopenharmony_ci            #Add an empty app data record (just content type and tag)
688e1051a39Sopenharmony_ci            $data = pack("C", TLSProxy::Record::RT_APPLICATION_DATA).("\0"x16);
689e1051a39Sopenharmony_ci
690e1051a39Sopenharmony_ci            $record->data($data);
691e1051a39Sopenharmony_ci            $record->len(length $data);
692e1051a39Sopenharmony_ci            push @{$records}, $record;
693e1051a39Sopenharmony_ci        }
694e1051a39Sopenharmony_ci
695e1051a39Sopenharmony_ci        #Now add the rest of the KeyUpdate message
696e1051a39Sopenharmony_ci        $record = TLSProxy::Record->new(
697e1051a39Sopenharmony_ci            1,
698e1051a39Sopenharmony_ci            TLSProxy::Record::RT_APPLICATION_DATA,
699e1051a39Sopenharmony_ci            TLSProxy::Record::VERS_TLS_1_2,
700e1051a39Sopenharmony_ci            0,
701e1051a39Sopenharmony_ci            0,
702e1051a39Sopenharmony_ci            0,
703e1051a39Sopenharmony_ci            0,
704e1051a39Sopenharmony_ci            "",
705e1051a39Sopenharmony_ci            ""
706e1051a39Sopenharmony_ci        );
707e1051a39Sopenharmony_ci
708e1051a39Sopenharmony_ci        #Add the last 4 bytes of the KeyUpdate record
709e1051a39Sopenharmony_ci        $data = pack "C4",
710e1051a39Sopenharmony_ci            0x00, 0x00, 0x01, # Message length
711e1051a39Sopenharmony_ci            0x00; # Update not requested
712e1051a39Sopenharmony_ci
713e1051a39Sopenharmony_ci        #Add content type and tag
714e1051a39Sopenharmony_ci        $data .= pack("C", TLSProxy::Record::RT_HANDSHAKE).("\0"x16);
715e1051a39Sopenharmony_ci
716e1051a39Sopenharmony_ci        $record->data($data);
717e1051a39Sopenharmony_ci        $record->len(length $data);
718e1051a39Sopenharmony_ci        push @{$records}, $record;
719e1051a39Sopenharmony_ci
720e1051a39Sopenharmony_ci    }
721e1051a39Sopenharmony_ci}
722