File: frontend_signer.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 (86 lines) | stat: -rw-r--r-- 2,873 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
/* -*- indent-tabs-mode: nil -*- */
#include "log/frontend_signer.h"

#include <glog/logging.h>

#include "log/database.h"
#include "log/log_signer.h"
#include "merkletree/serial_hasher.h"
#include "proto/ct.pb.h"
#include "proto/serializer.h"
#include "util/status.h"
#include "util/util.h"

using cert_trans::ConsistentStore;
using cert_trans::Database;
using cert_trans::LoggedEntry;
using ct::LogEntry;
using ct::SignedCertificateTimestamp;
using std::string;
using util::Status;


FrontendSigner::FrontendSigner(Database* db, ConsistentStore* store,
                               LogSigner* signer)
    : db_(CHECK_NOTNULL(db)),
      store_(CHECK_NOTNULL(store)),
      signer_(CHECK_NOTNULL(signer)) {
}

Status FrontendSigner::QueueEntry(const LogEntry& entry,
                                  SignedCertificateTimestamp* sct) {
  const string sha256_hash(
      Sha256Hasher::Sha256Digest(Serializer::LeafData(entry)));
  CHECK(!sha256_hash.empty());

  // Check if the entry already exists in the local DB (i.e. it's been
  // integrated into the tree.)
  // This isn't foolproof; it could be that the local node doesn't yet have
  // a copy of this if the cert was added recently, but it's not fatal if the
  // same cert gets added twice.
  // TODO(ekasper): switch to using SignedEntryWithType as the DB key.
  cert_trans::LoggedEntry logged;
  Database::LookupResult db_result = db_->LookupByHash(sha256_hash, &logged);

  if (db_result == Database::LOOKUP_OK) {
    // If we did find a local copy, return the previously issued SCT.
    if (sct != nullptr) {
      *sct = logged.sct();
    }
    return Status(util::error::ALREADY_EXISTS,
                  "entry already exists in Database");
  }
  CHECK_EQ(Database::NOT_FOUND, db_result);

  // Dont have the cert locally, so create an SCT and store it and the cert.
  SignedCertificateTimestamp local_sct;
  TimestampAndSign(entry, &local_sct);

  cert_trans::LoggedEntry new_logged;
  new_logged.mutable_sct()->CopyFrom(local_sct);
  new_logged.mutable_entry()->CopyFrom(entry);
  CHECK_EQ(new_logged.Hash(), sha256_hash);

  // If this cert has already been added (but not yet integrated into the
  // tree), then this call will update new_logged.sct with the previously
  // issued one.
  util::Status status(store_->AddPendingEntry(&new_logged));
  CHECK_EQ(new_logged.Hash(), sha256_hash);

  if (sct != nullptr) {
    *sct = new_logged.sct();
  }

  return status;
}


void FrontendSigner::TimestampAndSign(const LogEntry& entry,
                                      SignedCertificateTimestamp* sct) const {
  sct->set_version(ct::V1);
  sct->set_timestamp(util::TimeInMilliseconds());
  sct->clear_extensions();
  // The submission handler has already verified the format of this entry,
  // so this should never fail.
  CHECK_EQ(LogSigner::OK, signer_->SignCertificateTimestamp(entry, sct));
}