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