1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "quiche/quic/core/crypto/crypto_utils.h"
6
7 #include <string>
8
9 #include "absl/base/macros.h"
10 #include "absl/strings/escaping.h"
11 #include "absl/strings/string_view.h"
12 #include "quiche/quic/core/quic_utils.h"
13 #include "quiche/quic/platform/api/quic_test.h"
14 #include "quiche/quic/test_tools/quic_test_utils.h"
15 #include "quiche/common/test_tools/quiche_test_utils.h"
16
17 namespace quic {
18 namespace test {
19 namespace {
20
21 class CryptoUtilsTest : public QuicTest {};
22
TEST_F(CryptoUtilsTest,HandshakeFailureReasonToString)23 TEST_F(CryptoUtilsTest, HandshakeFailureReasonToString) {
24 EXPECT_STREQ("HANDSHAKE_OK",
25 CryptoUtils::HandshakeFailureReasonToString(HANDSHAKE_OK));
26 EXPECT_STREQ("CLIENT_NONCE_UNKNOWN_FAILURE",
27 CryptoUtils::HandshakeFailureReasonToString(
28 CLIENT_NONCE_UNKNOWN_FAILURE));
29 EXPECT_STREQ("CLIENT_NONCE_INVALID_FAILURE",
30 CryptoUtils::HandshakeFailureReasonToString(
31 CLIENT_NONCE_INVALID_FAILURE));
32 EXPECT_STREQ("CLIENT_NONCE_NOT_UNIQUE_FAILURE",
33 CryptoUtils::HandshakeFailureReasonToString(
34 CLIENT_NONCE_NOT_UNIQUE_FAILURE));
35 EXPECT_STREQ("CLIENT_NONCE_INVALID_ORBIT_FAILURE",
36 CryptoUtils::HandshakeFailureReasonToString(
37 CLIENT_NONCE_INVALID_ORBIT_FAILURE));
38 EXPECT_STREQ("CLIENT_NONCE_INVALID_TIME_FAILURE",
39 CryptoUtils::HandshakeFailureReasonToString(
40 CLIENT_NONCE_INVALID_TIME_FAILURE));
41 EXPECT_STREQ("CLIENT_NONCE_STRIKE_REGISTER_TIMEOUT",
42 CryptoUtils::HandshakeFailureReasonToString(
43 CLIENT_NONCE_STRIKE_REGISTER_TIMEOUT));
44 EXPECT_STREQ("CLIENT_NONCE_STRIKE_REGISTER_FAILURE",
45 CryptoUtils::HandshakeFailureReasonToString(
46 CLIENT_NONCE_STRIKE_REGISTER_FAILURE));
47 EXPECT_STREQ("SERVER_NONCE_DECRYPTION_FAILURE",
48 CryptoUtils::HandshakeFailureReasonToString(
49 SERVER_NONCE_DECRYPTION_FAILURE));
50 EXPECT_STREQ("SERVER_NONCE_INVALID_FAILURE",
51 CryptoUtils::HandshakeFailureReasonToString(
52 SERVER_NONCE_INVALID_FAILURE));
53 EXPECT_STREQ("SERVER_NONCE_NOT_UNIQUE_FAILURE",
54 CryptoUtils::HandshakeFailureReasonToString(
55 SERVER_NONCE_NOT_UNIQUE_FAILURE));
56 EXPECT_STREQ("SERVER_NONCE_INVALID_TIME_FAILURE",
57 CryptoUtils::HandshakeFailureReasonToString(
58 SERVER_NONCE_INVALID_TIME_FAILURE));
59 EXPECT_STREQ("SERVER_NONCE_REQUIRED_FAILURE",
60 CryptoUtils::HandshakeFailureReasonToString(
61 SERVER_NONCE_REQUIRED_FAILURE));
62 EXPECT_STREQ("SERVER_CONFIG_INCHOATE_HELLO_FAILURE",
63 CryptoUtils::HandshakeFailureReasonToString(
64 SERVER_CONFIG_INCHOATE_HELLO_FAILURE));
65 EXPECT_STREQ("SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE",
66 CryptoUtils::HandshakeFailureReasonToString(
67 SERVER_CONFIG_UNKNOWN_CONFIG_FAILURE));
68 EXPECT_STREQ("SOURCE_ADDRESS_TOKEN_INVALID_FAILURE",
69 CryptoUtils::HandshakeFailureReasonToString(
70 SOURCE_ADDRESS_TOKEN_INVALID_FAILURE));
71 EXPECT_STREQ("SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE",
72 CryptoUtils::HandshakeFailureReasonToString(
73 SOURCE_ADDRESS_TOKEN_DECRYPTION_FAILURE));
74 EXPECT_STREQ("SOURCE_ADDRESS_TOKEN_PARSE_FAILURE",
75 CryptoUtils::HandshakeFailureReasonToString(
76 SOURCE_ADDRESS_TOKEN_PARSE_FAILURE));
77 EXPECT_STREQ("SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE",
78 CryptoUtils::HandshakeFailureReasonToString(
79 SOURCE_ADDRESS_TOKEN_DIFFERENT_IP_ADDRESS_FAILURE));
80 EXPECT_STREQ("SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE",
81 CryptoUtils::HandshakeFailureReasonToString(
82 SOURCE_ADDRESS_TOKEN_CLOCK_SKEW_FAILURE));
83 EXPECT_STREQ("SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE",
84 CryptoUtils::HandshakeFailureReasonToString(
85 SOURCE_ADDRESS_TOKEN_EXPIRED_FAILURE));
86 EXPECT_STREQ("INVALID_EXPECTED_LEAF_CERTIFICATE",
87 CryptoUtils::HandshakeFailureReasonToString(
88 INVALID_EXPECTED_LEAF_CERTIFICATE));
89 EXPECT_STREQ("MAX_FAILURE_REASON",
90 CryptoUtils::HandshakeFailureReasonToString(MAX_FAILURE_REASON));
91 EXPECT_STREQ(
92 "INVALID_HANDSHAKE_FAILURE_REASON",
93 CryptoUtils::HandshakeFailureReasonToString(
94 static_cast<HandshakeFailureReason>(MAX_FAILURE_REASON + 1)));
95 }
96
TEST_F(CryptoUtilsTest,AuthTagLengths)97 TEST_F(CryptoUtilsTest, AuthTagLengths) {
98 for (const auto& version : AllSupportedVersions()) {
99 for (QuicTag algo : {kAESG, kCC20}) {
100 SCOPED_TRACE(version);
101 std::unique_ptr<QuicEncrypter> encrypter(
102 QuicEncrypter::Create(version, algo));
103 size_t auth_tag_size = 12;
104 if (version.UsesInitialObfuscators()) {
105 auth_tag_size = 16;
106 }
107 EXPECT_EQ(encrypter->GetCiphertextSize(0), auth_tag_size);
108 }
109 }
110 }
111
TEST_F(CryptoUtilsTest,ValidateChosenVersion)112 TEST_F(CryptoUtilsTest, ValidateChosenVersion) {
113 for (const ParsedQuicVersion& v1 : AllSupportedVersions()) {
114 for (const ParsedQuicVersion& v2 : AllSupportedVersions()) {
115 std::string error_details;
116 bool success = CryptoUtils::ValidateChosenVersion(
117 CreateQuicVersionLabel(v1), v2, &error_details);
118 EXPECT_EQ(success, v1 == v2);
119 EXPECT_EQ(success, error_details.empty());
120 }
121 }
122 }
123
TEST_F(CryptoUtilsTest,ValidateServerVersionsNoVersionNegotiation)124 TEST_F(CryptoUtilsTest, ValidateServerVersionsNoVersionNegotiation) {
125 QuicVersionLabelVector version_information_other_versions;
126 ParsedQuicVersionVector client_original_supported_versions;
127 for (const ParsedQuicVersion& version : AllSupportedVersions()) {
128 std::string error_details;
129 EXPECT_TRUE(CryptoUtils::ValidateServerVersions(
130 version_information_other_versions, version,
131 client_original_supported_versions, &error_details));
132 EXPECT_TRUE(error_details.empty());
133 }
134 }
135
TEST_F(CryptoUtilsTest,ValidateServerVersionsWithVersionNegotiation)136 TEST_F(CryptoUtilsTest, ValidateServerVersionsWithVersionNegotiation) {
137 for (const ParsedQuicVersion& version : AllSupportedVersions()) {
138 QuicVersionLabelVector version_information_other_versions{
139 CreateQuicVersionLabel(version)};
140 ParsedQuicVersionVector client_original_supported_versions{
141 ParsedQuicVersion::ReservedForNegotiation(), version};
142 std::string error_details;
143 EXPECT_TRUE(CryptoUtils::ValidateServerVersions(
144 version_information_other_versions, version,
145 client_original_supported_versions, &error_details));
146 EXPECT_TRUE(error_details.empty());
147 }
148 }
149
TEST_F(CryptoUtilsTest,ValidateServerVersionsWithDowngrade)150 TEST_F(CryptoUtilsTest, ValidateServerVersionsWithDowngrade) {
151 if (AllSupportedVersions().size() <= 1) {
152 // We are not vulnerable to downgrade if we only support one version.
153 return;
154 }
155 ParsedQuicVersion client_version = AllSupportedVersions().front();
156 ParsedQuicVersion server_version = AllSupportedVersions().back();
157 ASSERT_NE(client_version, server_version);
158 QuicVersionLabelVector version_information_other_versions{
159 CreateQuicVersionLabel(client_version)};
160 ParsedQuicVersionVector client_original_supported_versions{
161 ParsedQuicVersion::ReservedForNegotiation(), server_version};
162 std::string error_details;
163 EXPECT_FALSE(CryptoUtils::ValidateServerVersions(
164 version_information_other_versions, server_version,
165 client_original_supported_versions, &error_details));
166 EXPECT_FALSE(error_details.empty());
167 }
168
169 // Test that the library is using the correct labels for each version, and
170 // therefore generating correct obfuscators, using the test vectors in appendix
171 // A of each RFC or internet-draft.
TEST_F(CryptoUtilsTest,ValidateCryptoLabels)172 TEST_F(CryptoUtilsTest, ValidateCryptoLabels) {
173 // if the number of HTTP/3 QUIC versions has changed, we need to change the
174 // expected_keys hardcoded into this test. Regrettably, this is not a
175 // compile-time constant.
176 EXPECT_EQ(AllSupportedVersionsWithTls().size(), 3u);
177 const char draft_29_key[] = {// test vector from draft-ietf-quic-tls-29, A.1
178 0x14,
179 static_cast<char>(0x9d),
180 0x0b,
181 0x16,
182 0x62,
183 static_cast<char>(0xab),
184 static_cast<char>(0x87),
185 0x1f,
186 static_cast<char>(0xbe),
187 0x63,
188 static_cast<char>(0xc4),
189 static_cast<char>(0x9b),
190 0x5e,
191 0x65,
192 0x5a,
193 0x5d};
194 const char v1_key[] = {// test vector from RFC 9001, A.1
195 static_cast<char>(0xcf),
196 0x3a,
197 0x53,
198 0x31,
199 0x65,
200 0x3c,
201 0x36,
202 0x4c,
203 static_cast<char>(0x88),
204 static_cast<char>(0xf0),
205 static_cast<char>(0xf3),
206 0x79,
207 static_cast<char>(0xb6),
208 0x06,
209 0x7e,
210 0x37};
211 const char v2_08_key[] = {// test vector from draft-ietf-quic-v2-08
212 static_cast<char>(0x82),
213 static_cast<char>(0xdb),
214 static_cast<char>(0x63),
215 static_cast<char>(0x78),
216 static_cast<char>(0x61),
217 static_cast<char>(0xd5),
218 static_cast<char>(0x5e),
219 0x1d,
220 static_cast<char>(0x01),
221 static_cast<char>(0x1f),
222 0x19,
223 static_cast<char>(0xea),
224 0x71,
225 static_cast<char>(0xd5),
226 static_cast<char>(0xd2),
227 static_cast<char>(0xa7)};
228 const char connection_id[] = // test vector from both docs
229 {static_cast<char>(0x83),
230 static_cast<char>(0x94),
231 static_cast<char>(0xc8),
232 static_cast<char>(0xf0),
233 0x3e,
234 0x51,
235 0x57,
236 0x08};
237 const QuicConnectionId cid(connection_id, sizeof(connection_id));
238 const char* key_str;
239 size_t key_size;
240 for (const ParsedQuicVersion& version : AllSupportedVersionsWithTls()) {
241 if (version == ParsedQuicVersion::Draft29()) {
242 key_str = draft_29_key;
243 key_size = sizeof(draft_29_key);
244 } else if (version == ParsedQuicVersion::RFCv1()) {
245 key_str = v1_key;
246 key_size = sizeof(v1_key);
247 } else { // draft-ietf-quic-v2-01
248 key_str = v2_08_key;
249 key_size = sizeof(v2_08_key);
250 }
251 const absl::string_view expected_key{key_str, key_size};
252
253 CrypterPair crypters;
254 CryptoUtils::CreateInitialObfuscators(Perspective::IS_SERVER, version, cid,
255 &crypters);
256 EXPECT_EQ(crypters.encrypter->GetKey(), expected_key);
257 }
258 }
259
260 } // namespace
261 } // namespace test
262 } // namespace quic
263