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 #include <vector> |
| 12 | 12 |
| 13 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
| 14 #include "base/time/time.h" | 14 #include "base/time/time.h" |
| 15 #include "crypto/secure_hash.h" | 15 #include "crypto/secure_hash.h" |
| 16 #include "crypto/sha2.h" | |
|
Ryan Sleevi
2016/08/25 20:32:45
Unnecessary
| |
| 16 #include "net/base/hash_value.h" | 17 #include "net/base/hash_value.h" |
| 17 #include "net/cert/ct_log_verifier_util.h" | 18 #include "net/cert/ct_log_verifier_util.h" |
| 18 #include "net/cert/merkle_consistency_proof.h" | 19 #include "net/cert/merkle_consistency_proof.h" |
| 19 #include "net/cert/signed_certificate_timestamp.h" | 20 #include "net/cert/signed_certificate_timestamp.h" |
| 20 #include "net/cert/signed_tree_head.h" | 21 #include "net/cert/signed_tree_head.h" |
| 21 #include "net/test/ct_test_util.h" | 22 #include "net/test/ct_test_util.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 23 | 24 |
| 24 namespace net { | 25 namespace net { |
| 25 | 26 |
| 26 namespace { | 27 namespace { |
| 27 | 28 |
| 28 // Calculate the power of two nearest to, but less than, |n|. | 29 // Calculate the power of two nearest to, but less than, |n|. |
| 29 // |n| must be at least 2. | 30 // |n| must be at least 2. |
| 30 uint64_t CalculateNearestPowerOfTwo(uint64_t n) { | 31 uint64_t CalculateNearestPowerOfTwo(uint64_t n) { |
| 31 DCHECK_GT(n, 1u); | 32 DCHECK_GT(n, 1u); |
| 32 | 33 |
| 33 uint64_t ret = UINT64_C(1) << 63; | 34 uint64_t ret = UINT64_C(1) << 63; |
| 34 while (ret >= n) | 35 while (ret >= n) |
| 35 ret >>= 1; | 36 ret >>= 1; |
| 36 | 37 |
| 37 return ret; | 38 return ret; |
| 38 } | 39 } |
| 39 | 40 |
| 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 | 41 // A single consistency proof. Contains the old and new tree sizes |
| 50 // (snapshot1 and snapshot2), the length of the proof (proof_length) and | 42 // (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). | 43 // at most 3 proof nodes (all test proofs will be for a tree of size 8). |
| 52 struct ProofTestVector { | 44 struct ProofTestVector { |
| 53 uint64_t snapshot1; | 45 uint64_t snapshot1; |
| 54 uint64_t snapshot2; | 46 uint64_t snapshot2; |
| 55 size_t proof_length; | 47 size_t proof_length; |
| 56 TestVector proof[3]; | 48 const char* const proof[3]; |
| 57 }; | 49 }; |
| 58 | 50 |
| 59 // All test data replicated from | 51 // All test data replicated from |
| 60 // https://github.com/google/certificate-transparency/blob/c41b090ecc14ddd6b3531 dc7e5ce36b21e253fdd/cpp/merkletree/merkle_tree_test.cc | 52 // https://github.com/google/certificate-transparency/blob/c41b090ecc14ddd6b3531 dc7e5ce36b21e253fdd/cpp/merkletree/merkle_tree_test.cc |
| 61 // A hash of the empty string. | 53 // A hash of the empty string. |
| 62 const TestVector kSHA256EmptyTreeHash = { | 54 const char* const kSHA256EmptyTreeHash = |
|
Ryan Sleevi
2016/08/25 20:32:45
const char kSHA256EmptyTreeHash[32] =
{ 0xe3, 0x
| |
| 63 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", 32}; | 55 "\xe3\xb0\xc4\x42\x98\xfc\x1c\x14\x9a\xfb\xf4\xc8\x99\x6f\xb9\x24\x27\xae" |
| 56 "\x41\xe4\x64\x9b\x93\x4c\xa4\x95\x99\x1b\x78\x52\xb8\x55"; | |
| 64 | 57 |
| 65 // Node hashes for a sample tree of size 8 (each element in this array is | 58 // 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). | 59 // a node hash, not leaf data; order represents order of the nodes in the tree). |
| 67 const TestVector kSHA256Roots[8] = { | 60 const char* const kSHA256Roots[8] = { |
| 68 {"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", 32}, | 61 "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", |
| 69 {"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", 32}, | 62 "fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", |
| 70 {"aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", 32}, | 63 "aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", |
| 71 {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", 32}, | 64 "d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", |
| 72 {"4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4", 32}, | 65 "4e3bbb1f7b478dcfe71fb631631519a3bca12c9aefca1612bfce4c13a86264d4", |
| 73 {"76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef", 32}, | 66 "76e67dadbcdf1e10e1b74ddc608abd2f98dfb16fbce75277b5232a127f2087ef", |
| 74 {"ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", 32}, | 67 "ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", |
| 75 {"5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328", 32}}; | 68 "5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328"}; |
| 76 | 69 |
| 77 // A collection of consistency proofs between various sub-trees of the tree | 70 // A collection of consistency proofs between various sub-trees of the tree |
| 78 // defined by |kSHA256Roots|. | 71 // defined by |kSHA256Roots|. |
| 79 const ProofTestVector kSHA256Proofs[4] = { | 72 const ProofTestVector kSHA256Proofs[4] = { |
| 80 // Empty consistency proof between trees of the same size (1). | 73 // Empty consistency proof between trees of the same size (1). |
| 81 {1, 1, 0, {{"", 0}, {"", 0}, {"", 0}}}, | 74 {1, 1, 0, {"", "", ""}}, |
| 82 // Consistency proof between tree of size 1 and tree of size 8, with 3 | 75 // Consistency proof between tree of size 1 and tree of size 8, with 3 |
| 83 // nodes in the proof. | 76 // nodes in the proof. |
| 84 {1, | 77 {1, |
| 85 8, | 78 8, |
| 86 3, | 79 3, |
| 87 {{"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", 32}, | 80 {"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", |
| 88 {"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, | 81 "5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", |
| 89 {"6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4", | 82 "6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4"}}, |
| 90 32}}}, | |
| 91 // Consistency proof between tree of size 6 and tree of size 8, with 3 | 83 // Consistency proof between tree of size 6 and tree of size 8, with 3 |
| 92 // nodes in the proof. | 84 // nodes in the proof. |
| 93 {6, | 85 {6, |
| 94 8, | 86 8, |
| 95 3, | 87 3, |
| 96 {{"0ebc5d3437fbe2db158b9f126a1d118e308181031d0a949f8dededebc558ef6a", 32}, | 88 {"0ebc5d3437fbe2db158b9f126a1d118e308181031d0a949f8dededebc558ef6a", |
| 97 {"ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0", 32}, | 89 "ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0", |
| 98 {"d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7", | 90 "d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7"}}, |
| 99 32}}}, | |
| 100 // Consistency proof between tree of size 2 and tree of size 5, with 2 | 91 // Consistency proof between tree of size 2 and tree of size 5, with 2 |
| 101 // nodes in the proof. | 92 // nodes in the proof. |
| 102 {2, | 93 {2, |
| 103 5, | 94 5, |
| 104 2, | 95 2, |
| 105 {{"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", 32}, | 96 {"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", |
| 106 {"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", 32}, | 97 "bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", ""}}}; |
| 107 {"", 0}}}}; | |
| 108 | 98 |
| 109 // Decodes a hexadecimal string into the binary data it represents. | 99 // Decodes a hexadecimal string into the binary data it represents. |
| 110 std::string HexToBytes(const char* hex_data, size_t hex_data_length) { | 100 std::string HexToBytes(const std::string& hex_data) { |
| 111 std::vector<uint8_t> output; | 101 std::vector<uint8_t> output; |
| 112 std::string result; | 102 std::string result; |
| 113 std::string hex_data_input(hex_data, hex_data_length); | |
| 114 if (base::HexStringToBytes(hex_data, &output)) | 103 if (base::HexStringToBytes(hex_data, &output)) |
| 115 result.assign(reinterpret_cast<const char*>(&output[0]), output.size()); | 104 result.assign(output.begin(), output.end()); |
| 116 return result; | 105 return result; |
| 117 } | 106 } |
| 118 | 107 |
| 119 std::string GetEmptyTreeHash() { | 108 std::string GetEmptyTreeHash() { |
| 120 return HexToBytes(kSHA256EmptyTreeHash.str, | 109 return std::string(kSHA256EmptyTreeHash, crypto::kSHA256Length); |
|
Ryan Sleevi
2016/08/25 20:32:45
return std::string(std::begin(kSHA256EmptyTreeHash
| |
| 121 kSHA256EmptyTreeHash.length_bytes); | |
| 122 } | 110 } |
| 123 | 111 |
| 124 // Creates a ct::MerkleConsistencyProof and returns the result of | 112 // Creates a ct::MerkleConsistencyProof and returns the result of |
| 125 // calling log->VerifyConsistencyProof with that proof and snapshots. | 113 // calling log->VerifyConsistencyProof with that proof and snapshots. |
| 126 bool VerifyConsistencyProof(scoped_refptr<const CTLogVerifier> log, | 114 bool VerifyConsistencyProof(scoped_refptr<const CTLogVerifier> log, |
| 127 uint64_t old_tree_size, | 115 uint64_t old_tree_size, |
| 128 const std::string& old_tree_root, | 116 const std::string& old_tree_root, |
| 129 uint64_t new_tree_size, | 117 uint64_t new_tree_size, |
| 130 const std::string& new_tree_root, | 118 const std::string& new_tree_root, |
| 131 const std::vector<std::string>& proof) { | 119 const std::vector<std::string>& proof) { |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 } | 363 } |
| 376 | 364 |
| 377 TEST_F(CTLogVerifierTest, VerifiesValidConsistencyProofs) { | 365 TEST_F(CTLogVerifierTest, VerifiesValidConsistencyProofs) { |
| 378 std::vector<std::string> proof; | 366 std::vector<std::string> proof; |
| 379 std::string root1, root2; | 367 std::string root1, root2; |
| 380 | 368 |
| 381 // Known good proofs. | 369 // Known good proofs. |
| 382 for (size_t i = 0; i < arraysize(kSHA256Proofs); ++i) { | 370 for (size_t i = 0; i < arraysize(kSHA256Proofs); ++i) { |
| 383 proof.clear(); | 371 proof.clear(); |
| 384 for (size_t j = 0; j < kSHA256Proofs[i].proof_length; ++j) { | 372 for (size_t j = 0; j < kSHA256Proofs[i].proof_length; ++j) { |
| 385 const TestVector& v = kSHA256Proofs[i].proof[j]; | 373 const char* const v = kSHA256Proofs[i].proof[j]; |
| 386 proof.push_back(HexToBytes(v.str, v.length_bytes)); | 374 proof.push_back(HexToBytes(v)); |
| 387 } | 375 } |
| 388 const uint64_t snapshot1 = kSHA256Proofs[i].snapshot1; | 376 const uint64_t snapshot1 = kSHA256Proofs[i].snapshot1; |
| 389 const uint64_t snapshot2 = kSHA256Proofs[i].snapshot2; | 377 const uint64_t snapshot2 = kSHA256Proofs[i].snapshot2; |
| 390 const TestVector& old_root = kSHA256Roots[snapshot1 - 1]; | 378 const char* const old_root = kSHA256Roots[snapshot1 - 1]; |
| 391 const TestVector& new_root = kSHA256Roots[snapshot2 - 1]; | 379 const char* const new_root = kSHA256Roots[snapshot2 - 1]; |
| 392 VerifierConsistencyCheck( | 380 VerifierConsistencyCheck(snapshot1, snapshot2, HexToBytes(old_root), |
| 393 snapshot1, snapshot2, HexToBytes(old_root.str, old_root.length_bytes), | 381 HexToBytes(new_root), proof); |
| 394 HexToBytes(new_root.str, new_root.length_bytes), proof); | |
| 395 } | 382 } |
| 396 } | 383 } |
| 397 | 384 |
| 398 const char kLeafPrefix[] = {'\x00'}; | 385 const char kLeafPrefix[] = {'\x00'}; |
| 399 | 386 |
| 400 // Reference implementation of RFC6962. | 387 // Reference implementation of RFC6962. |
| 401 // This allows generation of arbitrary-sized Merkle trees and consistency | 388 // This allows generation of arbitrary-sized Merkle trees and consistency |
| 402 // proofs between them for testing the consistency proof validation | 389 // proofs between them for testing the consistency proof validation |
| 403 // code. | 390 // code. |
| 404 class TreeHasher { | 391 class TreeHasher { |
| 405 public: | 392 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) { | 393 static std::string HashLeaf(const std::string& leaf) { |
| 412 SHA256HashValue sha256; | 394 SHA256HashValue sha256; |
| 413 memset(sha256.data, 0, sizeof(sha256.data)); | 395 memset(sha256.data, 0, sizeof(sha256.data)); |
| 414 | 396 |
| 415 std::unique_ptr<crypto::SecureHash> hash( | 397 std::unique_ptr<crypto::SecureHash> hash( |
| 416 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); | 398 crypto::SecureHash::Create(crypto::SecureHash::SHA256)); |
| 417 hash->Update(kLeafPrefix, 1); | 399 hash->Update(kLeafPrefix, 1); |
| 418 hash->Update(leaf.data(), leaf.size()); | 400 hash->Update(leaf.data(), leaf.size()); |
| 419 hash->Finish(sha256.data, sizeof(sha256.data)); | 401 hash->Finish(sha256.data, sizeof(sha256.data)); |
| 420 | 402 |
| 421 return std::string(reinterpret_cast<const char*>(sha256.data), | 403 return std::string(reinterpret_cast<const char*>(sha256.data), |
| 422 sizeof(sha256.data)); | 404 sizeof(sha256.data)); |
| 423 } | 405 } |
| 424 }; | 406 }; |
| 425 | 407 |
| 426 // Reference implementation of Merkle hash, for cross-checking. | 408 // Reference implementation of Merkle hash, for cross-checking. |
| 427 // Recursively calculates the hash of the root given the leaf data | 409 // Recursively calculates the hash of the root given the leaf data |
| 428 // specified in |inputs|. | 410 // specified in |inputs|. |
| 429 std::string ReferenceMerkleTreeHash(std::string* inputs, uint64_t input_size) { | 411 std::string ReferenceMerkleTreeHash(std::string* inputs, uint64_t input_size) { |
| 430 if (!input_size) | 412 if (!input_size) |
| 431 return TreeHasher::HashEmpty(); | 413 return GetEmptyTreeHash(); |
| 432 if (input_size == 1) | 414 if (input_size == 1) |
| 433 return TreeHasher::HashLeaf(inputs[0]); | 415 return TreeHasher::HashLeaf(inputs[0]); |
| 434 | 416 |
| 435 const uint64_t split = CalculateNearestPowerOfTwo(input_size); | 417 const uint64_t split = CalculateNearestPowerOfTwo(input_size); |
| 436 | 418 |
| 437 return ct::internal::HashNodes( | 419 return ct::internal::HashNodes( |
| 438 ReferenceMerkleTreeHash(&inputs[0], split), | 420 ReferenceMerkleTreeHash(&inputs[0], split), |
| 439 ReferenceMerkleTreeHash(&inputs[split], input_size - split)); | 421 ReferenceMerkleTreeHash(&inputs[split], input_size - split)); |
| 440 } | 422 } |
| 441 | 423 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 514 | 496 |
| 515 // Test verification of consistency proofs between all tree sizes from 1 to 128. | 497 // Test verification of consistency proofs between all tree sizes from 1 to 128. |
| 516 INSTANTIATE_TEST_CASE_P(RangeOfTreeSizesAndSnapshots, | 498 INSTANTIATE_TEST_CASE_P(RangeOfTreeSizesAndSnapshots, |
| 517 CTLogVerifierTestUsingReferenceGenerator, | 499 CTLogVerifierTestUsingReferenceGenerator, |
| 518 testing::Range(UINT64_C(1), | 500 testing::Range(UINT64_C(1), |
| 519 (kReferenceTreeSize / 2) + 1)); | 501 (kReferenceTreeSize / 2) + 1)); |
| 520 | 502 |
| 521 } // namespace | 503 } // namespace |
| 522 | 504 |
| 523 } // namespace net | 505 } // namespace net |
| OLD | NEW |