Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / cert / ct_log_response_parser.cc
blob0069fc708484a565eedf39f5f32d252801b43552
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/cert/ct_log_response_parser.h"
7 #include "base/base64.h"
8 #include "base/json/json_value_converter.h"
9 #include "base/logging.h"
10 #include "base/strings/string_piece.h"
11 #include "base/time/time.h"
12 #include "base/values.h"
13 #include "net/cert/ct_serialization.h"
14 #include "net/cert/signed_tree_head.h"
16 namespace net {
18 namespace ct {
20 namespace {
22 // Structure for making JSON decoding easier. The string fields
23 // are base64-encoded so will require further decoding.
24 struct JsonSignedTreeHead {
25 int tree_size;
26 double timestamp;
27 std::string sha256_root_hash;
28 DigitallySigned signature;
30 static void RegisterJSONConverter(
31 base::JSONValueConverter<JsonSignedTreeHead>* converted);
34 bool ConvertSHA256RootHash(const base::StringPiece& s, std::string* result) {
35 if (!base::Base64Decode(s, result)) {
36 DVLOG(1) << "Failed decoding sha256_root_hash";
37 return false;
40 if (result->length() != kSthRootHashLength) {
41 DVLOG(1) << "sha256_root_hash is expected to be 32 bytes, but is "
42 << result->length() << " bytes.";
43 return false;
46 return true;
49 bool ConvertTreeHeadSignature(const base::StringPiece& s,
50 DigitallySigned* result) {
51 std::string tree_head_signature;
52 if (!base::Base64Decode(s, &tree_head_signature)) {
53 DVLOG(1) << "Failed decoding tree_head_signature";
54 return false;
57 base::StringPiece sp(tree_head_signature);
58 if (!DecodeDigitallySigned(&sp, result)) {
59 DVLOG(1) << "Failed decoding signature to DigitallySigned";
60 return false;
62 return true;
65 void JsonSignedTreeHead::RegisterJSONConverter(
66 base::JSONValueConverter<JsonSignedTreeHead>* converter) {
67 converter->RegisterIntField("tree_size", &JsonSignedTreeHead::tree_size);
68 converter->RegisterDoubleField("timestamp", &JsonSignedTreeHead::timestamp);
69 converter->RegisterCustomField("sha256_root_hash",
70 &JsonSignedTreeHead::sha256_root_hash,
71 &ConvertSHA256RootHash);
72 converter->RegisterCustomField<DigitallySigned>(
73 "tree_head_signature",
74 &JsonSignedTreeHead::signature,
75 &ConvertTreeHeadSignature);
78 bool IsJsonSTHStructurallyValid(const JsonSignedTreeHead& sth) {
79 if (sth.tree_size < 0) {
80 DVLOG(1) << "Tree size in Signed Tree Head JSON is negative: "
81 << sth.tree_size;
82 return false;
85 if (sth.timestamp < 0) {
86 DVLOG(1) << "Timestamp in Signed Tree Head JSON is negative: "
87 << sth.timestamp;
88 return false;
91 if (sth.sha256_root_hash.empty()) {
92 DVLOG(1) << "Missing SHA256 root hash from Signed Tree Head JSON.";
93 return false;
96 if (sth.signature.signature_data.empty()) {
97 DVLOG(1) << "Missing signature from Signed Tree Head JSON.";
98 return false;
101 return true;
104 } // namespace
106 bool FillSignedTreeHead(const base::Value& json_signed_tree_head,
107 SignedTreeHead* signed_tree_head) {
108 JsonSignedTreeHead parsed_sth;
109 base::JSONValueConverter<JsonSignedTreeHead> converter;
110 if (!converter.Convert(json_signed_tree_head, &parsed_sth)) {
111 DVLOG(1) << "Invalid Signed Tree Head JSON.";
112 return false;
115 if (!IsJsonSTHStructurallyValid(parsed_sth))
116 return false;
118 signed_tree_head->version = SignedTreeHead::V1;
119 signed_tree_head->tree_size = parsed_sth.tree_size;
120 signed_tree_head->timestamp =
121 base::Time::UnixEpoch() + base::TimeDelta::FromMilliseconds(
122 static_cast<int64_t>(parsed_sth.timestamp));
123 signed_tree_head->signature = parsed_sth.signature;
124 memcpy(signed_tree_head->sha256_root_hash,
125 parsed_sth.sha256_root_hash.c_str(),
126 kSthRootHashLength);
127 return true;
130 } // namespace ct
132 } // namespace net