summaryrefslogtreecommitdiffstats
path: root/chromium/components/certificate_transparency/chrome_ct_policy_enforcer.h
blob: c167e4e281c1117d228fa78496edddd97a485c95 (plain)
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_CERTIFICATE_TRANSPARENCY_CHROME_CT_POLICY_ENFORCER_H_
#define COMPONENTS_CERTIFICATE_TRANSPARENCY_CHROME_CT_POLICY_ENFORCER_H_

#include <map>
#include <string>
#include <utility>
#include <vector>

#include "base/component_export.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/time/clock.h"
#include "base/time/time.h"
#include "net/cert/ct_policy_enforcer.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace certificate_transparency {

struct COMPONENT_EXPORT(CERTIFICATE_TRANSPARENCY) OperatorHistoryEntry {
  // Name of the current operator for the log.
  std::string current_operator_;
  // Vector of previous operators (if any) for the log, represented as pairs of
  // operator name and time when they stopped operating the log.
  std::vector<std::pair<std::string, base::Time>> previous_operators_;

  OperatorHistoryEntry();
  ~OperatorHistoryEntry();
  OperatorHistoryEntry(const OperatorHistoryEntry& other);
};

// A CTPolicyEnforcer that enforces the "Certificate Transparency in Chrome"
// policies detailed at
// https://github.com/chromium/ct-policy/blob/master/ct_policy.md
//
// This should only be used when there is a reliable, rapid update mechanism
// for the set of known, qualified logs - either through a reliable binary
// updating mechanism or through out-of-band delivery. See
// //net/docs/certificate-transparency.md for more details.
class COMPONENT_EXPORT(CERTIFICATE_TRANSPARENCY) ChromeCTPolicyEnforcer
    : public net::CTPolicyEnforcer {
 public:
  // |logs| is a list of Certificate Transparency logs.  Data about each log is
  // needed to apply Chrome's policies. |disqualified_logs| is a map of log ID
  // to disqualification date.  |operated_by_google_logs| is a list of log IDs
  // operated by Google.  (Log IDs are the SHA-256 hash of the log's DER-encoded
  // SubjectPublicKeyInfo.)  |log_list_date| is the time at which the other two
  // arguments were generated.  Both lists of logs must be sorted by log ID.
  ChromeCTPolicyEnforcer(
      base::Time log_list_date,
      std::vector<std::pair<std::string, base::Time>> disqualified_logs,
      std::vector<std::string> operated_by_google_logs,
      std::map<std::string, OperatorHistoryEntry> log_operator_history);

  ~ChromeCTPolicyEnforcer() override;

  net::ct::CTPolicyCompliance CheckCompliance(
      net::X509Certificate* cert,
      const net::ct::SCTList& verified_scts,
      const net::NetLogWithSource& net_log) override;

  // Updates the list of logs used for compliance checks. |disqualified_logs| is
  // a map of log ID to disqualification date.  |operated_by_google_logs| is a
  // list of log IDs operated by Google
  void UpdateCTLogList(
      base::Time update_time,
      std::vector<std::pair<std::string, base::Time>> disqualified_logs,
      std::vector<std::string> operated_by_google_logs,
      std::map<std::string, OperatorHistoryEntry> log_operator_history);

  void SetClockForTesting(const base::Clock* clock) { clock_ = clock; }

  // TODO(https://crbug.com/999240): These are exposed to allow end-to-end
  // testing by higher layers (i.e. that the ChromeCTPolicyEnforcer is
  // correctly constructed). When either this issue or https://crbug.com/848277
  // are fixed, the configuration can be tested independently, and these can
  // be removed.
  const std::vector<std::string>& operated_by_google_logs_for_testing() {
    return operated_by_google_logs_;
  }
  const std::vector<std::pair<std::string, base::Time>>&
  disqualified_logs_for_testing() {
    return disqualified_logs_;
  }

  const std::map<std::string, OperatorHistoryEntry>&
  operator_history_for_testing() {
    return log_operator_history_;
  }

  void SetOperatorHistoryForTesting(
      std::map<std::string, OperatorHistoryEntry> log_operator_history) {
    log_operator_history_ = std::move(log_operator_history);
  }

  void SetValidGoogleLogForTesting(const std::string& google_log) {
    valid_google_log_for_testing_ = google_log;
  }

  void SetDisqualifiedLogForTesting(
      const std::pair<std::string, base::Time>& disqualified_log) {
    disqualified_log_for_testing_ = disqualified_log;
  }

 private:
  FRIEND_TEST_ALL_PREFIXES(ChromeCTPolicyEnforcerTestBothPolicies,
                           IsLogDisqualifiedTimestamp);
  FRIEND_TEST_ALL_PREFIXES(ChromeCTPolicyEnforcerTestBothPolicies,
                           IsLogDisqualifiedReturnsFalseOnUnknownLog);
  // Returns true if the log identified by |log_id| (the SHA-256 hash of the
  // log's DER-encoded SPKI) has been disqualified, and sets
  // |*disqualification_date| to the date of disqualification. Any SCTs that
  // are embedded in certificates issued after |*disqualification_date| should
  // not be trusted, nor contribute to any uniqueness or freshness
  bool IsLogDisqualified(base::StringPiece log_id,
                         base::Time* disqualification_date) const;

  // Returns true if the log identified by |log_id| (the SHA-256 hash of the
  // log's DER-encoded SPKI) is operated by Google.
  bool IsLogOperatedByGoogle(base::StringPiece log_id) const;

  // Returns true if the supplied log data are fresh enough.
  bool IsLogDataTimely() const;

  net::ct::CTPolicyCompliance CheckCTPolicyCompliance(
      const net::X509Certificate& cert,
      const net::ct::SCTList& verified_scts) const;

  std::string GetOperatorForLog(std::string log_id, base::Time timestamp) const;

  // Map of SHA-256(SPKI) to log disqualification date.
  std::vector<std::pair<std::string, base::Time>> disqualified_logs_;

  // List of SHA-256(SPKI) for logs operated by Google.
  std::vector<std::string> operated_by_google_logs_;

  std::map<std::string, OperatorHistoryEntry> log_operator_history_;

  raw_ptr<const base::Clock> clock_;

  // The time at which |disqualified_logs_| and |operated_by_google_logs_| were
  // generated.
  base::Time log_list_date_;

  // If set, this log ID will be considered a valid, Google operated log.
  // Calling UpdateCTLogList clears this value if set.
  absl::optional<std::string> valid_google_log_for_testing_;

  // If set, this log ID will be considered a disqualified log, effective at the
  // specified time.
  // Calling UpdateCTLogList clears this value if set.
  absl::optional<std::pair<std::string, base::Time>>
      disqualified_log_for_testing_;
};

}  // namespace certificate_transparency

#endif  // COMPONENTS_CERTIFICATE_TRANSPARENCY_CHROME_CT_POLICY_ENFORCER_H_