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 "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"
17
18#if defined(OS_WIN)
19#include "base/win/windows_version.h"
20#endif
21
22using std::string;
23using std::vector;
24
25namespace net {
26namespace test {
27namespace {
28
29// TestProofVerifierCallback is a simple callback for a ProofVerifier that
30// signals a TestCompletionCallback when called and stores the results from the
31// ProofVerifier in pointers passed to the constructor.
32class TestProofVerifierCallback : public ProofVerifierCallback {
33 public:
34  TestProofVerifierCallback(TestCompletionCallback* comp_callback,
35                            bool* ok,
36                            string* error_details)
37      : comp_callback_(comp_callback),
38        ok_(ok),
39        error_details_(error_details) {}
40
41  virtual void Run(bool ok,
42                   const string& error_details,
43                   scoped_ptr<ProofVerifyDetails>* details) OVERRIDE {
44    *ok_ = ok;
45    *error_details_ = error_details;
46
47    comp_callback_->callback().Run(0);
48  }
49
50 private:
51  TestCompletionCallback* const comp_callback_;
52  bool* const ok_;
53  string* const error_details_;
54};
55
56// RunVerification runs |verifier->VerifyProof| and asserts that the result
57// matches |expected_ok|.
58void RunVerification(ProofVerifier* verifier,
59                     const string& hostname,
60                     const string& server_config,
61                     const vector<string>& certs,
62                     const string& proof,
63                     bool expected_ok) {
64  scoped_ptr<ProofVerifyDetails> details;
65  TestCompletionCallback comp_callback;
66  bool ok;
67  string error_details;
68  scoped_ptr<ProofVerifyContext> verify_context(
69      CryptoTestUtils::ProofVerifyContextForTesting());
70  TestProofVerifierCallback* callback =
71      new TestProofVerifierCallback(&comp_callback, &ok, &error_details);
72
73  QuicAsyncStatus status = verifier->VerifyProof(
74      hostname, server_config, certs, proof, verify_context.get(),
75      &error_details, &details, callback);
76
77  switch (status) {
78    case QUIC_FAILURE:
79      delete callback;
80      ASSERT_FALSE(expected_ok);
81      ASSERT_NE("", error_details);
82      return;
83    case QUIC_SUCCESS:
84      delete callback;
85      ASSERT_TRUE(expected_ok);
86      ASSERT_EQ("", error_details);
87      return;
88    case QUIC_PENDING:
89      comp_callback.WaitForResult();
90      ASSERT_EQ(expected_ok, ok);
91      break;
92  }
93}
94
95// Reads the certificate named "quic_" + |file_name| in the test data directory.
96// The certificate must be PEM encoded. Returns the DER-encoded certificate.
97string LoadTestCert(const string& file_name) {
98  base::FilePath certs_dir = GetTestCertsDirectory();
99  scoped_refptr<X509Certificate> cert =
100      ImportCertFromFile(certs_dir, "quic_" + file_name);
101  CHECK_NE(static_cast<X509Certificate*>(NULL), cert.get());
102
103  string der_bytes;
104  CHECK(X509Certificate::GetDEREncoded(cert->os_cert_handle(), &der_bytes));
105  return der_bytes;
106}
107
108}  // namespace
109
110// TODO(rtenneti): Enable testing of ProofVerifier.
111TEST(ProofTest, DISABLED_Verify) {
112  scoped_ptr<ProofSource> source(CryptoTestUtils::ProofSourceForTesting());
113  scoped_ptr<ProofVerifier> verifier(
114      CryptoTestUtils::ProofVerifierForTesting());
115
116  const string server_config = "server config bytes";
117  const string hostname = "test.example.com";
118  const vector<string>* certs;
119  const vector<string>* first_certs;
120  string error_details, signature, first_signature;
121
122  ASSERT_TRUE(source->GetProof(hostname, server_config, false /* no ECDSA */,
123                               &first_certs, &first_signature));
124  ASSERT_TRUE(source->GetProof(hostname, server_config, false /* no ECDSA */,
125                               &certs, &signature));
126
127  // Check that the proof source is caching correctly:
128  ASSERT_EQ(first_certs, certs);
129  ASSERT_EQ(signature, first_signature);
130
131  RunVerification(
132      verifier.get(), hostname, server_config, *certs, signature, true);
133
134  RunVerification(
135      verifier.get(), "foo.com", server_config, *certs, signature, false);
136
137  RunVerification(
138      verifier.get(), server_config.substr(1, string::npos), server_config,
139      *certs, signature, false);
140
141  const string corrupt_signature = "1" + signature;
142  RunVerification(
143      verifier.get(), hostname, server_config, *certs, corrupt_signature,
144      false);
145
146  vector<string> wrong_certs;
147  for (size_t i = 1; i < certs->size(); i++) {
148    wrong_certs.push_back((*certs)[i]);
149  }
150  RunVerification(
151      verifier.get(), "foo.com", server_config, wrong_certs, corrupt_signature,
152      false);
153}
154
155// A known answer test that allows us to test ProofVerifier without a working
156// ProofSource.
157TEST(ProofTest, VerifyRSAKnownAnswerTest) {
158  // These sample signatures were generated by running the Proof.Verify test
159  // and dumping the bytes of the |signature| output of ProofSource::GetProof().
160  static const unsigned char signature_data_0[] = {
161    0x31, 0xd5, 0xfb, 0x40, 0x30, 0x75, 0xd2, 0x7d, 0x61, 0xf9, 0xd7, 0x54,
162    0x30, 0x06, 0xaf, 0x54, 0x0d, 0xb0, 0x0a, 0xda, 0x63, 0xca, 0x7e, 0x9e,
163    0xce, 0xba, 0x10, 0x05, 0x1b, 0xa6, 0x7f, 0xef, 0x2b, 0xa3, 0xff, 0x3c,
164    0xbb, 0x9a, 0xe4, 0xbf, 0xb8, 0x0c, 0xc1, 0xbd, 0xed, 0xc2, 0x90, 0x68,
165    0xeb, 0x45, 0x48, 0xea, 0x3c, 0x95, 0xf8, 0xa2, 0xb9, 0xe7, 0x62, 0x29,
166    0x00, 0xc3, 0x18, 0xb4, 0x16, 0x6f, 0x5e, 0xb0, 0xc1, 0x26, 0xc0, 0x4b,
167    0x84, 0xf5, 0x97, 0xfc, 0x17, 0xf9, 0x1c, 0x43, 0xb8, 0xf2, 0x3f, 0x38,
168    0x32, 0xad, 0x36, 0x52, 0x2c, 0x26, 0x92, 0x7a, 0xea, 0x2c, 0xa2, 0xf4,
169    0x28, 0x2f, 0x19, 0x4d, 0x1f, 0x11, 0x46, 0x82, 0xd0, 0xc4, 0x86, 0x56,
170    0x5c, 0x97, 0x9e, 0xc6, 0x37, 0x8e, 0xaf, 0x9d, 0x69, 0xe9, 0x4f, 0x5a,
171    0x6d, 0x70, 0x75, 0xc7, 0x41, 0x95, 0x68, 0x53, 0x94, 0xca, 0x31, 0x63,
172    0x61, 0x9f, 0xb8, 0x8c, 0x3b, 0x75, 0x36, 0x8b, 0x69, 0xa2, 0x35, 0xc0,
173    0x4b, 0x77, 0x55, 0x08, 0xc2, 0xb4, 0x56, 0xd2, 0x81, 0xce, 0x9e, 0x25,
174    0xdb, 0x50, 0x74, 0xb3, 0x8a, 0xd9, 0x20, 0x42, 0x3f, 0x85, 0x2d, 0xaa,
175    0xfd, 0x66, 0xfa, 0xd6, 0x95, 0x55, 0x6b, 0x63, 0x63, 0x04, 0xf8, 0x6c,
176    0x3e, 0x08, 0x22, 0x39, 0xb9, 0x9a, 0xe0, 0xd7, 0x01, 0xff, 0xeb, 0x8a,
177    0xb9, 0xe2, 0x34, 0xa5, 0xa0, 0x51, 0xe9, 0xbe, 0x15, 0x12, 0xbf, 0xbe,
178    0x64, 0x3d, 0x3f, 0x98, 0xce, 0xc1, 0xa6, 0x33, 0x32, 0xd3, 0x5c, 0xa8,
179    0x39, 0x93, 0xdc, 0x1c, 0xb9, 0xab, 0x3c, 0x80, 0x62, 0xb3, 0x76, 0x21,
180    0xdf, 0x47, 0x1e, 0xa9, 0x0e, 0x5e, 0x8a, 0xbe, 0x66, 0x5b, 0x7c, 0x21,
181    0xfa, 0x78, 0x2d, 0xd1, 0x1d, 0x5c, 0x35, 0x8a, 0x34, 0xb2, 0x1a, 0xc2,
182    0xc4, 0x4b, 0x53, 0x54,
183  };
184  static const unsigned char signature_data_1[] = {
185    0x01, 0x7b, 0x52, 0x35, 0xe3, 0x51, 0xdd, 0xf1, 0x67, 0x8d, 0x31, 0x5e,
186    0xa3, 0x75, 0x1f, 0x68, 0x6c, 0xdd, 0x41, 0x7a, 0x18, 0x25, 0xe0, 0x12,
187    0x6e, 0x84, 0x46, 0x5e, 0xb2, 0x98, 0xd7, 0x84, 0xe1, 0x62, 0xe0, 0xc1,
188    0xc4, 0xd7, 0x4f, 0x4f, 0x80, 0xc1, 0x92, 0xd6, 0x02, 0xaf, 0xca, 0x28,
189    0x9f, 0xe0, 0xf3, 0x74, 0xd7, 0xf1, 0x44, 0x67, 0x59, 0x27, 0xc8, 0xc2,
190    0x8b, 0xd4, 0xe5, 0x4a, 0x07, 0xfd, 0x00, 0xd6, 0x8a, 0xbf, 0x8b, 0xcd,
191    0x6a, 0xe0, 0x1d, 0xf6, 0x4b, 0x68, 0x0f, 0xcf, 0xb9, 0xd0, 0xa1, 0xbc,
192    0x2e, 0xcf, 0x7c, 0x03, 0x47, 0x11, 0xe4, 0x4c, 0xbc, 0x1b, 0x6b, 0xa5,
193    0x2a, 0x82, 0x86, 0xa4, 0x7f, 0x1d, 0x85, 0x64, 0x21, 0x10, 0xd2, 0xb2,
194    0xa0, 0x31, 0xa2, 0x78, 0xe6, 0xf2, 0xea, 0x96, 0x38, 0x8c, 0x9a, 0xe1,
195    0x01, 0xab, 0x8e, 0x95, 0x66, 0xc8, 0xe5, 0xcc, 0x80, 0xa3, 0xbd, 0x16,
196    0xa7, 0x79, 0x19, 0x39, 0x61, 0x3d, 0xff, 0x37, 0xca, 0x9f, 0x97, 0x05,
197    0xc7, 0xcb, 0xf0, 0xea, 0xaf, 0x64, 0x07, 0xc0, 0xed, 0x2a, 0x98, 0xa4,
198    0xaf, 0x04, 0x6f, 0xf2, 0xc9, 0xb2, 0x73, 0x9a, 0x56, 0x85, 0x43, 0x64,
199    0x5f, 0xaa, 0xb7, 0xff, 0x31, 0x4c, 0x2e, 0x6c, 0x17, 0xcf, 0xe5, 0xbe,
200    0x7f, 0x7e, 0xad, 0xf5, 0x6f, 0x84, 0x50, 0x20, 0x29, 0xb3, 0x57, 0xe7,
201    0xb1, 0xdc, 0x2c, 0x95, 0x48, 0xfe, 0xb0, 0xc1, 0x92, 0xda, 0xc5, 0x58,
202    0x95, 0xb0, 0x1a, 0x3a, 0x05, 0x71, 0x3c, 0x6d, 0x20, 0x01, 0x4c, 0xa9,
203    0xe4, 0x38, 0x08, 0x65, 0xb4, 0xbd, 0x86, 0x76, 0xbd, 0xad, 0x25, 0x06,
204    0x74, 0x0b, 0xca, 0x95, 0x27, 0x0c, 0x13, 0x08, 0x7e, 0x30, 0xcf, 0xf6,
205    0xb5, 0xc1, 0x2a, 0x08, 0xfc, 0x4b, 0xc6, 0xb5, 0x2f, 0x23, 0x27, 0x32,
206    0x89, 0xdb, 0x0e, 0x4a,
207  };
208  static const unsigned char signature_data_2[] = {
209    0x6d, 0x7d, 0x22, 0x8c, 0x85, 0xc4, 0x8a, 0x80, 0x05, 0xe4, 0x3c, 0xaf,
210    0x10, 0x3b, 0xe3, 0x51, 0xb1, 0x86, 0x52, 0x63, 0xb6, 0x17, 0x33, 0xbd,
211    0x1b, 0x1e, 0xc4, 0x50, 0x10, 0xfc, 0xcc, 0xea, 0x6b, 0x11, 0xeb, 0x6d,
212    0x5e, 0x00, 0xe7, 0xf3, 0x67, 0x99, 0x74, 0x53, 0x12, 0x8f, 0xe4, 0x3e,
213    0x20, 0x17, 0x8e, 0x83, 0xe6, 0xdc, 0x83, 0x91, 0x0e, 0xf3, 0x69, 0x22,
214    0x95, 0x14, 0xdf, 0xc1, 0xda, 0xb5, 0xdb, 0x6a, 0x1a, 0xb4, 0x4f, 0x26,
215    0xd0, 0x32, 0x1d, 0x73, 0x95, 0x1f, 0x39, 0x1d, 0x00, 0xcb, 0xc3, 0x92,
216    0x49, 0x53, 0xcb, 0x5c, 0x36, 0x70, 0x19, 0xd9, 0x64, 0x36, 0xda, 0xfb,
217    0x20, 0xe5, 0x47, 0xd9, 0x08, 0xc6, 0x5a, 0x9e, 0x87, 0x1a, 0xdb, 0x11,
218    0x7b, 0x17, 0xfc, 0x53, 0x7b, 0xc1, 0xa0, 0xc0, 0x33, 0xcf, 0x96, 0xba,
219    0x03, 0x79, 0x8e, 0xc6, 0x05, 0xd2, 0xb7, 0xa2, 0xe2, 0xc1, 0x67, 0xb7,
220    0x6a, 0xeb, 0xb1, 0x40, 0xbb, 0x7d, 0x57, 0xcb, 0xc2, 0x60, 0x9f, 0xf1,
221    0x72, 0xe5, 0xad, 0xce, 0x95, 0x45, 0x7c, 0xbc, 0x75, 0x81, 0x45, 0x19,
222    0xe1, 0xa7, 0x2f, 0x05, 0x52, 0xeb, 0xed, 0xdd, 0x19, 0xd9, 0x1a, 0xc9,
223    0x5a, 0x06, 0x8e, 0x29, 0x54, 0xb5, 0x4f, 0x80, 0xaa, 0x36, 0x36, 0xc0,
224    0xff, 0x64, 0xac, 0xe8, 0x0f, 0x99, 0x35, 0x5e, 0xc6, 0x72, 0x1f, 0x8c,
225    0xc4, 0x2b, 0x7d, 0xc1, 0xfb, 0xf0, 0x12, 0x61, 0xb1, 0x18, 0x65, 0xdd,
226    0xc2, 0x38, 0x92, 0xba, 0x84, 0xf8, 0xc8, 0x5e, 0x17, 0x63, 0xe0, 0x9c,
227    0x2c, 0xe6, 0x70, 0x71, 0xdc, 0xe5, 0xc1, 0xea, 0xb3, 0x9a, 0xb6, 0x91,
228    0xdc, 0xc5, 0x56, 0x84, 0x8a, 0x31, 0x31, 0x23, 0x61, 0x94, 0x7e, 0x01,
229    0x22, 0x49, 0xf3, 0xcb, 0x0e, 0x31, 0x03, 0x04, 0x1b, 0x14, 0x43, 0x7c,
230    0xad, 0x42, 0xe5, 0x55,
231  };
232
233  scoped_ptr<ProofVerifier> verifier(
234      CryptoTestUtils::ProofVerifierForTesting());
235
236  const string server_config = "server config bytes";
237  const string hostname = "test.example.com";
238
239  vector<string> certs(2);
240  certs[0] = LoadTestCert("test.example.com.crt");
241  certs[1] = LoadTestCert("intermediate.crt");
242
243  // Signatures are nondeterministic, so we test multiple signatures on the
244  // same server_config.
245  vector<string> signatures(3);
246  signatures[0].assign(reinterpret_cast<const char*>(signature_data_0),
247                       sizeof(signature_data_0));
248  signatures[1].assign(reinterpret_cast<const char*>(signature_data_1),
249                       sizeof(signature_data_1));
250  signatures[2].assign(reinterpret_cast<const char*>(signature_data_2),
251                       sizeof(signature_data_2));
252
253  for (size_t i = 0; i < signatures.size(); i++) {
254    const string& signature = signatures[i];
255
256    RunVerification(
257        verifier.get(), hostname, server_config, certs, signature, true);
258    RunVerification(
259        verifier.get(), "foo.com", server_config, certs, signature, false);
260    RunVerification(
261        verifier.get(), hostname, server_config.substr(1, string::npos),
262        certs, signature, false);
263
264    const string corrupt_signature = "1" + signature;
265    RunVerification(
266        verifier.get(), hostname, server_config, certs, corrupt_signature,
267        false);
268
269    vector<string> wrong_certs;
270    for (size_t i = 1; i < certs.size(); i++) {
271      wrong_certs.push_back(certs[i]);
272    }
273    RunVerification(verifier.get(), hostname, server_config, wrong_certs,
274                    signature, false);
275  }
276}
277
278// A known answer test that allows us to test ProofVerifier without a working
279// ProofSource.
280TEST(ProofTest, VerifyECDSAKnownAnswerTest) {
281  // Disable this test on platforms that do not support ECDSA certificates.
282#if defined(OS_WIN)
283  if (base::win::GetVersion() < base::win::VERSION_VISTA)
284    return;
285#endif
286
287  // These sample signatures were generated by running the Proof.Verify test
288  // (modified to use ECDSA for signing proofs) and dumping the bytes of the
289  // |signature| output of ProofSource::GetProof().
290  static const unsigned char signature_data_0[] = {
291    0x30, 0x45, 0x02, 0x21, 0x00, 0x89, 0xc4, 0x7d, 0x08, 0xd1, 0x49, 0x19,
292    0x6c, 0xd1, 0x7c, 0xb9, 0x25, 0xe0, 0xe3, 0xbd, 0x6a, 0x5c, 0xd7, 0xaa,
293    0x0c, 0xdc, 0x4f, 0x8e, 0xeb, 0xde, 0xbf, 0x32, 0xf8, 0xd1, 0x84, 0x95,
294    0x97, 0x02, 0x20, 0x29, 0x3d, 0x49, 0x22, 0x73, 0xed, 0x8b, 0xde, 0x3d,
295    0xc2, 0xa4, 0x20, 0xcc, 0xe7, 0xc8, 0x2a, 0x85, 0x20, 0x9b, 0x5b, 0xda,
296    0xcd, 0x58, 0x23, 0xbe, 0x89, 0x73, 0x31, 0x87, 0x51, 0xd1, 0x01,
297  };
298  static const unsigned char signature_data_1[] = {
299    0x30, 0x46, 0x02, 0x21, 0x00, 0xec, 0xdf, 0x69, 0xc8, 0x24, 0x59, 0x93,
300    0xda, 0x49, 0xee, 0x37, 0x28, 0xaf, 0xeb, 0x0e, 0x2f, 0x80, 0x17, 0x4b,
301    0x3b, 0xf6, 0x54, 0xcd, 0x3b, 0x86, 0xc5, 0x98, 0x0d, 0xff, 0xc6, 0xb1,
302    0xe7, 0x02, 0x21, 0x00, 0xe1, 0x36, 0x8c, 0xc0, 0xf4, 0x50, 0x5f, 0xba,
303    0xfb, 0xe2, 0xff, 0x1d, 0x5d, 0x64, 0xe4, 0x07, 0xbb, 0x5a, 0x4b, 0x19,
304    0xb6, 0x39, 0x7a, 0xc4, 0x12, 0xc6, 0xe5, 0x42, 0xc8, 0x78, 0x33, 0xcd,
305  };
306  static const unsigned char signature_data_2[] = {
307    0x30, 0x45, 0x02, 0x20, 0x09, 0x51, 0xe9, 0xde, 0xdb, 0x01, 0xfd, 0xb4,
308    0xd8, 0x20, 0xbb, 0xad, 0x41, 0xe3, 0xaa, 0xe7, 0xa3, 0xc3, 0x32, 0x10,
309    0x9d, 0xfa, 0x37, 0xce, 0x17, 0xd1, 0x29, 0xf9, 0xd4, 0x1d, 0x0d, 0x19,
310    0x02, 0x21, 0x00, 0xc6, 0x20, 0xd4, 0x28, 0xf9, 0x70, 0xb5, 0xb4, 0xff,
311    0x4a, 0x35, 0xba, 0xa0, 0xf2, 0x8e, 0x00, 0xf7, 0xcb, 0x43, 0xaf, 0x2d,
312    0x1f, 0xce, 0x92, 0x05, 0xca, 0x29, 0xfe, 0xd2, 0x8f, 0xd9, 0x31,
313  };
314
315  scoped_ptr<ProofVerifier> verifier(
316      CryptoTestUtils::ProofVerifierForTesting());
317
318  const string server_config = "server config bytes";
319  const string hostname = "test.example.com";
320
321  vector<string> certs(2);
322  certs[0] = LoadTestCert("test_ecc.example.com.crt");
323  certs[1] = LoadTestCert("intermediate.crt");
324
325  // Signatures are nondeterministic, so we test multiple signatures on the
326  // same server_config.
327  vector<string> signatures(3);
328  signatures[0].assign(reinterpret_cast<const char*>(signature_data_0),
329                       sizeof(signature_data_0));
330  signatures[1].assign(reinterpret_cast<const char*>(signature_data_1),
331                       sizeof(signature_data_1));
332  signatures[2].assign(reinterpret_cast<const char*>(signature_data_2),
333                       sizeof(signature_data_2));
334
335  for (size_t i = 0; i < signatures.size(); i++) {
336    const string& signature = signatures[i];
337
338    RunVerification(
339        verifier.get(), hostname, server_config, certs, signature, true);
340    RunVerification(
341        verifier.get(), "foo.com", server_config, certs, signature, false);
342    RunVerification(
343        verifier.get(), hostname, server_config.substr(1, string::npos),
344        certs, signature, false);
345
346    // An ECDSA signature is DER-encoded. Corrupt the last byte so that the
347    // signature can still be DER-decoded correctly.
348    string corrupt_signature = signature;
349    corrupt_signature[corrupt_signature.size() - 1] += 1;
350    RunVerification(
351        verifier.get(), hostname, server_config, certs, corrupt_signature,
352        false);
353
354    // Prepending a "1" makes the DER invalid.
355    const string bad_der_signature1 = "1" + signature;
356    RunVerification(
357        verifier.get(), hostname, server_config, certs, bad_der_signature1,
358        false);
359
360    vector<string> wrong_certs;
361    for (size_t i = 1; i < certs.size(); i++) {
362      wrong_certs.push_back(certs[i]);
363    }
364    RunVerification(
365        verifier.get(), hostname, server_config, wrong_certs, signature,
366        false);
367  }
368}
369
370}  // namespace test
371}  // namespace net
372