105901b04Schristos#! /usr/bin/env perl 2aa42b575Schristos# Copyright 2017-2022 The OpenSSL Project Authors. All Rights Reserved. 305901b04Schristos# 4*66bae5e7Schristos# Licensed under the Apache License 2.0 (the "License"). You may not use 505901b04Schristos# this file except in compliance with the License. You can obtain a copy 605901b04Schristos# in the file LICENSE in the source distribution or at 705901b04Schristos# https://www.openssl.org/source/license.html 805901b04Schristos 905901b04Schristosuse strict; 1005901b04Schristosuse OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/; 1105901b04Schristosuse OpenSSL::Test::Utils; 1205901b04Schristosuse TLSProxy::Proxy; 1305901b04Schristos 1405901b04Schristosmy $test_name = "test_tls13hrr"; 1505901b04Schristossetup($test_name); 1605901b04Schristos 1705901b04Schristosplan skip_all => "TLSProxy isn't usable on $^O" 1805901b04Schristos if $^O =~ /^(VMS)$/; 1905901b04Schristos 2005901b04Schristosplan skip_all => "$test_name needs the dynamic engine feature enabled" 2105901b04Schristos if disabled("engine") || disabled("dynamic-engine"); 2205901b04Schristos 2305901b04Schristosplan skip_all => "$test_name needs the sock feature enabled" 2405901b04Schristos if disabled("sock"); 2505901b04Schristos 2605901b04Schristosplan skip_all => "$test_name needs TLS1.3 enabled" 27*66bae5e7Schristos if disabled("tls1_3") || (disabled("ec") && disabled("dh")); 2805901b04Schristos 2905901b04Schristos$ENV{OPENSSL_ia32cap} = '~0x200000200000000'; 3005901b04Schristos 3105901b04Schristosmy $proxy = TLSProxy::Proxy->new( 3205901b04Schristos undef, 3305901b04Schristos cmdstr(app(["openssl"]), display => 1), 3405901b04Schristos srctop_file("apps", "server.pem"), 3505901b04Schristos (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) 3605901b04Schristos); 3705901b04Schristos 3805901b04Schristosuse constant { 3905901b04Schristos CHANGE_HRR_CIPHERSUITE => 0, 40aa42b575Schristos CHANGE_CH1_CIPHERSUITE => 1, 41aa42b575Schristos DUPLICATE_HRR => 2 4205901b04Schristos}; 4305901b04Schristos 4405901b04Schristos#Test 1: A client should fail if the server changes the ciphersuite between the 4505901b04Schristos# HRR and the SH 4605901b04Schristos$proxy->filter(\&hrr_filter); 47*66bae5e7Schristosif (disabled("ec")) { 48*66bae5e7Schristos $proxy->serverflags("-curves ffdhe3072"); 49*66bae5e7Schristos} else { 5005901b04Schristos $proxy->serverflags("-curves P-256"); 51*66bae5e7Schristos} 5205901b04Schristosmy $testtype = CHANGE_HRR_CIPHERSUITE; 5305901b04Schristos$proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; 54aa42b575Schristosplan tests => 3; 5505901b04Schristosok(TLSProxy::Message->fail(), "Server ciphersuite changes"); 5605901b04Schristos 5705901b04Schristos#Test 2: It is an error if the client changes the offered ciphersuites so that 5805901b04Schristos# we end up selecting a different ciphersuite between HRR and the SH 5905901b04Schristos$proxy->clear(); 60*66bae5e7Schristosif (disabled("ec")) { 61*66bae5e7Schristos $proxy->serverflags("-curves ffdhe3072"); 62*66bae5e7Schristos} else { 6305901b04Schristos $proxy->serverflags("-curves P-256"); 64*66bae5e7Schristos} 6505901b04Schristos$proxy->ciphersuitess("TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384"); 6605901b04Schristos$testtype = CHANGE_CH1_CIPHERSUITE; 6705901b04Schristos$proxy->start(); 6805901b04Schristosok(TLSProxy::Message->fail(), "Client ciphersuite changes"); 6905901b04Schristos 70aa42b575Schristos#Test 3: A client should fail with unexpected_message alert if the server 71aa42b575Schristos# sends more than 1 HRR 72aa42b575Schristosmy $fatal_alert = 0; 73aa42b575Schristos$proxy->clear(); 74aa42b575Schristosif (disabled("ec")) { 75aa42b575Schristos $proxy->serverflags("-curves ffdhe3072"); 76aa42b575Schristos} else { 77aa42b575Schristos $proxy->serverflags("-curves P-256"); 78aa42b575Schristos} 79aa42b575Schristos$testtype = DUPLICATE_HRR; 80aa42b575Schristos$proxy->start(); 81aa42b575Schristosok($fatal_alert, "Server duplicated HRR"); 82aa42b575Schristos 8305901b04Schristossub hrr_filter 8405901b04Schristos{ 8505901b04Schristos my $proxy = shift; 8605901b04Schristos 8705901b04Schristos if ($testtype == CHANGE_HRR_CIPHERSUITE) { 8805901b04Schristos # We're only interested in the HRR 8905901b04Schristos if ($proxy->flight != 1) { 9005901b04Schristos return; 9105901b04Schristos } 9205901b04Schristos 9305901b04Schristos my $hrr = ${$proxy->message_list}[1]; 9405901b04Schristos 9505901b04Schristos # We will normally only ever select CIPHER_TLS13_AES_128_GCM_SHA256 9605901b04Schristos # because that's what Proxy tells s_server to do. Setting as below means 9705901b04Schristos # the ciphersuite will change will we get the ServerHello 9805901b04Schristos $hrr->ciphersuite(TLSProxy::Message::CIPHER_TLS13_AES_256_GCM_SHA384); 9905901b04Schristos $hrr->repack(); 10005901b04Schristos return; 10105901b04Schristos } 10205901b04Schristos 103aa42b575Schristos if ($testtype == DUPLICATE_HRR) { 104aa42b575Schristos # We're only interested in the HRR 105aa42b575Schristos # and the unexpected_message alert from client 106aa42b575Schristos if ($proxy->flight == 4) { 107aa42b575Schristos $fatal_alert = 1 108aa42b575Schristos if @{$proxy->record_list}[-1]->is_fatal_alert(0) == 10; 109aa42b575Schristos return; 110aa42b575Schristos } 111aa42b575Schristos if ($proxy->flight != 3) { 112aa42b575Schristos return; 113aa42b575Schristos } 114aa42b575Schristos 115aa42b575Schristos # Find ServerHello record (HRR actually) and insert after that 116aa42b575Schristos my $i; 117aa42b575Schristos for ($i = 0; ${$proxy->record_list}[$i]->flight() < 1; $i++) { 118aa42b575Schristos next; 119aa42b575Schristos } 120aa42b575Schristos my $hrr_record = ${$proxy->record_list}[$i]; 121aa42b575Schristos my $dup_hrr = TLSProxy::Record->new(3, 122aa42b575Schristos $hrr_record->content_type(), 123aa42b575Schristos $hrr_record->version(), 124aa42b575Schristos $hrr_record->len(), 125aa42b575Schristos $hrr_record->sslv2(), 126aa42b575Schristos $hrr_record->len_real(), 127aa42b575Schristos $hrr_record->decrypt_len(), 128aa42b575Schristos $hrr_record->data(), 129aa42b575Schristos $hrr_record->decrypt_data()); 130aa42b575Schristos 131aa42b575Schristos $i++; 132aa42b575Schristos splice @{$proxy->record_list}, $i, 0, $dup_hrr; 133aa42b575Schristos return; 134aa42b575Schristos } 135aa42b575Schristos 13605901b04Schristos # CHANGE_CH1_CIPHERSUITE 13705901b04Schristos if ($proxy->flight != 0) { 13805901b04Schristos return; 13905901b04Schristos } 14005901b04Schristos 14105901b04Schristos my $ch1 = ${$proxy->message_list}[0]; 14205901b04Schristos 14305901b04Schristos # The server will always pick TLS_AES_256_GCM_SHA384 14405901b04Schristos my @ciphersuites = (TLSProxy::Message::CIPHER_TLS13_AES_128_GCM_SHA256); 14505901b04Schristos $ch1->ciphersuite_len(2 * scalar @ciphersuites); 14605901b04Schristos $ch1->ciphersuites(\@ciphersuites); 14705901b04Schristos $ch1->repack(); 14805901b04Schristos} 149