1 1.1 christos #! /usr/bin/env perl 2 1.1 christos # Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos # 4 1.1 christos # Licensed under the OpenSSL license (the "License"). You may not use 5 1.1 christos # this file except in compliance with the License. You can obtain a copy 6 1.1 christos # in the file LICENSE in the source distribution or at 7 1.1 christos # https://www.openssl.org/source/license.html 8 1.1 christos 9 1.1 christos use strict; 10 1.1 christos use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/; 11 1.1 christos use OpenSSL::Test::Utils; 12 1.1 christos use TLSProxy::Proxy; 13 1.1 christos 14 1.1 christos my $test_name = "test_tls13hrr"; 15 1.1 christos setup($test_name); 16 1.1 christos 17 1.1 christos plan skip_all => "TLSProxy isn't usable on $^O" 18 1.1 christos if $^O =~ /^(VMS)$/; 19 1.1 christos 20 1.1 christos plan skip_all => "$test_name needs the dynamic engine feature enabled" 21 1.1 christos if disabled("engine") || disabled("dynamic-engine"); 22 1.1 christos 23 1.1 christos plan skip_all => "$test_name needs the sock feature enabled" 24 1.1 christos if disabled("sock"); 25 1.1 christos 26 1.1 christos plan skip_all => "$test_name needs TLS1.3 enabled" 27 1.1 christos if disabled("tls1_3"); 28 1.1 christos 29 1.1 christos $ENV{OPENSSL_ia32cap} = '~0x200000200000000'; 30 1.1 christos 31 1.1 christos my $proxy = TLSProxy::Proxy->new( 32 1.1 christos undef, 33 1.1 christos cmdstr(app(["openssl"]), display => 1), 34 1.1 christos srctop_file("apps", "server.pem"), 35 1.1 christos (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) 36 1.1 christos ); 37 1.1 christos 38 1.1 christos use constant { 39 1.1 christos CHANGE_HRR_CIPHERSUITE => 0, 40 1.1 christos CHANGE_CH1_CIPHERSUITE => 1, 41 1.1 christos DUPLICATE_HRR => 2 42 1.1 christos }; 43 1.1 christos 44 1.1 christos #Test 1: A client should fail if the server changes the ciphersuite between the 45 1.1 christos # HRR and the SH 46 1.1 christos $proxy->filter(\&hrr_filter); 47 1.1 christos $proxy->serverflags("-curves P-256"); 48 1.1 christos my $testtype = CHANGE_HRR_CIPHERSUITE; 49 1.1 christos $proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; 50 1.1 christos plan tests => 3; 51 1.1 christos ok(TLSProxy::Message->fail(), "Server ciphersuite changes"); 52 1.1 christos 53 1.1 christos #Test 2: It is an error if the client changes the offered ciphersuites so that 54 1.1 christos # we end up selecting a different ciphersuite between HRR and the SH 55 1.1 christos $proxy->clear(); 56 1.1 christos $proxy->serverflags("-curves P-256"); 57 1.1 christos $proxy->ciphersuitess("TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384"); 58 1.1 christos $testtype = CHANGE_CH1_CIPHERSUITE; 59 1.1 christos $proxy->start(); 60 1.1 christos ok(TLSProxy::Message->fail(), "Client ciphersuite changes"); 61 1.1 christos 62 1.1 christos #Test 3: A client should fail with unexpected_message alert if the server 63 1.1 christos # sends more than 1 HRR 64 1.1 christos my $fatal_alert = 0; 65 1.1 christos $proxy->clear(); 66 1.1 christos if (disabled("ec")) { 67 1.1 christos $proxy->serverflags("-curves ffdhe3072"); 68 1.1 christos } else { 69 1.1 christos $proxy->serverflags("-curves P-256"); 70 1.1 christos } 71 1.1 christos $testtype = DUPLICATE_HRR; 72 1.1 christos $proxy->start(); 73 1.1 christos ok($fatal_alert, "Server duplicated HRR"); 74 1.1 christos 75 1.1 christos sub hrr_filter 76 1.1 christos { 77 1.1 christos my $proxy = shift; 78 1.1 christos 79 1.1 christos if ($testtype == CHANGE_HRR_CIPHERSUITE) { 80 1.1 christos # We're only interested in the HRR 81 1.1 christos if ($proxy->flight != 1) { 82 1.1 christos return; 83 1.1 christos } 84 1.1 christos 85 1.1 christos my $hrr = ${$proxy->message_list}[1]; 86 1.1 christos 87 1.1 christos # We will normally only ever select CIPHER_TLS13_AES_128_GCM_SHA256 88 1.1 christos # because that's what Proxy tells s_server to do. Setting as below means 89 1.1 christos # the ciphersuite will change will we get the ServerHello 90 1.1 christos $hrr->ciphersuite(TLSProxy::Message::CIPHER_TLS13_AES_256_GCM_SHA384); 91 1.1 christos $hrr->repack(); 92 1.1 christos return; 93 1.1 christos } 94 1.1 christos 95 1.1 christos if ($testtype == DUPLICATE_HRR) { 96 1.1 christos # We're only interested in the HRR 97 1.1 christos # and the unexpected_message alert from client 98 1.1 christos if ($proxy->flight == 4) { 99 1.1 christos $fatal_alert = 1 100 1.1 christos if @{$proxy->record_list}[-1]->is_fatal_alert(0) == 10; 101 1.1 christos return; 102 1.1 christos } 103 1.1 christos if ($proxy->flight != 3) { 104 1.1 christos return; 105 1.1 christos } 106 1.1 christos 107 1.1 christos # Find ServerHello record (HRR actually) and insert after that 108 1.1 christos my $i; 109 1.1 christos for ($i = 0; ${$proxy->record_list}[$i]->flight() < 1; $i++) { 110 1.1 christos next; 111 1.1 christos } 112 1.1 christos my $hrr_record = ${$proxy->record_list}[$i]; 113 1.1 christos my $dup_hrr = TLSProxy::Record->new(3, 114 1.1 christos $hrr_record->content_type(), 115 1.1 christos $hrr_record->version(), 116 1.1 christos $hrr_record->len(), 117 1.1 christos $hrr_record->sslv2(), 118 1.1 christos $hrr_record->len_real(), 119 1.1 christos $hrr_record->decrypt_len(), 120 1.1 christos $hrr_record->data(), 121 1.1 christos $hrr_record->decrypt_data()); 122 1.1 christos 123 1.1 christos $i++; 124 1.1 christos splice @{$proxy->record_list}, $i, 0, $dup_hrr; 125 1.1 christos return; 126 1.1 christos } 127 1.1 christos 128 1.1 christos # CHANGE_CH1_CIPHERSUITE 129 1.1 christos if ($proxy->flight != 0) { 130 1.1 christos return; 131 1.1 christos } 132 1.1 christos 133 1.1 christos my $ch1 = ${$proxy->message_list}[0]; 134 1.1 christos 135 1.1 christos # The server will always pick TLS_AES_256_GCM_SHA384 136 1.1 christos my @ciphersuites = (TLSProxy::Message::CIPHER_TLS13_AES_128_GCM_SHA256); 137 1.1 christos $ch1->ciphersuite_len(2 * scalar @ciphersuites); 138 1.1 christos $ch1->ciphersuites(\@ciphersuites); 139 1.1 christos $ch1->repack(); 140 1.1 christos } 141