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.
5 #include "base/files/file_path.h"
6 #include "net/base/net_errors.h"
7 #include "net/base/test_completion_callback.h"
8 #include "net/base/test_data_directory.h"
9 #include "net/cert/cert_status_flags.h"
10 #include "net/cert/cert_verify_result.h"
11 #include "net/cert/x509_certificate.h"
12 #include "net/quic/crypto/proof_source.h"
13 #include "net/quic/crypto/proof_verifier.h"
14 #include "net/quic/test_tools/crypto_test_utils.h"
15 #include "net/test/cert_test_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
19 #include "base/win/windows_version.h"
28 TEST(ProofTest, Verify) {
29 // TODO(rtenneti): Enable testing of ProofVerifier.
31 scoped_ptr<ProofSource> source(CryptoTestUtils::ProofSourceForTesting());
32 scoped_ptr<ProofVerifier> verifier(
33 CryptoTestUtils::ProofVerifierForTesting());
35 const string server_config = "server config bytes";
36 const string hostname = "test.example.com";
37 const vector<string>* certs;
38 const vector<string>* first_certs;
39 string error_details, signature, first_signature;
40 CertVerifyResult cert_verify_result;
42 ASSERT_TRUE(source->GetProof(hostname, server_config, false /* no ECDSA */,
43 &first_certs, &first_signature));
44 ASSERT_TRUE(source->GetProof(hostname, server_config, false /* no ECDSA */,
47 // Check that the proof source is caching correctly:
48 ASSERT_EQ(first_certs, certs);
49 ASSERT_EQ(signature, first_signature);
52 TestCompletionCallback callback;
53 rv = verifier->VerifyProof(hostname, server_config, *certs, signature,
54 &error_details, &cert_verify_result,
56 rv = callback.GetResult(rv);
58 ASSERT_EQ("", error_details);
59 ASSERT_FALSE(IsCertStatusError(cert_verify_result.cert_status));
61 rv = verifier->VerifyProof("foo.com", server_config, *certs, signature,
62 &error_details, &cert_verify_result,
64 rv = callback.GetResult(rv);
65 ASSERT_EQ(ERR_FAILED, rv);
66 ASSERT_NE("", error_details);
68 rv = verifier->VerifyProof(hostname, server_config.substr(1, string::npos),
69 *certs, signature, &error_details,
70 &cert_verify_result, callback.callback());
71 rv = callback.GetResult(rv);
72 ASSERT_EQ(ERR_FAILED, rv);
73 ASSERT_NE("", error_details);
75 const string corrupt_signature = "1" + signature;
76 rv = verifier->VerifyProof(hostname, server_config, *certs,
77 corrupt_signature, &error_details,
78 &cert_verify_result, callback.callback());
79 rv = callback.GetResult(rv);
80 ASSERT_EQ(ERR_FAILED, rv);
81 ASSERT_NE("", error_details);
83 vector<string> wrong_certs;
84 for (size_t i = 1; i < certs->size(); i++) {
85 wrong_certs.push_back((*certs)[i]);
87 rv = verifier->VerifyProof("foo.com", server_config, wrong_certs, signature,
88 &error_details, &cert_verify_result,
90 rv = callback.GetResult(rv);
91 ASSERT_EQ(ERR_FAILED, rv);
92 ASSERT_NE("", error_details);
96 // TestProofVerifierCallback is a simple callback for a ProofVerifier that
97 // signals a TestCompletionCallback when called and stores the results from the
98 // ProofVerifier in pointers passed to the constructor.
99 class TestProofVerifierCallback : public ProofVerifierCallback {
101 TestProofVerifierCallback(TestCompletionCallback* comp_callback,
103 std::string* error_details)
104 : comp_callback_(comp_callback),
106 error_details_(error_details) {}
108 virtual void Run(bool ok,
109 const std::string& error_details,
110 scoped_ptr<ProofVerifyDetails>* details) OVERRIDE {
112 *error_details_ = error_details;
114 comp_callback_->callback().Run(0);
118 TestCompletionCallback* const comp_callback_;
120 std::string* const error_details_;
123 // RunVerification runs |verifier->VerifyProof| and asserts that the result
124 // matches |expected_ok|.
125 static void RunVerification(ProofVerifier* verifier,
126 const std::string& hostname,
127 const std::string& server_config,
128 const vector<std::string>& certs,
129 const std::string& proof,
131 scoped_ptr<ProofVerifyDetails> details;
132 TestCompletionCallback comp_callback;
134 std::string error_details;
135 TestProofVerifierCallback* callback =
136 new TestProofVerifierCallback(&comp_callback, &ok, &error_details);
138 ProofVerifier::Status status = verifier->VerifyProof(
139 hostname, server_config, certs, proof, &error_details, &details,
143 case ProofVerifier::FAILURE:
144 ASSERT_FALSE(expected_ok);
145 ASSERT_NE("", error_details);
147 case ProofVerifier::SUCCESS:
148 ASSERT_TRUE(expected_ok);
149 ASSERT_EQ("", error_details);
151 case ProofVerifier::PENDING:
152 comp_callback.WaitForResult();
153 ASSERT_EQ(expected_ok, ok);
158 static string PEMCertFileToDER(const string& file_name) {
159 base::FilePath certs_dir = GetTestCertsDirectory();
160 scoped_refptr<X509Certificate> cert =
161 ImportCertFromFile(certs_dir, file_name);
162 CHECK_NE(static_cast<X509Certificate*>(NULL), cert);
165 CHECK(X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_bytes));
169 // A known answer test that allows us to test ProofVerifier without a working
171 TEST(ProofTest, VerifyRSAKnownAnswerTest) {
172 // These sample signatures were generated by running the Proof.Verify test
173 // and dumping the bytes of the |signature| output of ProofSource::GetProof().
174 // sLen = special value -2 used by OpenSSL.
175 static const unsigned char signature_data_0[] = {
176 0x9e, 0xe6, 0x74, 0x3b, 0x8f, 0xb8, 0x66, 0x77, 0x57, 0x09,
177 0x8a, 0x04, 0xe9, 0xf0, 0x7c, 0x91, 0xa9, 0x5c, 0xe9, 0xdf,
178 0x12, 0x4d, 0x23, 0x82, 0x8c, 0x29, 0x72, 0x7f, 0xc2, 0x20,
179 0xa7, 0xb3, 0xe5, 0xbc, 0xcf, 0x3c, 0x0d, 0x8f, 0xae, 0x46,
180 0x6a, 0xb9, 0xee, 0x0c, 0xe1, 0x13, 0x21, 0xc0, 0x7e, 0x45,
181 0x24, 0x24, 0x4b, 0x72, 0x43, 0x5e, 0xc4, 0x0d, 0xdf, 0x6c,
182 0xd8, 0xaa, 0x35, 0x97, 0x05, 0x40, 0x76, 0xd3, 0x2c, 0xee,
183 0x82, 0x16, 0x6a, 0x43, 0xf9, 0xa2, 0xd0, 0x41, 0x3c, 0xed,
184 0x3f, 0x40, 0x10, 0x95, 0xc7, 0xa9, 0x1f, 0x04, 0xdb, 0xd5,
185 0x98, 0x9f, 0xe2, 0xbf, 0x77, 0x3d, 0xc9, 0x9a, 0xaf, 0xf7,
186 0xef, 0x63, 0x0b, 0x7d, 0xc8, 0x37, 0xda, 0x37, 0x23, 0x88,
187 0x78, 0xc8, 0x8b, 0xf5, 0xb9, 0x36, 0x5d, 0x72, 0x1f, 0xfc,
188 0x14, 0xff, 0xa7, 0x81, 0x27, 0x49, 0xae, 0xe1,
190 static const unsigned char signature_data_1[] = {
191 0x5e, 0xc2, 0xab, 0x6b, 0x16, 0xe6, 0x55, 0xf3, 0x16, 0x46,
192 0x35, 0xdc, 0xcc, 0xde, 0xd0, 0xbd, 0x6c, 0x66, 0xb2, 0x3d,
193 0xd3, 0x14, 0x78, 0xed, 0x47, 0x55, 0xfb, 0xdb, 0xe1, 0x7d,
194 0xbf, 0x31, 0xf6, 0xf4, 0x10, 0x4c, 0x8d, 0x22, 0x17, 0xaa,
195 0xe1, 0x85, 0xc7, 0x96, 0x4c, 0x42, 0xfb, 0xf4, 0x63, 0x53,
196 0x8a, 0x79, 0x01, 0x63, 0x48, 0xa8, 0x3a, 0xbc, 0xc9, 0xd2,
197 0xf5, 0xec, 0xe9, 0x09, 0x71, 0xaf, 0xce, 0x34, 0x56, 0xe5,
198 0x00, 0xbe, 0xee, 0x3c, 0x1c, 0xc4, 0xa0, 0x07, 0xd5, 0x77,
199 0xb8, 0x83, 0x57, 0x7d, 0x1a, 0xc9, 0xd0, 0xc0, 0x59, 0x9a,
200 0x88, 0x19, 0x3f, 0xb9, 0xf0, 0x45, 0x37, 0xc3, 0x00, 0x8b,
201 0xb3, 0x89, 0xf4, 0x89, 0x07, 0xa9, 0xc3, 0x26, 0xbf, 0x81,
202 0xaf, 0x6b, 0x47, 0xbc, 0x16, 0x55, 0x37, 0x0a, 0xbe, 0x0e,
203 0xc5, 0x75, 0x3f, 0x3d, 0x8e, 0xe8, 0x44, 0xe3,
205 static const unsigned char signature_data_2[] = {
206 0x8e, 0x5c, 0x78, 0x63, 0x74, 0x99, 0x2e, 0x96, 0xc0, 0x14,
207 0x8d, 0xb5, 0x13, 0x74, 0xa3, 0xa4, 0xe0, 0x43, 0x3e, 0x85,
208 0xba, 0x8f, 0x3c, 0x5e, 0x14, 0x64, 0x0e, 0x5e, 0xff, 0x89,
209 0x88, 0x8a, 0x65, 0xe2, 0xa2, 0x79, 0xe4, 0xe9, 0x3a, 0x7f,
210 0xf6, 0x9d, 0x3d, 0xe2, 0xb0, 0x8a, 0x35, 0x55, 0xed, 0x21,
211 0xee, 0x20, 0xd8, 0x8a, 0x60, 0x47, 0xca, 0x52, 0x54, 0x91,
212 0x99, 0x69, 0x8d, 0x16, 0x34, 0x69, 0xe1, 0x46, 0x56, 0x67,
213 0x5f, 0x50, 0xf0, 0x94, 0xe7, 0x8b, 0xf2, 0x6a, 0x73, 0x0f,
214 0x30, 0x30, 0xde, 0x59, 0xdc, 0xc7, 0xfe, 0xb6, 0x83, 0xe1,
215 0x86, 0x1d, 0x88, 0xd3, 0x2f, 0x2f, 0x74, 0x68, 0xbd, 0x6c,
216 0xd1, 0x46, 0x76, 0x06, 0xa9, 0xd4, 0x03, 0x3f, 0xda, 0x7d,
217 0xa7, 0xff, 0x48, 0xe4, 0xb4, 0x42, 0x06, 0xac, 0x19, 0x12,
218 0xe6, 0x05, 0xae, 0xbe, 0x29, 0x94, 0x8f, 0x99,
221 scoped_ptr<ProofVerifier> verifier(
222 CryptoTestUtils::ProofVerifierForTesting());
224 const string server_config = "server config bytes";
225 const string hostname = "test.example.com";
226 CertVerifyResult cert_verify_result;
228 vector<string> certs(2);
229 certs[0] = PEMCertFileToDER("quic_test.example.com.crt");
230 certs[1] = PEMCertFileToDER("quic_intermediate.crt");
232 // Signatures are nondeterministic, so we test multiple signatures on the
233 // same server_config.
234 vector<string> signatures(3);
235 signatures[0].assign(reinterpret_cast<const char*>(signature_data_0),
236 sizeof(signature_data_0));
237 signatures[1].assign(reinterpret_cast<const char*>(signature_data_1),
238 sizeof(signature_data_1));
239 signatures[2].assign(reinterpret_cast<const char*>(signature_data_2),
240 sizeof(signature_data_2));
242 for (size_t i = 0; i < signatures.size(); i++) {
243 const string& signature = signatures[i];
246 verifier.get(), hostname, server_config, certs, signature, true);
248 verifier.get(), "foo.com", server_config, certs, signature, false);
250 verifier.get(), hostname, server_config.substr(1, string::npos),
251 certs, signature, false);
253 const string corrupt_signature = "1" + signature;
255 verifier.get(), hostname, server_config, certs, corrupt_signature,
258 vector<string> wrong_certs;
259 for (size_t i = 1; i < certs.size(); i++) {
260 wrong_certs.push_back(certs[i]);
262 RunVerification(verifier.get(), hostname, server_config, wrong_certs,
267 // A known answer test that allows us to test ProofVerifier without a working
269 TEST(ProofTest, VerifyECDSAKnownAnswerTest) {
270 // Disable this test on platforms that do not support ECDSA certificates.
272 if (base::win::GetVersion() < base::win::VERSION_VISTA)
276 // These sample signatures were generated by running the Proof.Verify test
277 // (modified to use ECDSA for signing proofs) and dumping the bytes of the
278 // |signature| output of ProofSource::GetProof().
279 static const unsigned char signature_data_0[] = {
280 0x30, 0x45, 0x02, 0x20, 0x15, 0xb7, 0x9f, 0xe3, 0xd9, 0x7a,
281 0x3c, 0x3b, 0x18, 0xb0, 0xdb, 0x60, 0x23, 0x56, 0xa0, 0x06,
282 0x4e, 0x70, 0xa3, 0xf7, 0x4b, 0xe5, 0x0d, 0x69, 0xf0, 0x35,
283 0x8c, 0xae, 0xb5, 0x54, 0x32, 0xe9, 0x02, 0x21, 0x00, 0xf7,
284 0xe3, 0x06, 0x99, 0x16, 0x56, 0x7e, 0xab, 0x33, 0x53, 0x0d,
285 0xde, 0xbe, 0xef, 0x6d, 0xb0, 0xc7, 0xa6, 0x63, 0xaf, 0x8d,
286 0xab, 0x34, 0xa9, 0xc0, 0x63, 0x88, 0x47, 0x17, 0x4c, 0x4c,
289 static const unsigned char signature_data_1[] = {
290 0x30, 0x44, 0x02, 0x20, 0x69, 0x60, 0x55, 0xbb, 0x11, 0x93,
291 0x6a, 0xdc, 0x9b, 0x61, 0x2c, 0x60, 0x19, 0xbc, 0x15, 0x55,
292 0xcf, 0xf2, 0x8e, 0x2e, 0x27, 0x0b, 0x69, 0xef, 0x33, 0x25,
293 0x1e, 0x5d, 0x8c, 0x00, 0x11, 0xef, 0x02, 0x20, 0x0c, 0x26,
294 0xfe, 0x0b, 0x06, 0x8f, 0xe8, 0xe2, 0x02, 0x63, 0xe5, 0x43,
295 0x0d, 0xc9, 0x80, 0x4d, 0xe9, 0x6f, 0x6e, 0x18, 0xdb, 0xb0,
296 0x04, 0x2a, 0x45, 0x37, 0x1a, 0x60, 0x0e, 0xc6, 0xc4, 0x8f,
298 static const unsigned char signature_data_2[] = {
299 0x30, 0x45, 0x02, 0x21, 0x00, 0xd5, 0x43, 0x36, 0x60, 0x50,
300 0xce, 0xe0, 0x00, 0x51, 0x02, 0x84, 0x95, 0x51, 0x47, 0xaf,
301 0xe4, 0xf9, 0xe1, 0x23, 0xae, 0x21, 0xb4, 0x98, 0xd1, 0xa3,
302 0x5f, 0x3b, 0xf3, 0x6a, 0x65, 0x44, 0x6b, 0x02, 0x20, 0x30,
303 0x7e, 0xb4, 0xea, 0xf0, 0xda, 0xdb, 0xbd, 0x38, 0xb9, 0x7a,
304 0x5d, 0x12, 0x04, 0x0e, 0xc2, 0xf0, 0xb1, 0x0e, 0x25, 0xf8,
305 0x0a, 0x27, 0xa3, 0x16, 0x94, 0xac, 0x1e, 0xb8, 0x6e, 0x00,
309 scoped_ptr<ProofVerifier> verifier(
310 CryptoTestUtils::ProofVerifierForTesting());
312 const string server_config = "server config bytes";
313 const string hostname = "test.example.com";
314 CertVerifyResult cert_verify_result;
316 vector<string> certs(2);
317 certs[0] = PEMCertFileToDER("quic_test_ecc.example.com.crt");
318 certs[1] = PEMCertFileToDER("quic_intermediate.crt");
320 // Signatures are nondeterministic, so we test multiple signatures on the
321 // same server_config.
322 vector<string> signatures(3);
323 signatures[0].assign(reinterpret_cast<const char*>(signature_data_0),
324 sizeof(signature_data_0));
325 signatures[1].assign(reinterpret_cast<const char*>(signature_data_1),
326 sizeof(signature_data_1));
327 signatures[2].assign(reinterpret_cast<const char*>(signature_data_2),
328 sizeof(signature_data_2));
330 for (size_t i = 0; i < signatures.size(); i++) {
331 const string& signature = signatures[i];
334 verifier.get(), hostname, server_config, certs, signature, true);
336 verifier.get(), "foo.com", server_config, certs, signature, false);
338 verifier.get(), hostname, server_config.substr(1, string::npos),
339 certs, signature, false);
341 // An ECDSA signature is DER-encoded. Corrupt the last byte so that the
342 // signature can still be DER-decoded correctly.
343 string corrupt_signature = signature;
344 corrupt_signature[corrupt_signature.size() - 1] += 1;
346 verifier.get(), hostname, server_config, certs, corrupt_signature,
349 // Prepending a "1" makes the DER invalid.
350 const string bad_der_signature1 = "1" + signature;
352 verifier.get(), hostname, server_config, certs, bad_der_signature1,
355 vector<string> wrong_certs;
356 for (size_t i = 1; i < certs.size(); i++) {
357 wrong_certs.push_back(certs[i]);
360 verifier.get(), hostname, server_config, wrong_certs, signature,