Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(361)

Side by Side Diff: components/cast_certificate/cast_crl.cc

Issue 2050983002: Cast device revocation checking. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed test failure on 32 bit systems. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "components/cast_certificate/cast_crl.h"
6
7 #include <unordered_map>
8 #include <unordered_set>
9
10 #include "base/base64.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/memory/singleton.h"
13 #include "components/cast_certificate/proto/revocation.pb.h"
14 #include "crypto/sha2.h"
15 #include "net/cert/internal/parse_certificate.h"
16 #include "net/cert/internal/parsed_certificate.h"
17 #include "net/cert/internal/path_builder.h"
18 #include "net/cert/internal/signature_algorithm.h"
19 #include "net/cert/internal/signature_policy.h"
20 #include "net/cert/internal/trust_store.h"
21 #include "net/cert/internal/verify_certificate_chain.h"
22 #include "net/cert/internal/verify_signed_data.h"
23 #include "net/cert/x509_certificate.h"
24 #include "net/der/encode_values.h"
25 #include "net/der/input.h"
26 #include "net/der/parser.h"
27 #include "net/der/parse_values.h"
28
29 namespace cast_certificate {
30 namespace {
31
32 enum CrlVersion {
33 // version 0: Spki Hash Algorithm = SHA-256
34 // Signature Algorithm = RSA-PKCS1 V1.5 with SHA-256
35 CRL_VERSION_0 = 0,
36 };
37
38 // -------------------------------------------------------------------------
39 // Cast CRL trust anchors.
40 // -------------------------------------------------------------------------
41
42 // There is one trusted root for Cast CRL certificate chains:
43 //
44 // (1) CN=Cast CRL Root CA (kCastCRLRootCaDer)
45 //
46 // These constants are defined by the file included next:
47
48 #include "components/cast_certificate/cast_crl_root_ca_cert_der-inc.h"
49
50 // Singleton for the Cast CRL trust store.
51 class CastCRLTrustStore {
52 public:
53 static CastCRLTrustStore* GetInstance() {
54 return base::Singleton<CastCRLTrustStore, base::LeakySingletonTraits<
55 CastCRLTrustStore>>::get();
56 }
57
58 static net::TrustStore& Get() { return GetInstance()->store_; }
59
60 private:
61 friend struct base::DefaultSingletonTraits<CastCRLTrustStore>;
62
63 CastCRLTrustStore() {
64 // Initialize the trust store with the root certificate.
65 // TODO(ryanchung): Add official Cast CRL Root here
66 // scoped_refptr<net::ParsedCertificate> root = net::ParsedCertificate::
67 // net::ParsedCertificate::CreateFromCertificateData(
68 // kCastCRLRootCaDer, sizeof(kCastCRLRootCaDer),
69 // net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE, {});
70 // CHECK(root);
71 // store_.AddTrustedCertificate(std::move(root));
72 }
73
74 net::TrustStore store_;
75 DISALLOW_COPY_AND_ASSIGN(CastCRLTrustStore);
76 };
77
78 // Converts a uint64_t unix timestamp to net::der::GeneralizedTime.
79 bool ConvertTimeSeconds(uint64_t seconds,
80 net::der::GeneralizedTime* generalized_time) {
81 base::Time unix_timestamp =
82 base::Time::UnixEpoch() +
83 base::TimeDelta::FromSeconds(base::saturated_cast<int64_t>(seconds));
84 return net::der::EncodeTimeAsGeneralizedTime(unix_timestamp,
85 generalized_time);
86 }
87
88 // Specifies the signature verification policy.
89 // The required algorithms are:
90 // RSASSA PKCS#1 v1.5 with SHA-256, using RSA keys 2048-bits or longer.
91 std::unique_ptr<net::SignaturePolicy> CreateCastSignaturePolicy() {
92 return base::WrapUnique(new net::SimpleSignaturePolicy(2048));
93 }
94
95 // Verifies the CRL is signed by a trusted CRL authority at the time the CRL
96 // was issued. Verifies the signature of |tbs_crl| is valid based on the
97 // certificate and signature in |crl|. The validity of |tbs_crl| is verified
98 // at |time|. The validity period of the CRL is adjusted to be the earliest
99 // of the issuer certificate chain's expiration and the CRL's expiration and
100 // the result is stored in |overall_not_after|.
101 bool VerifyCRL(const Crl& crl,
102 const TbsCrl& tbs_crl,
103 const base::Time& time,
104 net::der::GeneralizedTime* overall_not_after) {
105 // Verify the trust of the CRL authority.
106 scoped_refptr<net::ParsedCertificate> parsed_cert =
107 net::ParsedCertificate::CreateFromCertificateData(
108 reinterpret_cast<const uint8_t*>(crl.signer_cert().data()),
109 crl.signer_cert().size(),
110 net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE, {});
111 if (parsed_cert == nullptr) {
112 VLOG(2) << "CRL - Issuer certificate parsing failed.";
113 return false;
114 }
115
116 // Wrap the signature in a BitString.
117 net::der::BitString signature_value_bit_string = net::der::BitString(
118 net::der::Input(base::StringPiece(crl.signature())), 0);
119
120 // Verify the signature.
121 auto signature_policy = CreateCastSignaturePolicy();
122 std::unique_ptr<net::SignatureAlgorithm> signature_algorithm_type =
123 net::SignatureAlgorithm::CreateRsaPkcs1(net::DigestAlgorithm::Sha256);
124 if (!VerifySignedData(*signature_algorithm_type,
125 net::der::Input(&crl.tbs_crl()),
126 signature_value_bit_string, parsed_cert->tbs().spki_tlv,
127 signature_policy.get())) {
128 VLOG(2) << "CRL - Signature verification failed.";
129 return false;
130 }
131
132 // Verify the issuer certificate.
133 net::der::GeneralizedTime verification_time;
134 if (!net::der::EncodeTimeAsGeneralizedTime(time, &verification_time)) {
135 VLOG(2) << "CRL - Unable to parse verification time.";
136 return false;
137 }
138 net::CertPathBuilder::Result result;
139 net::CertPathBuilder path_builder(
140 parsed_cert.get(), &CastCRLTrustStore::Get(), signature_policy.get(),
141 verification_time, &result);
142 net::CompletionStatus rv = path_builder.Run(base::Closure());
143 DCHECK_EQ(rv, net::CompletionStatus::SYNC);
144 if (!result.is_success() || result.paths.empty() ||
145 !result.paths[result.best_result_index]->is_success()) {
146 VLOG(2) << "CRL - Issuer certificate verification failed.";
147 return false;
148 }
149 // There are no requirements placed on the leaf certificate having any
150 // particular KeyUsages. Leaf certificate checks are bypassed.
151
152 // Verify the CRL is still valid.
153 net::der::GeneralizedTime not_before;
154 if (!ConvertTimeSeconds(tbs_crl.not_before_seconds(), &not_before)) {
155 VLOG(2) << "CRL - Unable to parse not_before.";
156 return false;
157 }
158 net::der::GeneralizedTime not_after;
159 if (!ConvertTimeSeconds(tbs_crl.not_after_seconds(), &not_after)) {
160 VLOG(2) << "CRL - Unable to parse not_after.";
161 return false;
162 }
163 if ((verification_time < not_before) || (verification_time > not_after)) {
164 VLOG(2) << "CRL - Not time-valid.";
165 return false;
166 }
167
168 // Set CRL expiry to the earliest of the cert chain expiry and CRL expiry.
169 *overall_not_after = not_after;
170 for (const auto& cert : result.paths[result.best_result_index]->path) {
171 net::der::GeneralizedTime cert_not_after = cert->tbs().validity_not_after;
172 if (cert_not_after < *overall_not_after)
173 *overall_not_after = cert_not_after;
174 }
175
176 // Perform sanity check on serial numbers.
177 for (const auto& range : tbs_crl.revoked_serial_number_ranges()) {
178 uint64_t first_serial_number = range.first_serial_number();
179 uint64_t last_serial_number = range.last_serial_number();
180 if (last_serial_number < first_serial_number) {
181 VLOG(2) << "CRL - Malformed serial number range.";
182 return false;
183 }
184 }
185 return true;
186 }
187
188 class CastCRLImpl : public CastCRL {
189 public:
190 CastCRLImpl(const TbsCrl& tbs_crl,
191 const net::der::GeneralizedTime& overall_not_after);
192 ~CastCRLImpl() override;
193
194 bool CheckRevocation(const net::ParsedCertificateList& trusted_chain,
195 const base::Time& time) const override;
196
197 private:
198 struct SerialNumberRange {
199 uint64_t first_serial;
200 uint64_t last_serial;
201 };
202
203 net::der::GeneralizedTime not_before_;
204 net::der::GeneralizedTime not_after_;
205
206 // Revoked public key hashes.
207 // The values consist of the SHA256 hash of the SubjectPublicKeyInfo.
208 std::set<std::string> revoked_hashes_;
209
210 // Revoked serial number ranges indexed by issuer public key hash.
211 // The key is the SHA256 hash of issuer's SubjectPublicKeyInfo.
212 // The value is a list of revoked serial number ranges.
213 std::unordered_map<std::string, std::vector<SerialNumberRange>>
214 revoked_serial_numbers_;
215 DISALLOW_COPY_AND_ASSIGN(CastCRLImpl);
216 };
217
218 CastCRLImpl::CastCRLImpl(const TbsCrl& tbs_crl,
219 const net::der::GeneralizedTime& overall_not_after) {
220 // Parse the validity information.
221 // Assume ConvertTimeSeconds will succeed. Successful call to VerifyCRL
222 // means that these calls were successful.
223 ConvertTimeSeconds(tbs_crl.not_before_seconds(), &not_before_);
224 ConvertTimeSeconds(tbs_crl.not_after_seconds(), &not_after_);
225 if (overall_not_after < not_after_)
226 not_after_ = overall_not_after;
227
228 // Parse the revoked hashes.
229 for (const auto& hash : tbs_crl.revoked_public_key_hashes()) {
230 revoked_hashes_.insert(hash);
231 }
232
233 // Parse the revoked serial ranges.
234 for (const auto& range : tbs_crl.revoked_serial_number_ranges()) {
235 std::string issuer_hash = range.issuer_public_key_hash();
236
237 uint64_t first_serial_number = range.first_serial_number();
238 uint64_t last_serial_number = range.last_serial_number();
239 auto& serial_number_range = revoked_serial_numbers_[issuer_hash];
240 serial_number_range.push_back({first_serial_number, last_serial_number});
241 }
242 }
243
244 CastCRLImpl::~CastCRLImpl() {}
245
246 // Verifies the revocation status of the certificate chain, at the specified
247 // time.
248 bool CastCRLImpl::CheckRevocation(
249 const net::ParsedCertificateList& trusted_chain,
250 const base::Time& time) const {
251 if (trusted_chain.empty())
252 return false;
253
254 // Check the validity of the CRL at the specified time.
255 net::der::GeneralizedTime verification_time;
256 if (!net::der::EncodeTimeAsGeneralizedTime(time, &verification_time)) {
257 VLOG(2) << "CRL verification time malformed.";
258 return false;
259 }
260 if ((verification_time < not_before_) || (verification_time > not_after_)) {
261 VLOG(2) << "CRL not time-valid. Perform hard fail.";
262 return false;
263 }
264
265 // Check revocation.
266 for (size_t i = 0; i < trusted_chain.size(); ++i) {
267 const auto& parsed_cert = trusted_chain[i];
268 // Calculate the public key's hash to check for revocation.
269 std::string spki_hash =
270 crypto::SHA256HashString(parsed_cert->tbs().spki_tlv.AsString());
271 if (revoked_hashes_.find(spki_hash) != revoked_hashes_.end()) {
272 VLOG(2) << "Public key is revoked.";
273 return false;
274 }
275
276 // Check if the subordinate certificate was revoked by serial number.
277 if (i > 0) {
278 auto issuer_iter = revoked_serial_numbers_.find(spki_hash);
279 if (issuer_iter != revoked_serial_numbers_.end()) {
280 const auto& subordinate = trusted_chain[i - 1];
281 uint64_t serial_number;
282 // Only Google generated device certificates will be revoked by range.
283 // These will always be less than 64 bits in length.
284 if (!net::der::ParseUint64(subordinate->tbs().serial_number,
285 &serial_number)) {
286 continue;
287 }
288 for (const auto& revoked_serial : issuer_iter->second) {
289 if (revoked_serial.first_serial <= serial_number &&
290 revoked_serial.last_serial >= serial_number) {
291 VLOG(2) << "Serial number is revoked";
292 return false;
293 }
294 }
295 }
296 }
297 }
298 return true;
299 }
300
301 } // namespace
302
303 std::unique_ptr<CastCRL> ParseAndVerifyCRL(const std::string& crl_proto,
304 const base::Time& time) {
305 CrlBundle crl_bundle;
306 if (!crl_bundle.ParseFromString(crl_proto)) {
307 LOG(ERROR) << "CRL - Binary could not be parsed.";
308 return nullptr;
309 }
310 for (auto const& crl : crl_bundle.crls()) {
311 TbsCrl tbs_crl;
312 if (!tbs_crl.ParseFromString(crl.tbs_crl())) {
313 LOG(WARNING) << "Binary TBS CRL could not be parsed.";
314 continue;
315 }
316 if (tbs_crl.version() != CRL_VERSION_0) {
317 continue;
318 }
319 net::der::GeneralizedTime overall_not_after;
320 if (!VerifyCRL(crl, tbs_crl, time, &overall_not_after)) {
321 LOG(ERROR) << "CRL - Verification failed.";
322 return nullptr;
323 }
324 return base::WrapUnique(new CastCRLImpl(tbs_crl, overall_not_after));
325 }
326 LOG(ERROR) << "No supported version of revocation data.";
327 return nullptr;
328 }
329
330 bool SetCRLTrustAnchorForTest(const std::string& cert) {
331 scoped_refptr<net::ParsedCertificate> anchor(
332 net::ParsedCertificate::CreateFromCertificateCopy(cert, {}));
333 if (!anchor)
334 return false;
335 CastCRLTrustStore::Get().Clear();
336 CastCRLTrustStore::Get().AddTrustedCertificate(std::move(anchor));
337 return true;
338 }
339
340 } // namespace cast_certificate
OLDNEW
« no previous file with comments | « components/cast_certificate/cast_crl.h ('k') | components/cast_certificate/cast_crl_root_ca_cert_der-inc.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698