1#! /usr/bin/env perl 2# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. 3# 4# Licensed under the OpenSSL license (the "License"). You may not use 5# this file except in compliance with the License. You can obtain a copy 6# in the file LICENSE in the source distribution or at 7# https://www.openssl.org/source/license.html 8 9use strict; 10use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/; 11use OpenSSL::Test::Utils; 12use TLSProxy::Proxy; 13 14my $test_name = "test_sslcbcpadding"; 15setup($test_name); 16 17plan skip_all => "TLSProxy isn't usable on $^O" 18 if $^O =~ /^(VMS)$/; 19 20plan skip_all => "$test_name needs the dynamic engine feature enabled" 21 if disabled("engine") || disabled("dynamic-engine"); 22 23plan skip_all => "$test_name needs the sock feature enabled" 24 if disabled("sock"); 25 26plan skip_all => "$test_name needs TLSv1.2 enabled" 27 if disabled("tls1_2"); 28 29$ENV{OPENSSL_ia32cap} = '~0x200000200000000'; 30my $proxy = TLSProxy::Proxy->new( 31 \&add_maximal_padding_filter, 32 cmdstr(app(["openssl"]), display => 1), 33 srctop_file("apps", "server.pem"), 34 (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) 35); 36 37# TODO: We could test all 256 values, but then the log file gets too large for 38# CI. See https://github.com/openssl/openssl/issues/1440. 39my @test_offsets = (0, 128, 254, 255); 40 41# Test that maximally-padded records are accepted. 42my $bad_padding_offset = -1; 43$proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; 44plan tests => 1 + scalar(@test_offsets); 45ok(TLSProxy::Message->success(), "Maximally-padded record test"); 46 47# Test that invalid padding is rejected. 48foreach my $offset (@test_offsets) { 49 $proxy->clear(); 50 $bad_padding_offset = $offset; 51 $proxy->start(); 52 ok(TLSProxy::Message->fail(), "Invalid padding byte $bad_padding_offset"); 53} 54 55sub add_maximal_padding_filter 56{ 57 my $proxy = shift; 58 59 if ($proxy->flight == 0) { 60 # Disable Encrypt-then-MAC. 61 foreach my $message (@{$proxy->message_list}) { 62 if ($message->mt != TLSProxy::Message::MT_CLIENT_HELLO) { 63 next; 64 } 65 66 $message->delete_extension(TLSProxy::Message::EXT_ENCRYPT_THEN_MAC); 67 $message->process_extensions(); 68 $message->repack(); 69 } 70 } 71 72 if ($proxy->flight == 3) { 73 # Insert a maximally-padded record. Assume a block size of 16 (AES) and 74 # a MAC length of 20 (SHA-1). 75 my $block_size = 16; 76 my $mac_len = 20; 77 78 # Size the plaintext so that 256 is a valid padding. 79 my $plaintext_len = $block_size - ($mac_len % $block_size); 80 my $plaintext = "A" x $plaintext_len; 81 82 my $data = "B" x $block_size; # Explicit IV. 83 $data .= $plaintext; 84 $data .= TLSProxy::Proxy::fill_known_data($mac_len); # MAC. 85 86 # Add padding. 87 for (my $i = 0; $i < 256; $i++) { 88 if ($i == $bad_padding_offset) { 89 $data .= "\xfe"; 90 } else { 91 $data .= "\xff"; 92 } 93 } 94 95 my $record = TLSProxy::Record->new( 96 $proxy->flight, 97 TLSProxy::Record::RT_APPLICATION_DATA, 98 TLSProxy::Record::VERS_TLS_1_2, 99 length($data), 100 0, 101 length($data), 102 $plaintext_len, 103 $data, 104 $plaintext, 105 ); 106 107 # Send the record immediately after the server Finished. 108 push @{$proxy->record_list}, $record; 109 } 110} 111