Home | History | Annotate | Download | only in cert
      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.
      4 
      5 #include "net/cert/ct_log_response_parser.h"
      6 
      7 #include <string>
      8 
      9 #include "base/base64.h"
     10 #include "base/strings/stringprintf.h"
     11 #include "base/time/time.h"
     12 #include "net/cert/ct_serialization.h"
     13 #include "net/cert/signed_tree_head.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace net {
     17 
     18 namespace ct {
     19 
     20 std::string CreateSignedTreeHeadJsonString(std::string sha256_root_hash,
     21                                            std::string tree_head_signature) {
     22   std::string sth_json = "{\"tree_size\":2903698,\"timestamp\":1395761621447";
     23 
     24   if (!sha256_root_hash.empty()) {
     25     sth_json += base::StringPrintf(",\"sha256_root_hash\":\"%s\"",
     26                                    sha256_root_hash.c_str());
     27   }
     28   if (!tree_head_signature.empty()) {
     29     sth_json += base::StringPrintf(",\"tree_head_signature\":\"%s\"",
     30                                    tree_head_signature.c_str());
     31   }
     32 
     33   sth_json += "}";
     34   return sth_json;
     35 }
     36 
     37 const char kSHA256RootHash[] = "/WHFMgXtI/umKKuACJIN0Bb73TcILm9WkeU6qszvoAo=";
     38 
     39 const char kTreeHeadSignature[] =
     40     "BAMARzBFAiAB+IIYrkRsZDW0/6TzPgR+aJ26twCQ1JDTwq/"
     41     "mpinCjAIhAKDXdXMtqbvQ42r9dBIwV5RM/KpEzNQdIhXHesd9HPv3";
     42 
     43 TEST(CTLogResponseParserTest, ParsesValidJsonSTH) {
     44   std::string sample_sth =
     45       CreateSignedTreeHeadJsonString(kSHA256RootHash, kTreeHeadSignature);
     46   SignedTreeHead tree_head;
     47   EXPECT_TRUE(FillSignedTreeHead(sample_sth, &tree_head));
     48 
     49   base::Time expected_timestamp =
     50       base::Time::UnixEpoch() +
     51       base::TimeDelta::FromMilliseconds(1395761621447);
     52 
     53   ASSERT_EQ(SignedTreeHead::V1, tree_head.version);
     54   ASSERT_EQ(expected_timestamp, tree_head.timestamp);
     55   ASSERT_EQ(2903698u, tree_head.tree_size);
     56 
     57   // Copy the field from the SignedTreeHead because it's not null terminated
     58   // there and ASSERT_STREQ expects null-terminated strings.
     59   char actual_hash[kSthRootHashLength + 1];
     60   memcpy(actual_hash, tree_head.sha256_root_hash, kSthRootHashLength);
     61   actual_hash[kSthRootHashLength] = '\0';
     62   std::string expected_sha256_root_hash;
     63   base::Base64Decode(kSHA256RootHash, &expected_sha256_root_hash);
     64   ASSERT_STREQ(expected_sha256_root_hash.c_str(), actual_hash);
     65 
     66   std::string tree_head_signature;
     67   base::Base64Decode(kTreeHeadSignature, &tree_head_signature);
     68   base::StringPiece sp(tree_head_signature);
     69   DigitallySigned expected_signature;
     70   ASSERT_TRUE(DecodeDigitallySigned(&sp, &expected_signature));
     71 
     72   ASSERT_EQ(tree_head.signature.hash_algorithm,
     73             expected_signature.hash_algorithm);
     74   ASSERT_EQ(tree_head.signature.signature_algorithm,
     75             expected_signature.signature_algorithm);
     76   ASSERT_EQ(tree_head.signature.signature_data,
     77             expected_signature.signature_data);
     78 }
     79 
     80 TEST(CTLogResponseParserTest, FailsToParseMissingFields) {
     81   std::string missing_signature_sth =
     82       CreateSignedTreeHeadJsonString(kSHA256RootHash, "");
     83 
     84   SignedTreeHead tree_head;
     85   ASSERT_FALSE(FillSignedTreeHead(missing_signature_sth, &tree_head));
     86 
     87   std::string missing_root_hash_sth =
     88       CreateSignedTreeHeadJsonString("", kTreeHeadSignature);
     89   ASSERT_FALSE(FillSignedTreeHead(missing_root_hash_sth, &tree_head));
     90 }
     91 
     92 TEST(CTLogResponseParserTest, FailsToParseIncorrectLengthRootHash) {
     93   SignedTreeHead tree_head;
     94 
     95   std::string too_long_hash = CreateSignedTreeHeadJsonString(
     96       kSHA256RootHash, "/WHFMgXtI/umKKuACJIN0Bb73TcILm9WkeU6qszvoArK\n");
     97   ASSERT_FALSE(FillSignedTreeHead(too_long_hash, &tree_head));
     98 
     99   std::string too_short_hash = CreateSignedTreeHeadJsonString(
    100       kSHA256RootHash, "/WHFMgXtI/umKKuACJIN0Bb73TcILm9WkeU6qszvoA==\n");
    101   ASSERT_FALSE(FillSignedTreeHead(too_short_hash, &tree_head));
    102 }
    103 
    104 }  // namespace ct
    105 
    106 }  // namespace net
    107