]>
Commit | Line | Data |
---|---|---|
a2de7943 | 1 | #! /usr/bin/env perl |
a28d06f3 | 2 | # Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved. |
a2de7943 | 3 | # |
909f1a2e | 4 | # Licensed under the Apache License 2.0 (the "License"). You may not use |
a2de7943 MC |
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 | ||
9 | use strict; | |
10 | use OpenSSL::Test qw/:DEFAULT cmdstr srctop_file bldtop_dir/; | |
11 | use OpenSSL::Test::Utils; | |
12 | use TLSProxy::Proxy; | |
13 | ||
14 | my $test_name = "test_sslsignature"; | |
15 | setup($test_name); | |
16 | ||
17 | plan skip_all => "TLSProxy isn't usable on $^O" | |
c5856878 | 18 | if $^O =~ /^(VMS)$/; |
a2de7943 MC |
19 | |
20 | plan skip_all => "$test_name needs the dynamic engine feature enabled" | |
21 | if disabled("engine") || disabled("dynamic-engine"); | |
22 | ||
23 | plan skip_all => "$test_name needs the sock feature enabled" | |
24 | if disabled("sock"); | |
25 | ||
26 | plan skip_all => "$test_name needs TLS enabled" | |
27 | if alldisabled(available_protocols("tls")); | |
28 | ||
29 | $ENV{OPENSSL_ia32cap} = '~0x200000200000000'; | |
30 | my $proxy = TLSProxy::Proxy->new( | |
31 | undef, | |
32 | cmdstr(app(["openssl"]), display => 1), | |
33 | srctop_file("apps", "server.pem"), | |
34 | (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) | |
35 | ); | |
36 | ||
37 | use constant { | |
38 | NO_CORRUPTION => 0, | |
39 | CORRUPT_SERVER_CERT_VERIFY => 1, | |
40 | CORRUPT_CLIENT_CERT_VERIFY => 2, | |
41 | CORRUPT_TLS1_2_SERVER_KEY_EXCHANGE => 3, | |
42 | }; | |
43 | ||
44 | $proxy->filter(\&signature_filter); | |
45 | ||
46 | #Test 1: No corruption should succeed | |
47 | my $testtype = NO_CORRUPTION; | |
a763ca11 | 48 | $proxy->clientflags("-no_tls1_3") if disabled("ec") && disabled("dh"); |
a2de7943 MC |
49 | $proxy->start() or plan skip_all => "Unable to start up Proxy for tests"; |
50 | plan tests => 4; | |
51 | ok(TLSProxy::Message->success, "No corruption"); | |
52 | ||
53 | SKIP: { | |
a763ca11 MC |
54 | skip "TLSv1.3 disabled", 1 |
55 | if disabled("tls1_3") || (disabled("ec") && disabled("dh")); | |
a2de7943 MC |
56 | |
57 | #Test 2: Corrupting a server CertVerify signature in TLSv1.3 should fail | |
58 | $proxy->clear(); | |
59 | $testtype = CORRUPT_SERVER_CERT_VERIFY; | |
60 | $proxy->start(); | |
61 | ok(TLSProxy::Message->fail, "Corrupt server TLSv1.3 CertVerify"); | |
62 | ||
63 | #Test x: Corrupting a client CertVerify signature in TLSv1.3 should fail | |
64 | #$proxy->clear(); | |
65 | #$testtype = CORRUPT_CLIENT_CERT_VERIFY; | |
66 | #$proxy->serverflags("-Verify 5"); | |
67 | #$proxy->clientflags("-cert ".srctop_file("apps", "server.pem")); | |
68 | #$proxy->start(); | |
69 | #ok(TLSProxy::Message->fail, "Corrupt client TLSv1.3 CertVerify"); | |
70 | #TODO(TLS1.3): This test fails due to a problem in s_server/TLSProxy. | |
71 | #Currently a connection is counted as "successful" if the client ends it | |
72 | #with a close_notify. In TLSProxy the client initiates the closure of the | |
73 | #connection so really we should not count it as successful until s_server | |
74 | #has also responded with a close_notify. However s_server never sends a | |
75 | #close_notify - it just closes the connection. Fixing this would be a | |
76 | #significant change to the long established behaviour of s_server. | |
77 | #Unfortunately in this test, it is the server that notices the incorrect | |
78 | #signature and responds with an appropriate alert. However s_client never | |
79 | #sees that because it occurs after the server Finished has been sent. | |
80 | #Therefore s_client just continues to send its application data and sends | |
81 | #its close_notify regardless. TLSProxy sees this and thinks that the | |
82 | #connection was successful when in fact it was not. There isn't an easy fix | |
83 | #for this, so leaving this test commented out for now. | |
84 | } | |
85 | ||
86 | SKIP: { | |
87 | skip "TLS <= 1.2 disabled", 2 | |
88 | if alldisabled(("ssl3", "tls1", "tls1_1", "tls1_2")); | |
89 | ||
90 | #Test 3: Corrupting a CertVerify signature in <=TLSv1.2 should fail | |
91 | $proxy->clear(); | |
92 | $testtype = CORRUPT_CLIENT_CERT_VERIFY; | |
93 | $proxy->serverflags("-Verify 5"); | |
94 | $proxy->clientflags("-no_tls1_3 -cert ".srctop_file("apps", "server.pem")); | |
95 | $proxy->start(); | |
96 | ok(TLSProxy::Message->fail, "Corrupt <=TLSv1.2 CertVerify"); | |
97 | ||
928933f9 MC |
98 | SKIP: { |
99 | skip "DH disabled", 1 if disabled("dh"); | |
100 | ||
101 | #Test 4: Corrupting a ServerKeyExchange signature in <=TLSv1.2 should | |
102 | #fail | |
103 | $proxy->clear(); | |
104 | $testtype = CORRUPT_TLS1_2_SERVER_KEY_EXCHANGE; | |
105 | $proxy->clientflags("-no_tls1_3"); | |
106 | $proxy->cipherc('DHE-RSA-AES128-SHA'); | |
107 | $proxy->ciphers('DHE-RSA-AES128-SHA'); | |
108 | $proxy->start(); | |
109 | ok(TLSProxy::Message->fail, "Corrupt <=TLSv1.2 ServerKeyExchange"); | |
110 | } | |
a2de7943 MC |
111 | } |
112 | ||
113 | sub signature_filter | |
114 | { | |
115 | my $proxy = shift; | |
116 | my $flight; | |
117 | my $mt = TLSProxy::Message::MT_CERTIFICATE_VERIFY; | |
118 | ||
119 | if ($testtype == CORRUPT_SERVER_CERT_VERIFY | |
120 | || $testtype == CORRUPT_TLS1_2_SERVER_KEY_EXCHANGE | |
121 | || (!disabled("tls1_3") && $testtype == NO_CORRUPTION)) { | |
122 | $flight = 1; | |
123 | } else { | |
124 | $flight = 2; | |
125 | } | |
126 | ||
127 | # We're only interested in the initial server flight | |
128 | return if ($proxy->flight != $flight); | |
129 | ||
130 | $mt = TLSProxy::Message::MT_SERVER_KEY_EXCHANGE | |
131 | if ($testtype == CORRUPT_TLS1_2_SERVER_KEY_EXCHANGE); | |
132 | ||
133 | foreach my $message (@{$proxy->message_list}) { | |
134 | if ($message->mt == $mt) { | |
135 | my $sig = $message->signature(); | |
136 | my $sigbase = substr($sig, 0, -1); | |
137 | my $sigend = unpack("C", substr($sig, -1)); | |
138 | ||
139 | #Flip bits in final byte of signature to corrupt the sig | |
140 | $sigend ^= 0xff unless $testtype == NO_CORRUPTION; | |
141 | ||
142 | $message->signature($sigbase.pack("C", $sigend)); | |
143 | $message->repack(); | |
144 | } | |
145 | } | |
146 | } |