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 19 matching lines...) Expand all Loading... | |
30 uint64_t CalculateNearestPowerOfTwo(uint64_t n) { | 30 uint64_t CalculateNearestPowerOfTwo(uint64_t n) { |
31 DCHECK_GT(n, 1u); | 31 DCHECK_GT(n, 1u); |
32 | 32 |
33 uint64_t ret = UINT64_C(1) << 63; | 33 uint64_t ret = UINT64_C(1) << 63; |
34 while (ret >= n) | 34 while (ret >= n) |
35 ret >>= 1; | 35 ret >>= 1; |
36 | 36 |
37 return ret; | 37 return ret; |
38 } | 38 } |
39 | 39 |
40 // The following structures, TestVector and ProofTestVector are used for | |
41 // definining test proofs later on. | |
42 | |
43 // A single hash node. | |
44 struct TestVector { | |
45 const char* const str; | |
46 size_t length_bytes; | |
47 }; | |
48 | |
49 // A single consistency proof. Contains the old and new tree sizes | 40 // A single consistency proof. Contains the old and new tree sizes |
50 // (snapshot1 and snapshot2), the length of the proof (proof_length) and | 41 // (snapshot1 and snapshot2), the length of the proof (proof_length) and |
51 // at most 3 proof nodes (all test proofs will be for a tree of size 8). | 42 // at most 3 proof nodes (all test proofs will be for a tree of size 8). |
52 struct ProofTestVector { | 43 struct ProofTestVector { |
53 uint64_t snapshot1; | 44 uint64_t snapshot1; |
54 uint64_t snapshot2; | 45 uint64_t snapshot2; |
55 size_t proof_length; | 46 size_t proof_length; |
56 TestVector proof[3]; | 47 const char* const proof[3]; |
57 }; | 48 }; |
58 | 49 |
59 // All test data replicated from | 50 // All test data replicated from |
60 // https://github.com/google/certificate-transparency/blob/c41b090ecc14ddd6b3531 dc7e5ce36b21e253fdd/cpp/merkletree/merkle_tree_test.cc | 51 // https://github.com/google/certificate-transparency/blob/c41b090ecc14ddd6b3531 dc7e5ce36b21e253fdd/cpp/merkletree/merkle_tree_test.cc |
61 // A hash of the empty string. | 52 // A hash of the empty string. |
62 const TestVector kSHA256EmptyTreeHash = { | 53 const char* const kSHA256EmptyTreeHash = |
63 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", 32}; | 54 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; |
64 | 55 |
65 // Node hashes for a sample tree of size 8 (each element in this array is | 56 // Node hashes for a sample tree of size 8 (each element in this array is |
66 // a node hash, not leaf data; order represents order of the nodes in the tree). | 57 // a node hash, not leaf data; order represents order of the nodes in the tree). |
67 const TestVector kSHA256Roots[8] = { | 58 const char* const kSHA256Roots[8] = { |
68 {"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, | 59 "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", |
69 {"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", 32}, | 60 "fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", |
70 {"aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", 32}, | 61 "aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", |
71 {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", 32}, | 62 "d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", |
72 {"4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4", 32}, | 63 "4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4", |
73 {"76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef", 32}, | 64 "76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef", |
74 {"ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", 32}, | 65 "ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", |
75 {"5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328", 32}}; | 66 "5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328"}; |
76 | 67 |
77 // A collection of consistency proofs between various sub-trees of the tree | 68 // A collection of consistency proofs between various sub-trees of the tree |
78 // defined by |kSHA256Roots|. | 69 // defined by |kSHA256Roots|. |
79 const ProofTestVector kSHA256Proofs[4] = { | 70 const ProofTestVector kSHA256Proofs[4] = { |
80 // Empty consistency proof between trees of the same size (1). | 71 // Empty consistency proof between trees of the same size (1). |
81 {1, 1, 0, {{"", 0}, {"", 0}, {"", 0}}}, | 72 {1, 1, 0, {"", "", ""}}, |
82 // Consistency proof between tree of size 1 and tree of size 8, with 3 | 73 // Consistency proof between tree of size 1 and tree of size 8, with 3 |
83 // nodes in the proof. | 74 // nodes in the proof. |
84 {1, | 75 {1, |
85 8, | 76 8, |
86 3, | 77 3, |
87 {{"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", 32}, | 78 {"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", |
88 {"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, | 79 "5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", |
89 {"6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4", | 80 "6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4"}}, |
90 32}}}, | |
91 // Consistency proof between tree of size 6 and tree of size 8, with 3 | 81 // Consistency proof between tree of size 6 and tree of size 8, with 3 |
92 // nodes in the proof. | 82 // nodes in the proof. |
93 {6, | 83 {6, |
94 8, | 84 8, |
95 3, | 85 3, |
96 {{"0ebc5d3437fbe2db158b9f126a1d118e308181031d0a949f8dededebc558ef6a", 32}, | 86 {"0ebc5d3437fbe2db158b9f126a1d118e308181031d0a949f8dededebc558ef6a", |
97 {"ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0", 32}, | 87 "ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0", |
98 {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", | 88 "d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7"}}, |
99 32}}}, | |
100 // Consistency proof between tree of size 2 and tree of size 5, with 2 | 89 // Consistency proof between tree of size 2 and tree of size 5, with 2 |
101 // nodes in the proof. | 90 // nodes in the proof. |
102 {2, | 91 {2, |
103 5, | 92 5, |
104 2, | 93 2, |
105 {{"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, | 94 {"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", |
106 {"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", 32}, | 95 "bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", ""}}}; |
107 {"", 0}}}}; | |
108 | 96 |
109 // Decodes a hexadecimal string into the binary data it represents. | 97 // Decodes a hexadecimal string into the binary data it represents. |
110 std::string HexToBytes(const char* hex_data, size_t hex_data_length) { | 98 std::string HexToBytes(const std::string& hex_data) { |
Ryan Sleevi
2016/08/25 18:32:11
DESIGN: You're (almost) always passing string cons
Rob Percival
2016/08/25 19:35:13
base::HexStringToBytes takes a const std::string&,
Ryan Sleevi
2016/08/25 20:15:20
So then, is this a good API to be using? Should yo
Rob Percival
2016/08/25 20:26:40
As I said in a separate comment, I'm in the proces
| |
111 std::vector<uint8_t> output; | 99 std::vector<uint8_t> output; |
112 std::string result; | 100 std::string result; |
113 std::string hex_data_input(hex_data, hex_data_length); | |
114 if (base::HexStringToBytes(hex_data, &output)) | 101 if (base::HexStringToBytes(hex_data, &output)) |
115 result.assign(reinterpret_cast<const char*>(&output[0]), output.size()); | 102 result.assign(output.begin(), output.end()); |
116 return result; | 103 return result; |
117 } | 104 } |
118 | 105 |
119 std::string GetEmptyTreeHash() { | 106 const std::string& GetEmptyTreeHash() { |
120 return HexToBytes(kSHA256EmptyTreeHash.str, | 107 static const std::string empty_hash = HexToBytes(kSHA256EmptyTreeHash); |
Ryan Sleevi
2016/08/25 18:32:11
STYLE: https://google.github.io/styleguide/cppguid
Rob Percival
2016/08/25 19:35:13
Fixed by changing kSHA256EmptyTreeHash to be the d
Ryan Sleevi
2016/08/25 20:15:20
DESIGN: Given that you're clearly concerned about
Rob Percival
2016/08/25 20:26:40
Passing around hashes as char* runs the risk that
| |
121 kSHA256EmptyTreeHash.length_bytes); | 108 return empty_hash; |
122 } | 109 } |
123 | 110 |
124 // Creates a ct::MerkleConsistencyProof and returns the result of | 111 // Creates a ct::MerkleConsistencyProof and returns the result of |
125 // calling log->VerifyConsistencyProof with that proof and snapshots. | 112 // calling log->VerifyConsistencyProof with that proof and snapshots. |
126 bool VerifyConsistencyProof(scoped_refptr<const CTLogVerifier> log, | 113 bool VerifyConsistencyProof(scoped_refptr<const CTLogVerifier> log, |
127 uint64_t old_tree_size, | 114 uint64_t old_tree_size, |
128 const std::string& old_tree_root, | 115 const std::string& old_tree_root, |
129 uint64_t new_tree_size, | 116 uint64_t new_tree_size, |
130 const std::string& new_tree_root, | 117 const std::string& new_tree_root, |
131 const std::vector<std::string>& proof) { | 118 const std::vector<std::string>& proof) { |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
375 } | 362 } |
376 | 363 |
377 TEST_F(CTLogVerifierTest, VerifiesValidConsistencyProofs) { | 364 TEST_F(CTLogVerifierTest, VerifiesValidConsistencyProofs) { |
378 std::vector<std::string> proof; | 365 std::vector<std::string> proof; |
379 std::string root1, root2; | 366 std::string root1, root2; |
380 | 367 |
381 // Known good proofs. | 368 // Known good proofs. |
382 for (size_t i = 0; i < arraysize(kSHA256Proofs); ++i) { | 369 for (size_t i = 0; i < arraysize(kSHA256Proofs); ++i) { |
383 proof.clear(); | 370 proof.clear(); |
384 for (size_t j = 0; j < kSHA256Proofs[i].proof_length; ++j) { | 371 for (size_t j = 0; j < kSHA256Proofs[i].proof_length; ++j) { |
385 const TestVector& v = kSHA256Proofs[i].proof[j]; | 372 const char* const v = kSHA256Proofs[i].proof[j]; |
386 proof.push_back(HexToBytes(v.str, v.length_bytes)); | 373 proof.push_back(HexToBytes(v)); |
387 } | 374 } |
388 const uint64_t snapshot1 = kSHA256Proofs[i].snapshot1; | 375 const uint64_t snapshot1 = kSHA256Proofs[i].snapshot1; |
389 const uint64_t snapshot2 = kSHA256Proofs[i].snapshot2; | 376 const uint64_t snapshot2 = kSHA256Proofs[i].snapshot2; |
390 const TestVector& old_root = kSHA256Roots[snapshot1 - 1]; | 377 const char* const old_root = kSHA256Roots[snapshot1 - 1]; |
391 const TestVector& new_root = kSHA256Roots[snapshot2 - 1]; | 378 const char* const new_root = kSHA256Roots[snapshot2 - 1]; |
392 VerifierConsistencyCheck( | 379 VerifierConsistencyCheck(snapshot1, snapshot2, HexToBytes(old_root), |
393 snapshot1, snapshot2, HexToBytes(old_root.str, old_root.length_bytes), | 380 HexToBytes(new_root), proof); |
394 HexToBytes(new_root.str, new_root.length_bytes), proof); | |
395 } | 381 } |
396 } | 382 } |
397 | 383 |
398 const char kLeafPrefix[] = {'\x00'}; | 384 const char kLeafPrefix[] = {'\x00'}; |
399 | 385 |
400 // Reference implementation of RFC6962. | 386 // Reference implementation of RFC6962. |
401 // This allows generation of arbitrary-sized Merkle trees and consistency | 387 // This allows generation of arbitrary-sized Merkle trees and consistency |
402 // proofs between them for testing the consistency proof validation | 388 // proofs between them for testing the consistency proof validation |
403 // code. | 389 // code. |
404 class TreeHasher { | 390 class TreeHasher { |
405 public: | 391 public: |
406 static std::string HashEmpty() { | |
407 return HexToBytes(kSHA256EmptyTreeHash.str, | |
408 kSHA256EmptyTreeHash.length_bytes); | |
409 } | |
410 | |
411 static std::string HashLeaf(const std::string& leaf) { | 392 static std::string HashLeaf(const std::string& leaf) { |
412 SHA256HashValue sha256; | 393 SHA256HashValue sha256; |
413 memset(sha256.data, 0, sizeof(sha256.data)); | 394 memset(sha256.data, 0, sizeof(sha256.data)); |
414 | 395 |
415 std::unique_ptr<crypto::SecureHash> hash( | 396 std::unique_ptr<crypto::SecureHash> hash( |
416 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); | 397 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); |
417 hash->Update(kLeafPrefix, 1); | 398 hash->Update(kLeafPrefix, 1); |
418 hash->Update(leaf.data(), leaf.size()); | 399 hash->Update(leaf.data(), leaf.size()); |
419 hash->Finish(sha256.data, sizeof(sha256.data)); | 400 hash->Finish(sha256.data, sizeof(sha256.data)); |
420 | 401 |
421 return std::string(reinterpret_cast<const char*>(sha256.data), | 402 return std::string(reinterpret_cast<const char*>(sha256.data), |
422 sizeof(sha256.data)); | 403 sizeof(sha256.data)); |
423 } | 404 } |
424 }; | 405 }; |
425 | 406 |
426 // Reference implementation of Merkle hash, for cross-checking. | 407 // Reference implementation of Merkle hash, for cross-checking. |
427 // Recursively calculates the hash of the root given the leaf data | 408 // Recursively calculates the hash of the root given the leaf data |
428 // specified in |inputs|. | 409 // specified in |inputs|. |
429 std::string ReferenceMerkleTreeHash(std::string* inputs, uint64_t input_size) { | 410 std::string ReferenceMerkleTreeHash(std::string* inputs, uint64_t input_size) { |
430 if (!input_size) | 411 if (!input_size) |
431 return TreeHasher::HashEmpty(); | 412 return GetEmptyTreeHash(); |
432 if (input_size == 1) | 413 if (input_size == 1) |
433 return TreeHasher::HashLeaf(inputs[0]); | 414 return TreeHasher::HashLeaf(inputs[0]); |
434 | 415 |
435 const uint64_t split = CalculateNearestPowerOfTwo(input_size); | 416 const uint64_t split = CalculateNearestPowerOfTwo(input_size); |
436 | 417 |
437 return ct::internal::HashNodes( | 418 return ct::internal::HashNodes( |
438 ReferenceMerkleTreeHash(&inputs[0], split), | 419 ReferenceMerkleTreeHash(&inputs[0], split), |
439 ReferenceMerkleTreeHash(&inputs[split], input_size - split)); | 420 ReferenceMerkleTreeHash(&inputs[split], input_size - split)); |
440 } | 421 } |
441 | 422 |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
514 | 495 |
515 // Test verification of consistency proofs between all tree sizes from 1 to 128. | 496 // Test verification of consistency proofs between all tree sizes from 1 to 128. |
516 INSTANTIATE_TEST_CASE_P(RangeOfTreeSizesAndSnapshots, | 497 INSTANTIATE_TEST_CASE_P(RangeOfTreeSizesAndSnapshots, |
517 CTLogVerifierTestUsingReferenceGenerator, | 498 CTLogVerifierTestUsingReferenceGenerator, |
518 testing::Range(UINT64_C(1), | 499 testing::Range(UINT64_C(1), |
519 (kReferenceTreeSize / 2) + 1)); | 500 (kReferenceTreeSize / 2) + 1)); |
520 | 501 |
521 } // namespace | 502 } // namespace |
522 | 503 |
523 } // namespace net | 504 } // namespace net |
OLD | NEW |