summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/cert/ct_log_response_parser.cc45
-rw-r--r--net/cert/ct_log_response_parser.h7
-rw-r--r--net/cert/ct_log_response_parser_unittest.cc41
-rw-r--r--net/test/ct_test_util.cc17
-rw-r--r--net/test/ct_test_util.h5
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