diff options
-rw-r--r-- | net/cert/ct_log_response_parser.cc | 45 | ||||
-rw-r--r-- | net/cert/ct_log_response_parser.h | 7 | ||||
-rw-r--r-- | net/cert/ct_log_response_parser_unittest.cc | 41 | ||||
-rw-r--r-- | net/test/ct_test_util.cc | 17 | ||||
-rw-r--r-- | net/test/ct_test_util.h | 5 |
5 files changed, 115 insertions, 0 deletions
diff --git a/net/cert/ct_log_response_parser.cc b/net/cert/ct_log_response_parser.cc index 0069fc7..0c006cc 100644 --- a/net/cert/ct_log_response_parser.cc +++ b/net/cert/ct_log_response_parser.cc @@ -7,6 +7,7 @@ #include "base/base64.h" #include "base/json/json_value_converter.h" #include "base/logging.h" +#include "base/memory/scoped_vector.h" #include "base/strings/string_piece.h" #include "base/time/time.h" #include "base/values.h" @@ -101,6 +102,33 @@ bool IsJsonSTHStructurallyValid(const JsonSignedTreeHead& sth) { return true; } +// Structure for making JSON decoding easier. The string fields +// are base64-encoded so will require further decoding. +struct JsonConsistencyProof { + ScopedVector<std::string> proof_nodes; + + static void RegisterJSONConverter( + base::JSONValueConverter<JsonConsistencyProof>* converter); +}; + +bool ConvertIndividualProofNode(const base::Value* value, std::string* result) { + std::string b64_encoded_node; + if (!value->GetAsString(&b64_encoded_node)) + return false; + + if (!ConvertSHA256RootHash(b64_encoded_node, result)) + return false; + + return true; +} + +void JsonConsistencyProof::RegisterJSONConverter( + base::JSONValueConverter<JsonConsistencyProof>* converter) { + converter->RegisterRepeatedCustomValue<std::string>( + "consistency", &JsonConsistencyProof::proof_nodes, + &ConvertIndividualProofNode); +} + } // namespace bool FillSignedTreeHead(const base::Value& json_signed_tree_head, @@ -127,6 +155,23 @@ bool FillSignedTreeHead(const base::Value& json_signed_tree_head, return true; } +bool FillConsistencyProof(const base::Value& json_consistency_proof, + std::vector<std::string>* consistency_proof) { + JsonConsistencyProof parsed_proof; + base::JSONValueConverter<JsonConsistencyProof> converter; + if (!converter.Convert(json_consistency_proof, &parsed_proof)) { + DVLOG(1) << "Invalid consistency proof."; + return false; + } + + consistency_proof->reserve(parsed_proof.proof_nodes.size()); + for (std::string* proof_node : parsed_proof.proof_nodes) { + consistency_proof->push_back(*proof_node); + } + + return true; +} + } // namespace ct } // namespace net diff --git a/net/cert/ct_log_response_parser.h b/net/cert/ct_log_response_parser.h index b7a012b..403f8bf 100644 --- a/net/cert/ct_log_response_parser.h +++ b/net/cert/ct_log_response_parser.h @@ -5,6 +5,9 @@ #ifndef NET_CERT_CT_LOG_RESPONSE_PARSER_H_ #define NET_CERT_CT_LOG_RESPONSE_PARSER_H_ +#include <string> +#include <vector> + #include "base/strings/string_piece.h" #include "net/base/net_export.h" @@ -24,6 +27,10 @@ struct SignedTreeHead; NET_EXPORT bool FillSignedTreeHead(const base::Value& json_signed_tree_head, SignedTreeHead* signed_tree_head); +NET_EXPORT bool FillConsistencyProof( + const base::Value& json_signed_tree_head, + std::vector<std::string>* consistency_proof); + } // namespace ct } // namespace net diff --git a/net/cert/ct_log_response_parser_unittest.cc b/net/cert/ct_log_response_parser_unittest.cc index 9f02699..d2c192e 100644 --- a/net/cert/ct_log_response_parser_unittest.cc +++ b/net/cert/ct_log_response_parser_unittest.cc @@ -95,6 +95,47 @@ TEST(CTLogResponseParserTest, FailsToParseIncorrectLengthRootHash) { ASSERT_FALSE(FillSignedTreeHead(*too_short_hash_json.get(), &tree_head)); } +TEST(CTLogResponseParserTest, ParsesConsistencyProofSuccessfully) { + std::string first(32, 'a'); + std::string second(32, 'b'); + std::string third(32, 'c'); + + std::vector<std::string> raw_nodes; + raw_nodes.push_back(first); + raw_nodes.push_back(second); + raw_nodes.push_back(third); + scoped_ptr<base::Value> sample_consistency_proof = + ParseJson(CreateConsistencyProofJsonString(raw_nodes)); + + std::vector<std::string> output; + + ASSERT_TRUE(FillConsistencyProof(*sample_consistency_proof.get(), &output)); + + EXPECT_EQ(output[0], first); + EXPECT_EQ(output[1], second); + EXPECT_EQ(output[2], third); +} + +TEST(CTLogResponseParserTest, FailsOnInvalidProofJson) { + std::vector<std::string> output; + + scoped_ptr<base::Value> badly_encoded = + ParseJson(std::string("{\"consistency\": [\"notbase64\"]}")); + EXPECT_FALSE(FillConsistencyProof(*badly_encoded.get(), &output)); + + scoped_ptr<base::Value> not_a_string = + ParseJson(std::string("{\"consistency\": [42, 16]}")); + EXPECT_FALSE(FillConsistencyProof(*badly_encoded.get(), &output)); +} + +TEST(CTLogResponseParserTest, ParsesProofJsonWithExtraFields) { + std::vector<std::string> output; + + scoped_ptr<base::Value> badly_encoded = + ParseJson(std::string("{\"consistency\": [], \"somethingelse\": 3}")); + EXPECT_TRUE(FillConsistencyProof(*badly_encoded.get(), &output)); +} + } // namespace ct } // namespace net diff --git a/net/test/ct_test_util.cc b/net/test/ct_test_util.cc index 65a8122..3bd30ff 100644 --- a/net/test/ct_test_util.cc +++ b/net/test/ct_test_util.cc @@ -312,6 +312,23 @@ std::string CreateSignedTreeHeadJsonString(size_t tree_size, return sth_json; } +std::string CreateConsistencyProofJsonString( + const std::vector<std::string>& raw_nodes) { + std::string consistency_proof_json = std::string("{\"consistency\":["); + + for (auto it = raw_nodes.begin(); it != raw_nodes.end(); ++it) { + std::string proof_node_b64; + base::Base64Encode(*it, &proof_node_b64); + consistency_proof_json += + base::StringPrintf("\"%s\"", proof_node_b64.c_str()); + if (it + 1 != raw_nodes.end()) + consistency_proof_json += std::string(","); + } + consistency_proof_json += std::string("]}"); + + return consistency_proof_json; +} + } // namespace ct } // namespace net diff --git a/net/test/ct_test_util.h b/net/test/ct_test_util.h index 5701a28..5bb2d7a 100644 --- a/net/test/ct_test_util.h +++ b/net/test/ct_test_util.h @@ -6,6 +6,7 @@ #define NET_CERT_CT_TEST_UTIL_H_ #include <string> +#include <vector> #include "base/memory/ref_counted.h" @@ -86,6 +87,10 @@ std::string CreateSignedTreeHeadJsonString(size_t tree_size, std::string sha256_root_hash, std::string tree_head_signature); +// Assembles, and returns, a sample consistency proof in JSON format using +// the provided raw nodes (i.e. the raw nodes will be base64-encoded). +std::string CreateConsistencyProofJsonString( + const std::vector<std::string>& raw_nodes); } // namespace ct } // namespace net |