Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/cert/ct_log_verifier.h" | 5 #include "net/cert/ct_log_verifier.h" |
| 6 | 6 |
| 7 #include <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <string> | 10 #include <string> |
| 11 #include <vector> | |
| 11 | 12 |
| 13 #include "base/macros.h" | |
|
Ryan Sleevi
2016/07/26 19:33:44
? for what?
Rob Percival
2016/07/28 05:18:47
arraysize is used in this code. I added the #inclu
Ryan Sleevi
2016/07/28 14:54:49
There's a threshold to use judgement, but whenever
| |
| 12 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/time/time.h" | 15 #include "base/time/time.h" |
| 14 #include "crypto/secure_hash.h" | 16 #include "crypto/secure_hash.h" |
| 15 #include "net/base/hash_value.h" | 17 #include "net/base/hash_value.h" |
| 16 #include "net/cert/ct_log_verifier_util.h" | 18 #include "net/cert/ct_log_verifier_util.h" |
| 19 #include "net/cert/merkle_audit_proof.h" | |
| 17 #include "net/cert/merkle_consistency_proof.h" | 20 #include "net/cert/merkle_consistency_proof.h" |
| 18 #include "net/cert/signed_certificate_timestamp.h" | 21 #include "net/cert/signed_certificate_timestamp.h" |
| 19 #include "net/cert/signed_tree_head.h" | 22 #include "net/cert/signed_tree_head.h" |
| 20 #include "net/test/ct_test_util.h" | 23 #include "net/test/ct_test_util.h" |
| 21 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 22 | 25 |
| 23 namespace net { | 26 namespace net { |
| 24 | 27 |
| 25 namespace { | 28 namespace { |
| 26 | 29 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 54 size_t proof_length; | 57 size_t proof_length; |
| 55 TestVector proof[3]; | 58 TestVector proof[3]; |
| 56 }; | 59 }; |
| 57 | 60 |
| 58 // All test data replicated from | 61 // All test data replicated from |
| 59 // https://github.com/google/certificate-transparency/blob/c41b090ecc14ddd6b3531 dc7e5ce36b21e253fdd/cpp/merkletree/merkle_tree_test.cc | 62 // https://github.com/google/certificate-transparency/blob/c41b090ecc14ddd6b3531 dc7e5ce36b21e253fdd/cpp/merkletree/merkle_tree_test.cc |
| 60 // A hash of the empty string. | 63 // A hash of the empty string. |
| 61 const TestVector kSHA256EmptyTreeHash = { | 64 const TestVector kSHA256EmptyTreeHash = { |
| 62 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", 32}; | 65 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", 32}; |
| 63 | 66 |
| 67 // Hashes of the leaf data for the sample tree (8 leaves). | |
| 68 const TestVector kSHA256LeafHashes[8] = { | |
| 69 {"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, | |
| 70 {"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", 32}, | |
| 71 {"0298d122906dcfc10892cb53a73992fc5b9f493ea4c9badb27b791b4127a7fe7", 32}, | |
| 72 {"07506a85fd9dd2f120eb694f86011e5bb4662e5c415a62917033d4a9624487e7", 32}, | |
| 73 {"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", 32}, | |
| 74 {"4271a26be0d8a84f0bd54c8c302e7cb3a3b5d1fa6780a40bcce2873477dab658", 32}, | |
| 75 {"b08693ec2e721597130641e8211e7eedccb4c26413963eee6c1e2ed16ffb1a5f", 32}, | |
| 76 {"46f6ffadd3d06a09ff3c5860d2755c8b9819db7df44251788c7d8e3180de8eb1", 32}, | |
| 77 }; | |
| 78 | |
| 64 // Incremental roots from building the sample tree of size 8 leaf-by-leaf. | 79 // Incremental roots from building the sample tree of size 8 leaf-by-leaf. |
| 65 // The first entry is the root at size 0, the last is the root at size 8. | 80 // The first entry is the root at size 0, the last is the root at size 8. |
| 66 const TestVector kSHA256Roots[8] = { | 81 const TestVector kSHA256Roots[8] = { |
| 67 {"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, | 82 {"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, |
| 68 {"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", 32}, | 83 {"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", 32}, |
| 69 {"aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", 32}, | 84 {"aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", 32}, |
| 70 {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", 32}, | 85 {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", 32}, |
| 71 {"4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4", 32}, | 86 {"4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4", 32}, |
| 72 {"76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef", 32}, | 87 {"76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef", 32}, |
| 73 {"ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", 32}, | 88 {"ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", 32}, |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 97 32}}}, | 112 32}}}, |
| 98 // Consistency proof between tree of size 2 and tree of size 5, with 2 | 113 // Consistency proof between tree of size 2 and tree of size 5, with 2 |
| 99 // nodes in the proof. | 114 // nodes in the proof. |
| 100 {2, | 115 {2, |
| 101 5, | 116 5, |
| 102 2, | 117 2, |
| 103 {{"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, | 118 {{"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, |
| 104 {"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", 32}, | 119 {"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", 32}, |
| 105 {"", 0}}}}; | 120 {"", 0}}}}; |
| 106 | 121 |
| 122 // A single audit proof. Contains the leaf index (leaf), tree size (snapshot), | |
| 123 // the length of the proof (proof_length) and at most 3 proof nodes (all test | |
| 124 // proofs will be for a tree of size 8). | |
| 125 struct PathTestVector { | |
| 126 int leaf; | |
| 127 int snapshot; | |
|
Ryan Sleevi
2016/07/26 19:33:44
Why are these stored as int, and then force-coerce
Rob Percival
2016/07/28 05:18:47
The answer to most of your following comments is t
| |
| 128 int path_length; | |
|
Ryan Sleevi
2016/07/26 19:33:45
path_length should be size_t
Rob Percival
2016/08/25 17:44:59
Done.
| |
| 129 TestVector path[3]; | |
| 130 }; | |
| 131 | |
| 132 // A collection of audit proofs for various leaves and sub-trees of the tree | |
| 133 // defined by |kSHA256Roots|. | |
| 134 const PathTestVector kSHA256Paths[6] = { | |
| 135 {0, 0, 0, {{"", 0}, {"", 0}, {"", 0}}}, | |
| 136 {1, 1, 0, {{"", 0}, {"", 0}, {"", 0}}}, | |
| 137 {1, | |
| 138 8, | |
| 139 3, | |
| 140 {{"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", 32}, | |
| 141 {"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, | |
| 142 {"6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4", | |
| 143 32}}}, | |
| 144 {6, | |
| 145 8, | |
| 146 3, | |
| 147 {{"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", 32}, | |
| 148 {"ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0", 32}, | |
| 149 {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", | |
| 150 32}}}, | |
| 151 {3, | |
| 152 3, | |
| 153 1, | |
| 154 {{"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", 32}, | |
| 155 {"", 0}, | |
| 156 {"", 0}}}, | |
| 157 {2, | |
| 158 5, | |
| 159 3, | |
| 160 {{"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, | |
| 161 {"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, | |
| 162 {"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", | |
| 163 32}}}}; | |
| 164 | |
| 107 // Decodes a hexadecimal string into the binary data it represents. | 165 // Decodes a hexadecimal string into the binary data it represents. |
| 108 std::string HexToBytes(const char* hex_data, size_t hex_data_length) { | 166 std::string HexToBytes(const char* hex_data, size_t hex_data_length) { |
| 109 std::vector<uint8_t> output; | 167 std::vector<uint8_t> output; |
| 110 std::string result; | 168 std::string result; |
| 111 std::string hex_data_input(hex_data, hex_data_length); | 169 std::string hex_data_input(hex_data, hex_data_length); |
| 112 if (base::HexStringToBytes(hex_data, &output)) | 170 if (base::HexStringToBytes(hex_data, &output)) |
| 113 result.assign(reinterpret_cast<const char*>(&output[0]), output.size()); | 171 result.assign(reinterpret_cast<const char*>(&output[0]), output.size()); |
| 114 return result; | 172 return result; |
| 115 } | 173 } |
| 116 | 174 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 131 const std::string& old_tree_root, | 189 const std::string& old_tree_root, |
| 132 uint64_t new_tree_size, | 190 uint64_t new_tree_size, |
| 133 const std::string& new_tree_root, | 191 const std::string& new_tree_root, |
| 134 const std::vector<std::string>& proof) { | 192 const std::vector<std::string>& proof) { |
| 135 return log->VerifyConsistencyProof( | 193 return log->VerifyConsistencyProof( |
| 136 ct::MerkleConsistencyProof(log->key_id(), proof, old_tree_size, | 194 ct::MerkleConsistencyProof(log->key_id(), proof, old_tree_size, |
| 137 new_tree_size), | 195 new_tree_size), |
| 138 old_tree_root, new_tree_root); | 196 old_tree_root, new_tree_root); |
| 139 } | 197 } |
| 140 | 198 |
| 199 bool VerifyAuditProof(scoped_refptr<const CTLogVerifier> log, | |
| 200 uint64_t leaf, | |
| 201 uint64_t tree_size, | |
| 202 const std::vector<std::string>& proof, | |
| 203 const std::string& tree_root, | |
| 204 const std::string& leaf_hash) { | |
| 205 // Test vectors use a 1-based leaf index, but our code uses a 0-based index. | |
|
Ryan Sleevi
2016/07/26 19:33:45
https://groups.google.com/a/chromium.org/d/msg/chr
Rob Percival
2016/07/28 05:18:47
I'll improve this, though I'd like to get rid of t
| |
| 206 if (leaf == 0) | |
| 207 return false; | |
| 208 return log->VerifyAuditProof(ct::MerkleAuditProof(leaf - 1, tree_size, proof), | |
| 209 tree_root, leaf_hash); | |
| 210 } | |
| 211 | |
| 141 class CTLogVerifierTest : public ::testing::Test { | 212 class CTLogVerifierTest : public ::testing::Test { |
| 142 public: | 213 public: |
| 143 CTLogVerifierTest() {} | 214 CTLogVerifierTest() {} |
| 144 | 215 |
| 145 void SetUp() override { | 216 void SetUp() override { |
| 146 log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog", | 217 log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog", |
| 147 "https://ct.example.com", "ct.example.com"); | 218 "https://ct.example.com", "ct.example.com"); |
| 148 | 219 |
| 149 ASSERT_TRUE(log_); | 220 ASSERT_TRUE(log_); |
| 150 ASSERT_EQ(ct::GetTestPublicKeyId(), log_->key_id()); | 221 ASSERT_EQ(ct::GetTestPublicKeyId(), log_->key_id()); |
| 151 ASSERT_EQ("ct.example.com", log_->dns_domain()); | 222 ASSERT_EQ("ct.example.com", log_->dns_domain()); |
| 152 } | 223 } |
| 153 | 224 |
| 225 // Given an audit proof for a leaf in the tree, asserts that it verifies and | |
| 226 // no other combination of leaves, snapshots and proof nodes verifies. | |
|
Ryan Sleevi
2016/07/26 19:33:44
Every one of these checks should be separate tests
Rob Percival
2016/07/28 05:18:47
Again, inherited from the original tests. If I fin
Ryan Sleevi
2016/07/28 16:40:47
Well, whether or not we split it out to parameteri
Rob Percival
2016/08/25 17:44:59
That should be sufficient, but Eran is quite passi
| |
| 227 void VerifierCheck(int leaf, | |
| 228 int tree_size, | |
| 229 const std::vector<std::string>& path, | |
| 230 const std::string& root, | |
| 231 const std::string& leaf_hash) { | |
| 232 // Verify the original path. | |
| 233 EXPECT_TRUE(VerifyAuditProof(log_, leaf, tree_size, path, root, leaf_hash)); | |
| 234 | |
| 235 // Wrong leaf index. | |
| 236 EXPECT_FALSE( | |
| 237 VerifyAuditProof(log_, leaf - 1, tree_size, path, root, leaf_hash)); | |
| 238 EXPECT_FALSE( | |
| 239 VerifyAuditProof(log_, leaf + 1, tree_size, path, root, leaf_hash)); | |
| 240 EXPECT_FALSE( | |
| 241 VerifyAuditProof(log_, leaf ^ 2, tree_size, path, root, leaf_hash)); | |
| 242 | |
| 243 // Wrong tree height. | |
| 244 EXPECT_FALSE( | |
| 245 VerifyAuditProof(log_, leaf, tree_size * 2, path, root, leaf_hash)); | |
| 246 EXPECT_FALSE( | |
| 247 VerifyAuditProof(log_, leaf, tree_size / 2, path, root, leaf_hash)); | |
| 248 | |
| 249 // Wrong root. | |
| 250 EXPECT_FALSE(VerifyAuditProof(log_, leaf, tree_size, path, | |
| 251 HexToBytes(kSHA256EmptyTreeHash), leaf_hash)); | |
| 252 | |
| 253 // Wrong paths. | |
| 254 std::vector<std::string> wrong_path; | |
| 255 | |
| 256 // Modify a single element on the path. | |
| 257 for (size_t j = 0; j < path.size(); ++j) { | |
| 258 wrong_path = path; | |
| 259 wrong_path[j] = HexToBytes(kSHA256EmptyTreeHash); | |
| 260 EXPECT_FALSE( | |
| 261 VerifyAuditProof(log_, leaf, tree_size, wrong_path, root, leaf_hash)); | |
| 262 } | |
| 263 | |
| 264 // Add garbage at the end of the path. | |
| 265 wrong_path = path; | |
| 266 wrong_path.push_back(std::string()); | |
| 267 EXPECT_FALSE( | |
| 268 VerifyAuditProof(log_, leaf, tree_size, wrong_path, root, leaf_hash)); | |
| 269 wrong_path.pop_back(); | |
| 270 | |
| 271 wrong_path.push_back(root); | |
| 272 EXPECT_FALSE( | |
| 273 VerifyAuditProof(log_, leaf, tree_size, wrong_path, root, leaf_hash)); | |
| 274 wrong_path.pop_back(); | |
| 275 | |
| 276 // Remove a node from the end. | |
| 277 if (!wrong_path.empty()) { | |
| 278 wrong_path.pop_back(); | |
| 279 EXPECT_FALSE( | |
| 280 VerifyAuditProof(log_, leaf, tree_size, wrong_path, root, leaf_hash)); | |
| 281 } | |
| 282 | |
| 283 // Add garbage in the beginning of the path. | |
| 284 wrong_path.clear(); | |
| 285 wrong_path.push_back(std::string()); | |
| 286 wrong_path.insert(wrong_path.end(), path.begin(), path.end()); | |
| 287 EXPECT_FALSE( | |
| 288 VerifyAuditProof(log_, leaf, tree_size, wrong_path, root, leaf_hash)); | |
| 289 | |
| 290 wrong_path[0] = root; | |
| 291 EXPECT_FALSE( | |
| 292 VerifyAuditProof(log_, leaf, tree_size, wrong_path, root, leaf_hash)); | |
| 293 } | |
| 294 | |
| 154 // Given a consistency proof between two snapshots of the tree, asserts that | 295 // Given a consistency proof between two snapshots of the tree, asserts that |
| 155 // it verifies and no other combination of snapshots and proof nodes verifies. | 296 // it verifies and no other combination of snapshots and proof nodes verifies. |
| 156 void VerifierConsistencyCheck(int snapshot1, | 297 void VerifierConsistencyCheck(int snapshot1, |
| 157 int snapshot2, | 298 int snapshot2, |
| 158 const std::string& root1, | 299 const std::string& root1, |
| 159 const std::string& root2, | 300 const std::string& root2, |
| 160 const std::vector<std::string>& proof) { | 301 const std::vector<std::string>& proof) { |
| 161 // Verify the original consistency proof. | 302 // Verify the original consistency proof. |
| 162 EXPECT_TRUE( | 303 EXPECT_TRUE( |
| 163 VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, root2, proof)) | 304 VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, root2, proof)) |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 432 if (input_size == 1) | 573 if (input_size == 1) |
| 433 return TreeHasher::HashLeaf(inputs[0]); | 574 return TreeHasher::HashLeaf(inputs[0]); |
| 434 | 575 |
| 435 const uint64_t split = CalculateNearestPowerOfTwo(input_size); | 576 const uint64_t split = CalculateNearestPowerOfTwo(input_size); |
| 436 | 577 |
| 437 return ct::internal::HashNodes( | 578 return ct::internal::HashNodes( |
| 438 ReferenceMerkleTreeHash(&inputs[0], split), | 579 ReferenceMerkleTreeHash(&inputs[0], split), |
| 439 ReferenceMerkleTreeHash(&inputs[split], input_size - split)); | 580 ReferenceMerkleTreeHash(&inputs[split], input_size - split)); |
| 440 } | 581 } |
| 441 | 582 |
| 583 // Reference implementation of Merkle paths. Path from leaf to root, | |
| 584 // excluding the leaf and root themselves. Returns an audit proof for the tree | |
| 585 // leaf with index |leaf| (1-based). The tree is designated by |inputs|. | |
| 586 std::vector<std::string> ReferenceMerklePath(std::string* inputs, | |
| 587 uint64_t input_size, | |
| 588 uint64_t leaf) { | |
| 589 std::vector<std::string> path; | |
| 590 if (leaf > input_size || leaf == 0) | |
| 591 return path; | |
| 592 | |
| 593 if (input_size == 1) | |
| 594 return path; | |
| 595 | |
| 596 const uint64_t split = CalculateNearestPowerOfTwo(input_size); | |
| 597 | |
| 598 std::vector<std::string> subpath; | |
| 599 if (leaf <= split) { | |
| 600 subpath = ReferenceMerklePath(&inputs[0], split, leaf); | |
| 601 path.insert(path.end(), subpath.begin(), subpath.end()); | |
| 602 path.push_back(ReferenceMerkleTreeHash(&inputs[split], input_size - split)); | |
| 603 } else { | |
| 604 subpath = | |
| 605 ReferenceMerklePath(&inputs[split], input_size - split, leaf - split); | |
| 606 path.insert(path.end(), subpath.begin(), subpath.end()); | |
| 607 path.push_back(ReferenceMerkleTreeHash(&inputs[0], split)); | |
| 608 } | |
| 609 | |
| 610 return path; | |
| 611 } | |
| 612 | |
| 442 // Reference implementation of snapshot consistency. Returns a | 613 // Reference implementation of snapshot consistency. Returns a |
| 443 // consistency proof between two snapshots of the tree designated | 614 // consistency proof between two snapshots of the tree designated |
| 444 // by |inputs|. | 615 // by |inputs|. |
| 445 // Call with have_root1 = true. | 616 // Call with have_root1 = true. |
| 446 std::vector<std::string> ReferenceSnapshotConsistency(std::string* inputs, | 617 std::vector<std::string> ReferenceSnapshotConsistency(std::string* inputs, |
| 447 uint64_t snapshot2, | 618 uint64_t snapshot2, |
| 448 uint64_t snapshot1, | 619 uint64_t snapshot1, |
| 449 bool have_root1) { | 620 bool have_root1) { |
| 450 std::vector<std::string> proof; | 621 std::vector<std::string> proof; |
| 451 if (snapshot1 == 0 || snapshot1 > snapshot2) | 622 if (snapshot1 == 0 || snapshot1 > snapshot2) |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 497 TEST_F(CTLogVerifierTest, | 668 TEST_F(CTLogVerifierTest, |
| 498 MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator) { | 669 MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator) { |
| 499 std::vector<std::string> data; | 670 std::vector<std::string> data; |
| 500 for (int i = 0; i < 256; ++i) | 671 for (int i = 0; i < 256; ++i) |
| 501 data.push_back(std::string(1, i)); | 672 data.push_back(std::string(1, i)); |
| 502 | 673 |
| 503 std::vector<std::string> proof; | 674 std::vector<std::string> proof; |
| 504 std::string root1, root2; | 675 std::string root1, root2; |
| 505 // More tests with reference proof generator. | 676 // More tests with reference proof generator. |
| 506 for (size_t tree_size = 1; tree_size <= data.size() / 2; ++tree_size) { | 677 for (size_t tree_size = 1; tree_size <= data.size() / 2; ++tree_size) { |
| 678 SCOPED_TRACE(tree_size); | |
| 507 root2 = ReferenceMerkleTreeHash(data.data(), tree_size); | 679 root2 = ReferenceMerkleTreeHash(data.data(), tree_size); |
| 508 // Repeat for each snapshot in range. | 680 // Repeat for each snapshot in range. |
| 509 for (size_t snapshot = 1; snapshot <= tree_size; ++snapshot) { | 681 for (size_t snapshot = 1; snapshot <= tree_size; ++snapshot) { |
| 682 SCOPED_TRACE(snapshot); | |
| 510 proof = | 683 proof = |
| 511 ReferenceSnapshotConsistency(data.data(), tree_size, snapshot, true); | 684 ReferenceSnapshotConsistency(data.data(), tree_size, snapshot, true); |
| 512 root1 = ReferenceMerkleTreeHash(data.data(), snapshot); | 685 root1 = ReferenceMerkleTreeHash(data.data(), snapshot); |
| 513 VerifierConsistencyCheck(snapshot, tree_size, root1, root2, proof); | 686 VerifierConsistencyCheck(snapshot, tree_size, root1, root2, proof); |
| 514 } | 687 } |
| 515 } | 688 } |
| 516 } | 689 } |
| 517 | 690 |
| 691 TEST_F(CTLogVerifierTest, VerifiesAuditProofEdgeCases_EmptyProof) { | |
| 692 std::vector<std::string> path; | |
| 693 // Various invalid paths. | |
| 694 EXPECT_FALSE( | |
| 695 VerifyAuditProof(log_, 0, 0, path, std::string(), std::string())); | |
| 696 EXPECT_FALSE( | |
| 697 VerifyAuditProof(log_, 0, 1, path, std::string(), std::string())); | |
| 698 EXPECT_FALSE( | |
| 699 VerifyAuditProof(log_, 1, 0, path, std::string(), std::string())); | |
| 700 EXPECT_FALSE( | |
| 701 VerifyAuditProof(log_, 2, 1, path, std::string(), std::string())); | |
|
Ryan Sleevi
2016/07/26 19:33:44
All should be grouped into a new test; this seems
Rob Percival
2016/08/25 17:44:59
Done. The cases with a leaf index of 0 were pointl
| |
| 702 | |
| 703 const std::string empty_hash = HexToBytes(kSHA256EmptyTreeHash); | |
| 704 EXPECT_FALSE(VerifyAuditProof(log_, 0, 0, path, empty_hash, std::string())); | |
| 705 EXPECT_FALSE(VerifyAuditProof(log_, 0, 1, path, empty_hash, std::string())); | |
| 706 EXPECT_FALSE(VerifyAuditProof(log_, 1, 0, path, empty_hash, std::string())); | |
| 707 EXPECT_FALSE(VerifyAuditProof(log_, 2, 1, path, empty_hash, std::string())); | |
| 708 } | |
| 709 | |
| 710 TEST_F(CTLogVerifierTest, VerifiesValidAuditProofs) { | |
| 711 std::vector<std::string> path; | |
| 712 // Known good paths. | |
| 713 // i = 0 is an invalid path. | |
| 714 for (int i = 1; i < 6; ++i) { | |
| 715 SCOPED_TRACE(i); | |
| 716 // Construct the path. | |
| 717 path.clear(); | |
| 718 for (int j = 0; j < kSHA256Paths[i].path_length; ++j) | |
| 719 path.push_back(HexToBytes(kSHA256Paths[i].path[j])); | |
| 720 const TestVector& root_hash = kSHA256Roots[kSHA256Paths[i].snapshot - 1]; | |
| 721 VerifierCheck(kSHA256Paths[i].leaf, kSHA256Paths[i].snapshot, path, | |
| 722 HexToBytes(root_hash), | |
| 723 HexToBytes(kSHA256LeafHashes[kSHA256Paths[i].leaf - 1])); | |
| 724 } | |
| 725 } | |
| 726 | |
| 727 TEST_F(CTLogVerifierTest, VerifiesValidAuditProofsFromReferenceGenerator) { | |
| 728 std::vector<std::string> data; | |
| 729 for (size_t i = 0; i < 256; ++i) | |
| 730 data.emplace_back(1, i); | |
| 731 | |
| 732 // More tests with reference path generator. | |
| 733 std::string root; | |
| 734 std::vector<std::string> path; | |
| 735 for (size_t tree_size = 1; tree_size <= data.size() / 2; ++tree_size) { | |
| 736 SCOPED_TRACE(tree_size); | |
| 737 // Repeat for each leaf in range. | |
| 738 for (size_t leaf = 1; leaf <= tree_size; ++leaf) { | |
| 739 SCOPED_TRACE(leaf); | |
| 740 path = ReferenceMerklePath(data.data(), tree_size, leaf); | |
| 741 root = ReferenceMerkleTreeHash(data.data(), tree_size); | |
| 742 VerifierCheck(leaf, tree_size, path, root, | |
| 743 TreeHasher::HashLeaf(data[leaf - 1])); | |
| 744 } | |
| 745 } | |
| 746 } | |
| 747 | |
| 518 } // namespace | 748 } // namespace |
| 519 | 749 |
| 520 } // namespace net | 750 } // namespace net |
| OLD | NEW |