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> |
(...skipping 23 matching lines...) Expand all Loading... | |
34 ret >>= 1; | 34 ret >>= 1; |
35 | 35 |
36 return ret; | 36 return ret; |
37 } | 37 } |
38 | 38 |
39 // The following structures, TestVector and ProofTestVector are used for | 39 // The following structures, TestVector and ProofTestVector are used for |
40 // definining test proofs later on. | 40 // definining test proofs later on. |
41 | 41 |
42 // A single hash node. | 42 // A single hash node. |
43 struct TestVector { | 43 struct TestVector { |
44 const char* const str; | 44 const char* const str; // hex string |
45 size_t length_bytes; | 45 size_t length_bytes; // number of bytes represented by |str| |
46 }; | 46 }; |
47 | 47 |
48 // A single consistency proof. Contains the old and new tree sizes | 48 // A single consistency proof. Contains the old and new tree sizes |
49 // (snapshot1 and snapshot2), the length of the proof (proof_length) and | 49 // (snapshot1 and snapshot2), the length of the proof (proof_length) and |
50 // at most 3 proof nodes (all test proofs will be for a tree of size 8). | 50 // at most 3 proof nodes (all test proofs will be for a tree of size 8). |
51 struct ProofTestVector { | 51 struct ProofTestVector { |
52 uint64_t snapshot1; | 52 uint64_t snapshot1; |
53 uint64_t snapshot2; | 53 uint64_t snapshot2; |
54 size_t proof_length; | 54 size_t proof_length; |
55 TestVector proof[3]; | 55 TestVector proof[3]; |
56 }; | 56 }; |
57 | 57 |
58 // All test data replicated from | 58 // All test data replicated from |
59 // https://github.com/google/certificate-transparency/blob/c41b090ecc14ddd6b3531 dc7e5ce36b21e253fdd/cpp/merkletree/merkle_tree_test.cc | 59 // https://github.com/google/certificate-transparency/blob/c41b090ecc14ddd6b3531 dc7e5ce36b21e253fdd/cpp/merkletree/merkle_tree_test.cc |
60 // A hash of the empty string. | 60 // A hash of the empty string. |
61 const TestVector kSHA256EmptyTreeHash = { | 61 const TestVector kSHA256EmptyTreeHash = { |
62 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", 32}; | 62 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", 32}; |
63 | 63 |
64 // Node hashes for a sample tree of size 8 (each element in this array is | 64 // Incremental roots from building the sample tree of size 8 leaf-by-leaf. |
65 // a node hash, not leaf data; order represents order of the nodes in the tree). | 65 // The first entry is the root at size 0, the last is the root at size 8. |
66 const TestVector kSHA256Roots[8] = { | 66 const TestVector kSHA256Roots[8] = { |
67 {"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, | 67 {"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, |
68 {"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", 32}, | 68 {"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", 32}, |
69 {"aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", 32}, | 69 {"aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", 32}, |
70 {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", 32}, | 70 {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", 32}, |
71 {"4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4", 32}, | 71 {"4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4", 32}, |
72 {"76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef", 32}, | 72 {"76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef", 32}, |
73 {"ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", 32}, | 73 {"ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", 32}, |
74 {"5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328", 32}}; | 74 {"5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328", 32}}; |
75 | 75 |
76 // A collection of consistency proofs between various sub-trees of the tree | 76 // A collection of consistency proofs between various nodes of the sample tree. |
77 // defined by |kSHA256Roots|. | |
78 const ProofTestVector kSHA256Proofs[4] = { | 77 const ProofTestVector kSHA256Proofs[4] = { |
79 // Empty consistency proof between trees of the same size (1). | 78 // Empty consistency proof between trees of the same size (1). |
80 {1, 1, 0, {{"", 0}, {"", 0}, {"", 0}}}, | 79 {1, 1, 0, {{"", 0}, {"", 0}, {"", 0}}}, |
81 // Consistency proof between tree of size 1 and tree of size 8, with 3 | 80 // Consistency proof between tree of size 1 and tree of size 8, with 3 |
82 // nodes in the proof. | 81 // nodes in the proof. |
83 {1, | 82 {1, |
84 8, | 83 8, |
85 3, | 84 3, |
86 {{"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", 32}, | 85 {{"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", 32}, |
87 {"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, | 86 {"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, |
(...skipping 20 matching lines...) Expand all Loading... | |
108 // Decodes a hexadecimal string into the binary data it represents. | 107 // Decodes a hexadecimal string into the binary data it represents. |
109 std::string HexToBytes(const char* hex_data, size_t hex_data_length) { | 108 std::string HexToBytes(const char* hex_data, size_t hex_data_length) { |
110 std::vector<uint8_t> output; | 109 std::vector<uint8_t> output; |
111 std::string result; | 110 std::string result; |
112 std::string hex_data_input(hex_data, hex_data_length); | 111 std::string hex_data_input(hex_data, hex_data_length); |
113 if (base::HexStringToBytes(hex_data, &output)) | 112 if (base::HexStringToBytes(hex_data, &output)) |
114 result.assign(reinterpret_cast<const char*>(&output[0]), output.size()); | 113 result.assign(reinterpret_cast<const char*>(&output[0]), output.size()); |
115 return result; | 114 return result; |
116 } | 115 } |
117 | 116 |
117 std::string HexToBytes(const TestVector& x) { | |
118 std::string bytes = HexToBytes(x.str, x.length_bytes * 2); | |
119 CHECK_EQ(x.length_bytes, bytes.size()); | |
120 return bytes; | |
121 } | |
122 | |
118 std::string GetEmptyTreeHash() { | 123 std::string GetEmptyTreeHash() { |
119 return HexToBytes(kSHA256EmptyTreeHash.str, | 124 return HexToBytes(kSHA256EmptyTreeHash); |
120 kSHA256EmptyTreeHash.length_bytes); | |
Ryan Sleevi
2016/07/26 18:25:14
Wait, so this whole time, the empty tree hash was
Eran Messeri
2016/07/26 18:32:08
Turns out it wasn't, because of a bug in the HexTo
Ryan Sleevi
2016/07/26 18:36:24
So why does this CL leave the bug in place then? (
Rob Percival
2016/08/25 16:23:34
I've broken out a fix for this into https://codere
| |
121 } | 125 } |
122 | 126 |
123 // Creates a ct::MerkleConsistencyProof and returns the result of | 127 // Creates a ct::MerkleConsistencyProof and returns the result of |
124 // calling log->VerifyConsistencyProof with that proof and snapshots. | 128 // calling log->VerifyConsistencyProof with that proof and snapshots. |
125 bool VerifyConsistencyProof(scoped_refptr<const CTLogVerifier> log, | 129 bool VerifyConsistencyProof(scoped_refptr<const CTLogVerifier> log, |
126 uint64_t old_tree_size, | 130 uint64_t old_tree_size, |
127 const std::string& old_tree_root, | 131 const std::string& old_tree_root, |
128 uint64_t new_tree_size, | 132 uint64_t new_tree_size, |
129 const std::string& new_tree_root, | 133 const std::string& new_tree_root, |
130 const std::vector<std::string>& proof) { | 134 const std::vector<std::string>& proof) { |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
372 EXPECT_FALSE(VerifyConsistencyProof(log_, 1, empty_tree_hash, 1, | 376 EXPECT_FALSE(VerifyConsistencyProof(log_, 1, empty_tree_hash, 1, |
373 empty_tree_hash, proof)); | 377 empty_tree_hash, proof)); |
374 } | 378 } |
375 | 379 |
376 TEST_F(CTLogVerifierTest, VerifiesValidConsistencyProofs) { | 380 TEST_F(CTLogVerifierTest, VerifiesValidConsistencyProofs) { |
377 std::vector<std::string> proof; | 381 std::vector<std::string> proof; |
378 std::string root1, root2; | 382 std::string root1, root2; |
379 | 383 |
380 // Known good proofs. | 384 // Known good proofs. |
381 for (size_t i = 0; i < arraysize(kSHA256Proofs); ++i) { | 385 for (size_t i = 0; i < arraysize(kSHA256Proofs); ++i) { |
386 SCOPED_TRACE(i); | |
382 proof.clear(); | 387 proof.clear(); |
383 for (size_t j = 0; j < kSHA256Proofs[i].proof_length; ++j) { | 388 for (size_t j = 0; j < kSHA256Proofs[i].proof_length; ++j) { |
384 const TestVector& v = kSHA256Proofs[i].proof[j]; | 389 const TestVector& v = kSHA256Proofs[i].proof[j]; |
385 proof.push_back(HexToBytes(v.str, v.length_bytes)); | 390 proof.push_back(HexToBytes(v)); |
386 } | 391 } |
387 const uint64_t snapshot1 = kSHA256Proofs[i].snapshot1; | 392 const uint64_t snapshot1 = kSHA256Proofs[i].snapshot1; |
388 const uint64_t snapshot2 = kSHA256Proofs[i].snapshot2; | 393 const uint64_t snapshot2 = kSHA256Proofs[i].snapshot2; |
389 const TestVector& old_root = kSHA256Roots[snapshot1 - 1]; | 394 const TestVector& old_root = kSHA256Roots[snapshot1 - 1]; |
390 const TestVector& new_root = kSHA256Roots[snapshot2 - 1]; | 395 const TestVector& new_root = kSHA256Roots[snapshot2 - 1]; |
391 VerifierConsistencyCheck( | 396 VerifierConsistencyCheck(snapshot1, snapshot2, HexToBytes(old_root), |
392 snapshot1, snapshot2, HexToBytes(old_root.str, old_root.length_bytes), | 397 HexToBytes(new_root), proof); |
393 HexToBytes(new_root.str, new_root.length_bytes), proof); | |
394 } | 398 } |
395 } | 399 } |
396 | 400 |
397 const char kLeafPrefix[] = {'\x00'}; | 401 const char kLeafPrefix[] = {'\x00'}; |
398 | 402 |
399 // Reference implementation of RFC6962. | 403 // Reference implementation of RFC6962. |
400 // This allows generation of arbitrary-sized Merkle trees and consistency | 404 // This allows generation of arbitrary-sized Merkle trees and consistency |
401 // proofs between them for testing the consistency proof validation | 405 // proofs between them for testing the consistency proof validation |
402 // code. | 406 // code. |
403 class TreeHasher { | 407 class TreeHasher { |
404 public: | 408 public: |
405 static std::string HashEmpty() { | 409 static std::string HashEmpty() { return HexToBytes(kSHA256EmptyTreeHash); } |
406 return HexToBytes(kSHA256EmptyTreeHash.str, | |
407 kSHA256EmptyTreeHash.length_bytes); | |
408 } | |
409 | 410 |
410 static std::string HashLeaf(const std::string& leaf) { | 411 static std::string HashLeaf(const std::string& leaf) { |
411 SHA256HashValue sha256; | 412 SHA256HashValue sha256; |
412 memset(sha256.data, 0, sizeof(sha256.data)); | 413 memset(sha256.data, 0, sizeof(sha256.data)); |
413 | 414 |
414 std::unique_ptr<crypto::SecureHash> hash( | 415 std::unique_ptr<crypto::SecureHash> hash( |
415 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); | 416 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); |
416 hash->Update(kLeafPrefix, 1); | 417 hash->Update(kLeafPrefix, 1); |
417 hash->Update(leaf.data(), leaf.size()); | 418 hash->Update(leaf.data(), leaf.size()); |
418 hash->Finish(sha256.data, sizeof(sha256.data)); | 419 hash->Finish(sha256.data, sizeof(sha256.data)); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
487 | 488 |
488 // Times out on Win7 test bot. http://crbug.com/598406 | 489 // Times out on Win7 test bot. http://crbug.com/598406 |
489 #if defined(OS_WIN) | 490 #if defined(OS_WIN) |
490 #define MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator \ | 491 #define MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator \ |
491 DISABLED_VerifiesValidConsistencyProofsFromReferenceGenerator | 492 DISABLED_VerifiesValidConsistencyProofsFromReferenceGenerator |
492 #else | 493 #else |
493 #define MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator \ | 494 #define MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator \ |
494 VerifiesValidConsistencyProofsFromReferenceGenerator | 495 VerifiesValidConsistencyProofsFromReferenceGenerator |
495 #endif | 496 #endif |
496 TEST_F(CTLogVerifierTest, | 497 TEST_F(CTLogVerifierTest, |
497 MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator) { | 498 MAYBE_VerifiesValidConsistencyProofsFromReferenceGenerator) { |
Ryan Sleevi
2016/07/26 18:40:29
Since you're improving documentation, this test is
Rob Percival
2016/08/25 16:23:34
Done.
| |
498 std::vector<std::string> data; | 499 std::vector<std::string> data; |
499 for (int i = 0; i < 256; ++i) | 500 for (int i = 0; i < 256; ++i) |
500 data.push_back(std::string(1, i)); | 501 data.push_back(std::string(1, i)); |
501 | 502 |
502 std::vector<std::string> proof; | 503 std::vector<std::string> proof; |
503 std::string root1, root2; | 504 std::string root1, root2; |
504 // More tests with reference proof generator. | 505 // More tests with reference proof generator. |
505 for (size_t tree_size = 1; tree_size <= data.size() / 2; ++tree_size) { | 506 for (size_t tree_size = 1; tree_size <= data.size() / 2; ++tree_size) { |
506 root2 = ReferenceMerkleTreeHash(data.data(), tree_size); | 507 root2 = ReferenceMerkleTreeHash(data.data(), tree_size); |
507 // Repeat for each snapshot in range. | 508 // Repeat for each snapshot in range. |
508 for (size_t snapshot = 1; snapshot <= tree_size; ++snapshot) { | 509 for (size_t snapshot = 1; snapshot <= tree_size; ++snapshot) { |
509 proof = | 510 proof = |
510 ReferenceSnapshotConsistency(data.data(), tree_size, snapshot, true); | 511 ReferenceSnapshotConsistency(data.data(), tree_size, snapshot, true); |
511 root1 = ReferenceMerkleTreeHash(data.data(), snapshot); | 512 root1 = ReferenceMerkleTreeHash(data.data(), snapshot); |
512 VerifierConsistencyCheck(snapshot, tree_size, root1, root2, proof); | 513 VerifierConsistencyCheck(snapshot, tree_size, root1, root2, proof); |
513 } | 514 } |
514 } | 515 } |
515 } | 516 } |
516 | 517 |
517 } // namespace | 518 } // namespace |
518 | 519 |
519 } // namespace net | 520 } // namespace net |
OLD | NEW |