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_reader.h"
9 #include "base/json/json_value_converter.h"
10 #include "base/logging.h"
11 #include "base/strings/string_piece.h"
12 #include "base/time/time.h"
13 #include "base/values.h"
14 #include "net/cert/ct_serialization.h"
15 #include "net/cert/signed_tree_head.h"
23 // Structure for making JSON decoding easier. The string fields
24 // are base64-encoded so will require further decoding.
25 struct JsonSignedTreeHead
{
28 std::string sha256_root_hash
;
29 DigitallySigned signature
;
31 static void RegisterJSONConverter(
32 base::JSONValueConverter
<JsonSignedTreeHead
>* converted
);
35 bool ConvertSHA256RootHash(const base::StringPiece
& s
, std::string
* result
) {
36 if (!base::Base64Decode(s
, result
)) {
37 DVLOG(1) << "Failed decoding sha256_root_hash";
41 if (result
->length() != kSthRootHashLength
) {
42 DVLOG(1) << "sha256_root_hash is expected to be 32 bytes, but is "
43 << result
->length() << " bytes.";
50 bool ConvertTreeHeadSignature(const base::StringPiece
& s
,
51 DigitallySigned
* result
) {
52 std::string tree_head_signature
;
53 if (!base::Base64Decode(s
, &tree_head_signature
)) {
54 DVLOG(1) << "Failed decoding tree_head_signature";
58 base::StringPiece
sp(tree_head_signature
);
59 if (!DecodeDigitallySigned(&sp
, result
)) {
60 DVLOG(1) << "Failed decoding signature to DigitallySigned";
66 void JsonSignedTreeHead::RegisterJSONConverter(
67 base::JSONValueConverter
<JsonSignedTreeHead
>* converter
) {
68 converter
->RegisterIntField("tree_size", &JsonSignedTreeHead::tree_size
);
69 converter
->RegisterDoubleField("timestamp", &JsonSignedTreeHead::timestamp
);
70 converter
->RegisterCustomField("sha256_root_hash",
71 &JsonSignedTreeHead::sha256_root_hash
,
72 &ConvertSHA256RootHash
);
73 converter
->RegisterCustomField
<DigitallySigned
>(
74 "tree_head_signature",
75 &JsonSignedTreeHead::signature
,
76 &ConvertTreeHeadSignature
);
79 bool IsJsonSTHStructurallyValid(const JsonSignedTreeHead
& sth
) {
80 if (sth
.tree_size
< 0) {
81 DVLOG(1) << "Tree size in Signed Tree Head JSON is negative: "
86 if (sth
.timestamp
< 0) {
87 DVLOG(1) << "Timestamp in Signed Tree Head JSON is negative: "
92 if (sth
.sha256_root_hash
.empty()) {
93 DVLOG(1) << "Missing SHA256 root hash from Signed Tree Head JSON.";
97 if (sth
.signature
.signature_data
.empty()) {
98 DVLOG(1) << "Missing SHA256 root hash from Signed Tree Head JSON.";
107 bool FillSignedTreeHead(const base::StringPiece
& json_signed_tree_head
,
108 SignedTreeHead
* signed_tree_head
) {
109 base::JSONReader json_reader
;
110 scoped_ptr
<base::Value
> json(json_reader
.Read(json_signed_tree_head
));
111 if (json
.get() == NULL
) {
112 DVLOG(1) << "Empty Signed Tree Head JSON.";
116 JsonSignedTreeHead parsed_sth
;
117 base::JSONValueConverter
<JsonSignedTreeHead
> converter
;
118 if (!converter
.Convert(*json
.get(), &parsed_sth
)) {
119 DVLOG(1) << "Invalid Signed Tree Head JSON.";
123 if (!IsJsonSTHStructurallyValid(parsed_sth
))
126 signed_tree_head
->version
= SignedTreeHead::V1
;
127 signed_tree_head
->tree_size
= parsed_sth
.tree_size
;
128 signed_tree_head
->timestamp
=
129 base::Time::UnixEpoch() +
130 base::TimeDelta::FromMilliseconds(
131 static_cast<int64
>(parsed_sth
.timestamp
));
132 signed_tree_head
->signature
= parsed_sth
.signature
;
133 memcpy(signed_tree_head
->sha256_root_hash
,
134 parsed_sth
.sha256_root_hash
.c_str(),