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"
22 // Structure for making JSON decoding easier. The string fields
23 // are base64-encoded so will require further decoding.
24 struct JsonSignedTreeHead
{
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";
40 if (result
->length() != kSthRootHashLength
) {
41 DVLOG(1) << "sha256_root_hash is expected to be 32 bytes, but is "
42 << result
->length() << " bytes.";
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";
57 base::StringPiece
sp(tree_head_signature
);
58 if (!DecodeDigitallySigned(&sp
, result
)) {
59 DVLOG(1) << "Failed decoding signature to DigitallySigned";
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: "
85 if (sth
.timestamp
< 0) {
86 DVLOG(1) << "Timestamp in Signed Tree Head JSON is negative: "
91 if (sth
.sha256_root_hash
.empty()) {
92 DVLOG(1) << "Missing SHA256 root hash from Signed Tree Head JSON.";
96 if (sth
.signature
.signature_data
.empty()) {
97 DVLOG(1) << "Missing signature from Signed Tree Head JSON.";
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.";
115 if (!IsJsonSTHStructurallyValid(parsed_sth
))
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(),