File: log_verifier.cc

package info (click to toggle)
golang-github-google-certificate-transparency 0.0~git20160709.0.0f6e3d1~ds1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, buster
  • size: 5,676 kB
  • sloc: cpp: 35,278; python: 11,838; java: 1,911; sh: 1,885; makefile: 950; xml: 520; ansic: 225
file content (129 lines) | stat: -rw-r--r-- 4,690 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "log/log_verifier.h"

#include <glog/logging.h>
#include <stdint.h>

#include "log/cert_submission_handler.h"
#include "log/log_signer.h"
#include "merkletree/merkle_verifier.h"
#include "proto/ct.pb.h"
#include "proto/serializer.h"
#include "util/util.h"

using cert_trans::serialization::SerializeResult;
using ct::LogEntry;
using ct::MerkleAuditProof;
using ct::SignedCertificateTimestamp;
using ct::SignedTreeHead;
using std::string;

LogVerifier::LogVerifier(LogSigVerifier* sig_verifier,
                         MerkleVerifier* merkle_verifier)
    : sig_verifier_(sig_verifier), merkle_verifier_(merkle_verifier) {
}

LogVerifier::~LogVerifier() {
  delete sig_verifier_;
  delete merkle_verifier_;
}

LogVerifier::LogVerifyResult LogVerifier::VerifySignedCertificateTimestamp(
    const LogEntry& entry, const SignedCertificateTimestamp& sct,
    uint64_t begin_range, uint64_t end_range, string* merkle_leaf_hash) const {
  if (!IsBetween(sct.timestamp(), begin_range, end_range))
    return INVALID_TIMESTAMP;

  // TODO(ekasper): separate format and signature errors.
  if (sig_verifier_->VerifySCTSignature(entry, sct) != LogSigVerifier::OK)
    return INVALID_SIGNATURE;
  string serialized_leaf;
  // If SCT verification succeeded, then we should never fail here.
  if (merkle_leaf_hash != NULL) {
    CHECK_EQ(SerializeResult::OK,
             Serializer::SerializeSCTMerkleTreeLeaf(sct, entry,
                                                    &serialized_leaf));
    merkle_leaf_hash->assign(merkle_verifier_->LeafHash(serialized_leaf));
  }
  return VERIFY_OK;
}

LogVerifier::LogVerifyResult LogVerifier::VerifySignedCertificateTimestamp(
    const LogEntry& entry, const SignedCertificateTimestamp& sct,
    string* merkle_leaf_hash) const {
  // Allow a bit of slack, say 1 second into the future.
  return VerifySignedCertificateTimestamp(entry, sct, 0,
                                          util::TimeInMilliseconds() + 1000,
                                          merkle_leaf_hash);
}

LogVerifier::LogVerifyResult LogVerifier::VerifySignedTreeHead(
    const SignedTreeHead& sth, uint64_t begin_range,
    uint64_t end_range) const {
  if (!IsBetween(sth.timestamp(), begin_range, end_range))
    return INVALID_TIMESTAMP;

  if (sig_verifier_->VerifySTHSignature(sth) != LogSigVerifier::OK)
    return INVALID_SIGNATURE;
  return VERIFY_OK;
}

LogVerifier::LogVerifyResult LogVerifier::VerifySignedTreeHead(
    const SignedTreeHead& sth) const {
  // Allow a bit of slack, say 1 second into the future.
  return VerifySignedTreeHead(sth, 0, util::TimeInMilliseconds() + 1000);
}

LogVerifier::LogVerifyResult LogVerifier::VerifyMerkleAuditProof(
    const LogEntry& entry, const SignedCertificateTimestamp& sct,
    const MerkleAuditProof& merkle_proof) const {
  if (!IsBetween(merkle_proof.timestamp(), sct.timestamp(),
                 util::TimeInMilliseconds() + 1000))
    return INCONSISTENT_TIMESTAMPS;

  string serialized_leaf;
  SerializeResult serialize_result =
      Serializer::SerializeSCTMerkleTreeLeaf(sct, entry, &serialized_leaf);

  if (serialize_result != SerializeResult::OK)
    return INVALID_FORMAT;

  std::vector<string> path;
  for (int i = 0; i < merkle_proof.path_node_size(); ++i)
    path.push_back(merkle_proof.path_node(i));

  // Leaf indexing in the MerkleTree starts from 1.
  string root_hash =
      merkle_verifier_->RootFromPath(merkle_proof.leaf_index() + 1,
                                     merkle_proof.tree_size(), path,
                                     serialized_leaf);

  if (root_hash.empty())
    return INVALID_MERKLE_PATH;

  SignedTreeHead sth;
  sth.set_version(merkle_proof.version());
  sth.mutable_id()->CopyFrom(merkle_proof.id());
  sth.set_timestamp(merkle_proof.timestamp());
  sth.set_tree_size(merkle_proof.tree_size());
  sth.set_sha256_root_hash(root_hash);
  sth.mutable_signature()->CopyFrom(merkle_proof.tree_head_signature());

  if (sig_verifier_->VerifySTHSignature(sth) != LogSigVerifier::OK)
    return INVALID_SIGNATURE;
  return VERIFY_OK;
}

/* static */
bool LogVerifier::IsBetween(uint64_t timestamp, uint64_t earliest,
                            uint64_t latest) {
  return timestamp >= earliest && timestamp <= latest;
}

bool LogVerifier::VerifyConsistency(
    const ct::SignedTreeHead& sth1, const ct::SignedTreeHead& sth2,
    const std::vector<std::string>& proof) const {
  return merkle_verifier_->VerifyConsistency(sth1.tree_size(),
                                             sth2.tree_size(),
                                             sth1.sha256_root_hash(),
                                             sth2.sha256_root_hash(), proof);
}