| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/cast_certificate/cast_crl.h" | 5 #include "components/cast_certificate/cast_crl.h" |
| 6 | 6 |
| 7 #include <unordered_map> | 7 #include <unordered_map> |
| 8 #include <unordered_set> | 8 #include <unordered_set> |
| 9 | 9 |
| 10 #include "base/base64.h" | 10 #include "base/base64.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 CastCRLTrustStore>>::get(); | 55 CastCRLTrustStore>>::get(); |
| 56 } | 56 } |
| 57 | 57 |
| 58 static net::TrustStore& Get() { return GetInstance()->store_; } | 58 static net::TrustStore& Get() { return GetInstance()->store_; } |
| 59 | 59 |
| 60 private: | 60 private: |
| 61 friend struct base::DefaultSingletonTraits<CastCRLTrustStore>; | 61 friend struct base::DefaultSingletonTraits<CastCRLTrustStore>; |
| 62 | 62 |
| 63 CastCRLTrustStore() { | 63 CastCRLTrustStore() { |
| 64 // Initialize the trust store with the root certificate. | 64 // Initialize the trust store with the root certificate. |
| 65 scoped_refptr<net::ParsedCertificate> root = | 65 scoped_refptr<net::ParsedCertificate> cert = |
| 66 net::ParsedCertificate::CreateFromCertificateData( | 66 net::ParsedCertificate::CreateFromCertificateData( |
| 67 kCastCRLRootCaDer, sizeof(kCastCRLRootCaDer), | 67 kCastCRLRootCaDer, sizeof(kCastCRLRootCaDer), |
| 68 net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE, {}); | 68 net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE, {}); |
| 69 CHECK(root); | 69 CHECK(cert); |
| 70 store_.AddTrustedCertificate(std::move(root)); | 70 // TODO(crbug.com/635200): Support anchor constraints. |
| 71 auto anchor = |
| 72 net::TrustAnchor::CreateFromCertificateNoConstraints(std::move(cert)); |
| 73 CHECK(anchor); |
| 74 store_.AddTrustAnchor(std::move(anchor)); |
| 71 } | 75 } |
| 72 | 76 |
| 73 net::TrustStore store_; | 77 net::TrustStore store_; |
| 74 DISALLOW_COPY_AND_ASSIGN(CastCRLTrustStore); | 78 DISALLOW_COPY_AND_ASSIGN(CastCRLTrustStore); |
| 75 }; | 79 }; |
| 76 | 80 |
| 77 // Converts a uint64_t unix timestamp to net::der::GeneralizedTime. | 81 // Converts a uint64_t unix timestamp to net::der::GeneralizedTime. |
| 78 bool ConvertTimeSeconds(uint64_t seconds, | 82 bool ConvertTimeSeconds(uint64_t seconds, |
| 79 net::der::GeneralizedTime* generalized_time) { | 83 net::der::GeneralizedTime* generalized_time) { |
| 80 base::Time unix_timestamp = | 84 base::Time unix_timestamp = |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 VLOG(2) << "CRL - Unable to parse not_after."; | 164 VLOG(2) << "CRL - Unable to parse not_after."; |
| 161 return false; | 165 return false; |
| 162 } | 166 } |
| 163 if ((verification_time < not_before) || (verification_time > not_after)) { | 167 if ((verification_time < not_before) || (verification_time > not_after)) { |
| 164 VLOG(2) << "CRL - Not time-valid."; | 168 VLOG(2) << "CRL - Not time-valid."; |
| 165 return false; | 169 return false; |
| 166 } | 170 } |
| 167 | 171 |
| 168 // Set CRL expiry to the earliest of the cert chain expiry and CRL expiry. | 172 // Set CRL expiry to the earliest of the cert chain expiry and CRL expiry. |
| 169 *overall_not_after = not_after; | 173 *overall_not_after = not_after; |
| 170 for (const auto& cert : result.paths[result.best_result_index]->path) { | 174 for (const auto& cert : result.paths[result.best_result_index]->path.certs) { |
| 171 net::der::GeneralizedTime cert_not_after = cert->tbs().validity_not_after; | 175 net::der::GeneralizedTime cert_not_after = cert->tbs().validity_not_after; |
| 172 if (cert_not_after < *overall_not_after) | 176 if (cert_not_after < *overall_not_after) |
| 173 *overall_not_after = cert_not_after; | 177 *overall_not_after = cert_not_after; |
| 174 } | 178 } |
| 175 | 179 |
| 176 // Perform sanity check on serial numbers. | 180 // Perform sanity check on serial numbers. |
| 177 for (const auto& range : tbs_crl.revoked_serial_number_ranges()) { | 181 for (const auto& range : tbs_crl.revoked_serial_number_ranges()) { |
| 178 uint64_t first_serial_number = range.first_serial_number(); | 182 uint64_t first_serial_number = range.first_serial_number(); |
| 179 uint64_t last_serial_number = range.last_serial_number(); | 183 uint64_t last_serial_number = range.last_serial_number(); |
| 180 if (last_serial_number < first_serial_number) { | 184 if (last_serial_number < first_serial_number) { |
| 181 VLOG(2) << "CRL - Malformed serial number range."; | 185 VLOG(2) << "CRL - Malformed serial number range."; |
| 182 return false; | 186 return false; |
| 183 } | 187 } |
| 184 } | 188 } |
| 185 return true; | 189 return true; |
| 186 } | 190 } |
| 187 | 191 |
| 188 class CastCRLImpl : public CastCRL { | 192 class CastCRLImpl : public CastCRL { |
| 189 public: | 193 public: |
| 190 CastCRLImpl(const TbsCrl& tbs_crl, | 194 CastCRLImpl(const TbsCrl& tbs_crl, |
| 191 const net::der::GeneralizedTime& overall_not_after); | 195 const net::der::GeneralizedTime& overall_not_after); |
| 192 ~CastCRLImpl() override; | 196 ~CastCRLImpl() override; |
| 193 | 197 |
| 194 bool CheckRevocation(const net::ParsedCertificateList& trusted_chain, | 198 bool CheckRevocation(const net::CertPath& trusted_chain, |
| 195 const base::Time& time) const override; | 199 const base::Time& time) const override; |
| 196 | 200 |
| 197 private: | 201 private: |
| 198 struct SerialNumberRange { | 202 struct SerialNumberRange { |
| 199 uint64_t first_serial; | 203 uint64_t first_serial; |
| 200 uint64_t last_serial; | 204 uint64_t last_serial; |
| 201 }; | 205 }; |
| 202 | 206 |
| 203 net::der::GeneralizedTime not_before_; | 207 net::der::GeneralizedTime not_before_; |
| 204 net::der::GeneralizedTime not_after_; | 208 net::der::GeneralizedTime not_after_; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 238 uint64_t last_serial_number = range.last_serial_number(); | 242 uint64_t last_serial_number = range.last_serial_number(); |
| 239 auto& serial_number_range = revoked_serial_numbers_[issuer_hash]; | 243 auto& serial_number_range = revoked_serial_numbers_[issuer_hash]; |
| 240 serial_number_range.push_back({first_serial_number, last_serial_number}); | 244 serial_number_range.push_back({first_serial_number, last_serial_number}); |
| 241 } | 245 } |
| 242 } | 246 } |
| 243 | 247 |
| 244 CastCRLImpl::~CastCRLImpl() {} | 248 CastCRLImpl::~CastCRLImpl() {} |
| 245 | 249 |
| 246 // Verifies the revocation status of the certificate chain, at the specified | 250 // Verifies the revocation status of the certificate chain, at the specified |
| 247 // time. | 251 // time. |
| 248 bool CastCRLImpl::CheckRevocation( | 252 bool CastCRLImpl::CheckRevocation(const net::CertPath& trusted_chain, |
| 249 const net::ParsedCertificateList& trusted_chain, | 253 const base::Time& time) const { |
| 250 const base::Time& time) const { | 254 if (trusted_chain.IsEmpty()) |
| 251 if (trusted_chain.empty()) | |
| 252 return false; | 255 return false; |
| 253 | 256 |
| 254 // Check the validity of the CRL at the specified time. | 257 // Check the validity of the CRL at the specified time. |
| 255 net::der::GeneralizedTime verification_time; | 258 net::der::GeneralizedTime verification_time; |
| 256 if (!net::der::EncodeTimeAsGeneralizedTime(time, &verification_time)) { | 259 if (!net::der::EncodeTimeAsGeneralizedTime(time, &verification_time)) { |
| 257 VLOG(2) << "CRL verification time malformed."; | 260 VLOG(2) << "CRL verification time malformed."; |
| 258 return false; | 261 return false; |
| 259 } | 262 } |
| 260 if ((verification_time < not_before_) || (verification_time > not_after_)) { | 263 if ((verification_time < not_before_) || (verification_time > not_after_)) { |
| 261 VLOG(2) << "CRL not time-valid. Perform hard fail."; | 264 VLOG(2) << "CRL not time-valid. Perform hard fail."; |
| 262 return false; | 265 return false; |
| 263 } | 266 } |
| 264 | 267 |
| 265 // Check revocation. | 268 // Check revocation -- Note that this loop has "+ 1" in order to also loop |
| 266 for (size_t i = 0; i < trusted_chain.size(); ++i) { | 269 // over the trust anchor (which is treated specially). |
| 267 const auto& parsed_cert = trusted_chain[i]; | 270 for (size_t i = 0; i < trusted_chain.certs.size() + 1; ++i) { |
| 271 // This loop iterates over both certificates AND the trust anchor, |
| 272 // depending on what the value of |i| is. |
| 273 net::der::Input spki_tlv; |
| 274 if (i == trusted_chain.certs.size()) { |
| 275 spki_tlv = trusted_chain.trust_anchor->spki(); |
| 276 } else { |
| 277 spki_tlv = trusted_chain.certs[i]->tbs().spki_tlv; |
| 278 } |
| 279 |
| 268 // Calculate the public key's hash to check for revocation. | 280 // Calculate the public key's hash to check for revocation. |
| 269 std::string spki_hash = | 281 std::string spki_hash = crypto::SHA256HashString(spki_tlv.AsString()); |
| 270 crypto::SHA256HashString(parsed_cert->tbs().spki_tlv.AsString()); | |
| 271 if (revoked_hashes_.find(spki_hash) != revoked_hashes_.end()) { | 282 if (revoked_hashes_.find(spki_hash) != revoked_hashes_.end()) { |
| 272 VLOG(2) << "Public key is revoked."; | 283 VLOG(2) << "Public key is revoked."; |
| 273 return false; | 284 return false; |
| 274 } | 285 } |
| 275 | 286 |
| 276 // Check if the subordinate certificate was revoked by serial number. | 287 // Check if the subordinate certificate was revoked by serial number. |
| 277 if (i > 0) { | 288 if (i > 0) { |
| 278 auto issuer_iter = revoked_serial_numbers_.find(spki_hash); | 289 auto issuer_iter = revoked_serial_numbers_.find(spki_hash); |
| 279 if (issuer_iter != revoked_serial_numbers_.end()) { | 290 if (issuer_iter != revoked_serial_numbers_.end()) { |
| 280 const auto& subordinate = trusted_chain[i - 1]; | 291 const auto& subordinate = trusted_chain.certs[i - 1]; |
| 281 uint64_t serial_number; | 292 uint64_t serial_number; |
| 282 // Only Google generated device certificates will be revoked by range. | 293 // Only Google generated device certificates will be revoked by range. |
| 283 // These will always be less than 64 bits in length. | 294 // These will always be less than 64 bits in length. |
| 284 if (!net::der::ParseUint64(subordinate->tbs().serial_number, | 295 if (!net::der::ParseUint64(subordinate->tbs().serial_number, |
| 285 &serial_number)) { | 296 &serial_number)) { |
| 286 continue; | 297 continue; |
| 287 } | 298 } |
| 288 for (const auto& revoked_serial : issuer_iter->second) { | 299 for (const auto& revoked_serial : issuer_iter->second) { |
| 289 if (revoked_serial.first_serial <= serial_number && | 300 if (revoked_serial.first_serial <= serial_number && |
| 290 revoked_serial.last_serial >= serial_number) { | 301 revoked_serial.last_serial >= serial_number) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 } | 347 } |
| 337 | 348 |
| 338 std::unique_ptr<CastCRL> ParseAndVerifyCRLForTest( | 349 std::unique_ptr<CastCRL> ParseAndVerifyCRLForTest( |
| 339 const std::string& crl_proto, | 350 const std::string& crl_proto, |
| 340 const base::Time& time, | 351 const base::Time& time, |
| 341 net::TrustStore* trust_store) { | 352 net::TrustStore* trust_store) { |
| 342 return ParseAndVerifyCRL(crl_proto, time, trust_store); | 353 return ParseAndVerifyCRL(crl_proto, time, trust_store); |
| 343 } | 354 } |
| 344 | 355 |
| 345 } // namespace cast_certificate | 356 } // namespace cast_certificate |
| OLD | NEW |