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"
9 #include "base/base64.h"
10 #include "base/json/json_reader.h"
11 #include "base/strings/stringprintf.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"
16 #include "testing/gtest/include/gtest/gtest.h"
23 scoped_ptr
<base::Value
> ParseJson(const std::string
& json
) {
24 base::JSONReader json_reader
;
25 return json_reader
.Read(json
).Pass();
29 std::string
CreateSignedTreeHeadJsonString(std::string sha256_root_hash
,
30 std::string tree_head_signature
) {
31 std::string sth_json
= "{\"tree_size\":2903698,\"timestamp\":1395761621447";
33 if (!sha256_root_hash
.empty()) {
34 sth_json
+= base::StringPrintf(",\"sha256_root_hash\":\"%s\"",
35 sha256_root_hash
.c_str());
37 if (!tree_head_signature
.empty()) {
38 sth_json
+= base::StringPrintf(",\"tree_head_signature\":\"%s\"",
39 tree_head_signature
.c_str());
46 const char kSHA256RootHash
[] = "/WHFMgXtI/umKKuACJIN0Bb73TcILm9WkeU6qszvoAo=";
48 const char kTreeHeadSignature
[] =
49 "BAMARzBFAiAB+IIYrkRsZDW0/6TzPgR+aJ26twCQ1JDTwq/"
50 "mpinCjAIhAKDXdXMtqbvQ42r9dBIwV5RM/KpEzNQdIhXHesd9HPv3";
52 TEST(CTLogResponseParserTest
, ParsesValidJsonSTH
) {
53 scoped_ptr
<base::Value
> sample_sth
= ParseJson(
54 CreateSignedTreeHeadJsonString(kSHA256RootHash
, kTreeHeadSignature
));
55 SignedTreeHead tree_head
;
56 EXPECT_TRUE(FillSignedTreeHead(*sample_sth
.get(), &tree_head
));
58 base::Time expected_timestamp
=
59 base::Time::UnixEpoch() +
60 base::TimeDelta::FromMilliseconds(1395761621447);
62 ASSERT_EQ(SignedTreeHead::V1
, tree_head
.version
);
63 ASSERT_EQ(expected_timestamp
, tree_head
.timestamp
);
64 ASSERT_EQ(2903698u, tree_head
.tree_size
);
66 // Copy the field from the SignedTreeHead because it's not null terminated
67 // there and ASSERT_STREQ expects null-terminated strings.
68 char actual_hash
[kSthRootHashLength
+ 1];
69 memcpy(actual_hash
, tree_head
.sha256_root_hash
, kSthRootHashLength
);
70 actual_hash
[kSthRootHashLength
] = '\0';
71 std::string expected_sha256_root_hash
;
72 base::Base64Decode(kSHA256RootHash
, &expected_sha256_root_hash
);
73 ASSERT_STREQ(expected_sha256_root_hash
.c_str(), actual_hash
);
75 std::string tree_head_signature
;
76 base::Base64Decode(kTreeHeadSignature
, &tree_head_signature
);
77 base::StringPiece
sp(tree_head_signature
);
78 DigitallySigned expected_signature
;
79 ASSERT_TRUE(DecodeDigitallySigned(&sp
, &expected_signature
));
81 ASSERT_EQ(tree_head
.signature
.hash_algorithm
,
82 expected_signature
.hash_algorithm
);
83 ASSERT_EQ(tree_head
.signature
.signature_algorithm
,
84 expected_signature
.signature_algorithm
);
85 ASSERT_EQ(tree_head
.signature
.signature_data
,
86 expected_signature
.signature_data
);
89 TEST(CTLogResponseParserTest
, FailsToParseMissingFields
) {
90 scoped_ptr
<base::Value
> missing_signature_sth
=
91 ParseJson(CreateSignedTreeHeadJsonString(kSHA256RootHash
, ""));
93 SignedTreeHead tree_head
;
94 ASSERT_FALSE(FillSignedTreeHead(*missing_signature_sth
.get(), &tree_head
));
96 scoped_ptr
<base::Value
> missing_root_hash_sth
=
97 ParseJson(CreateSignedTreeHeadJsonString("", kTreeHeadSignature
));
98 ASSERT_FALSE(FillSignedTreeHead(*missing_root_hash_sth
.get(), &tree_head
));
101 TEST(CTLogResponseParserTest
, FailsToParseIncorrectLengthRootHash
) {
102 SignedTreeHead tree_head
;
104 scoped_ptr
<base::Value
> too_long_hash
=
105 ParseJson(CreateSignedTreeHeadJsonString(
106 kSHA256RootHash
, "/WHFMgXtI/umKKuACJIN0Bb73TcILm9WkeU6qszvoArK\n"));
107 ASSERT_FALSE(FillSignedTreeHead(*too_long_hash
.get(), &tree_head
));
109 scoped_ptr
<base::Value
> too_short_hash
=
110 ParseJson(CreateSignedTreeHeadJsonString(
111 kSHA256RootHash
, "/WHFMgXtI/umKKuACJIN0Bb73TcILm9WkeU6qszvoA==\n"));
112 ASSERT_FALSE(FillSignedTreeHead(*too_short_hash
.get(), &tree_head
));