OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_cert_validator.h" | 5 #include "components/cast_certificate/cast_cert_validator.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 #include <memory> | 11 #include <memory> |
12 #include <utility> | 12 #include <utility> |
13 | 13 |
14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
15 #include "base/memory/singleton.h" | 15 #include "base/memory/singleton.h" |
16 #include "net/cert/internal/cert_issuer_source_static.h" | |
16 #include "net/cert/internal/certificate_policies.h" | 17 #include "net/cert/internal/certificate_policies.h" |
17 #include "net/cert/internal/extended_key_usage.h" | 18 #include "net/cert/internal/extended_key_usage.h" |
18 #include "net/cert/internal/parse_certificate.h" | 19 #include "net/cert/internal/parse_certificate.h" |
19 #include "net/cert/internal/parse_name.h" | 20 #include "net/cert/internal/parse_name.h" |
20 #include "net/cert/internal/parsed_certificate.h" | 21 #include "net/cert/internal/parsed_certificate.h" |
22 #include "net/cert/internal/path_builder.h" | |
21 #include "net/cert/internal/signature_algorithm.h" | 23 #include "net/cert/internal/signature_algorithm.h" |
22 #include "net/cert/internal/signature_policy.h" | 24 #include "net/cert/internal/signature_policy.h" |
23 #include "net/cert/internal/trust_store.h" | 25 #include "net/cert/internal/trust_store.h" |
24 #include "net/cert/internal/verify_certificate_chain.h" | |
25 #include "net/cert/internal/verify_signed_data.h" | 26 #include "net/cert/internal/verify_signed_data.h" |
26 #include "net/der/input.h" | 27 #include "net/der/input.h" |
27 | 28 |
28 namespace cast_certificate { | 29 namespace cast_certificate { |
29 namespace { | 30 namespace { |
30 | 31 |
31 // ------------------------------------------------------------------------- | 32 // ------------------------------------------------------------------------- |
32 // Cast trust anchors. | 33 // Cast trust anchors. |
33 // ------------------------------------------------------------------------- | 34 // ------------------------------------------------------------------------- |
34 | 35 |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 net::der::GeneralizedTime result; | 239 net::der::GeneralizedTime result; |
239 result.year = exploded.year; | 240 result.year = exploded.year; |
240 result.month = exploded.month; | 241 result.month = exploded.month; |
241 result.day = exploded.day_of_month; | 242 result.day = exploded.day_of_month; |
242 result.hours = exploded.hour; | 243 result.hours = exploded.hour; |
243 result.minutes = exploded.minute; | 244 result.minutes = exploded.minute; |
244 result.seconds = exploded.second; | 245 result.seconds = exploded.second; |
245 return result; | 246 return result; |
246 } | 247 } |
247 | 248 |
248 class ScopedCheckUnreferencedCerts { | |
249 public: | |
250 explicit ScopedCheckUnreferencedCerts( | |
251 std::vector<scoped_refptr<net::ParsedCertificate>>* certs) | |
252 : certs_(certs) {} | |
253 ~ScopedCheckUnreferencedCerts() { | |
254 for (const auto& cert : *certs_) | |
255 DCHECK(cert->HasOneRef()); | |
256 } | |
257 | |
258 private: | |
259 std::vector<scoped_refptr<net::ParsedCertificate>>* certs_; | |
260 }; | |
261 | |
262 // Returns the parsing options used for Cast certificates. | 249 // Returns the parsing options used for Cast certificates. |
263 net::ParseCertificateOptions GetCertParsingOptions() { | 250 net::ParseCertificateOptions GetCertParsingOptions() { |
264 net::ParseCertificateOptions options; | 251 net::ParseCertificateOptions options; |
265 | 252 |
266 // Some cast intermediate certificates contain serial numbers that are | 253 // Some cast intermediate certificates contain serial numbers that are |
267 // 21 octets long, and might also not use valid DER encoding for an | 254 // 21 octets long, and might also not use valid DER encoding for an |
268 // INTEGER (non-minimal encoding). | 255 // INTEGER (non-minimal encoding). |
269 // | 256 // |
270 // Allow these sorts of serial numbers. | 257 // Allow these sorts of serial numbers. |
271 // | 258 // |
272 // TODO(eroman): At some point in the future this workaround will no longer be | 259 // TODO(eroman): At some point in the future this workaround will no longer be |
273 // necessary. Should revisit this for removal in 2017 if not earlier. | 260 // necessary. Should revisit this for removal in 2017 if not earlier. |
274 options.allow_invalid_serial_numbers = true; | 261 options.allow_invalid_serial_numbers = true; |
275 return options; | 262 return options; |
276 } | 263 } |
277 | 264 |
278 } // namespace | 265 } // namespace |
279 | 266 |
280 bool VerifyDeviceCert(const std::vector<std::string>& certs, | 267 bool VerifyDeviceCert(const std::vector<std::string>& certs, |
eroman
2016/06/27 19:58:52
Can you update the documentation in components/cas
mattm
2016/06/27 23:45:45
Done.
| |
281 const base::Time::Exploded& time, | 268 const base::Time::Exploded& time, |
282 std::unique_ptr<CertVerificationContext>* context, | 269 std::unique_ptr<CertVerificationContext>* context, |
283 CastDeviceCertPolicy* policy) { | 270 CastDeviceCertPolicy* policy) { |
284 // The underlying verification function expects a sequence of | 271 if (certs.empty()) |
285 // ParsedCertificate. | 272 return false; |
286 std::vector<scoped_refptr<net::ParsedCertificate>> input_chain; | |
287 // Verify that nothing saves a reference to the input certs, since the backing | |
288 // data will go out of scope when the function finishes. | |
289 ScopedCheckUnreferencedCerts ref_checker(&input_chain); | |
290 | 273 |
291 for (const auto& cert_der : certs) { | 274 // No reference to these ParsedCertificates is kept past the end of this |
292 // No reference to the ParsedCertificate is kept past the end of this | 275 // function, so using EXTERNAL_REFERENCE here is safe. |
293 // function, so using EXTERNAL_REFERENCE here is safe. | 276 scoped_refptr<net::ParsedCertificate> target_cert( |
294 if (!net::ParsedCertificate::CreateAndAddToVector( | 277 net::ParsedCertificate::CreateFromCertificateData( |
295 reinterpret_cast<const uint8_t*>(cert_der.data()), cert_der.size(), | 278 reinterpret_cast<const uint8_t*>(certs[0].data()), certs[0].size(), |
279 net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE, | |
280 GetCertParsingOptions())); | |
281 if (!target_cert) | |
282 return false; | |
283 | |
284 net::CertIssuerSourceStatic intermediate_cert_issuer_source; | |
285 for (size_t i = 1; i < certs.size(); ++i) { | |
eroman
2016/06/27 19:58:52
optional: How about starting at i=0 and handle the
mattm
2016/06/27 23:45:44
Done.
| |
286 scoped_refptr<net::ParsedCertificate> cert( | |
287 net::ParsedCertificate::CreateFromCertificateData( | |
288 reinterpret_cast<const uint8_t*>(certs[i].data()), certs[i].size(), | |
296 net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE, | 289 net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE, |
297 GetCertParsingOptions(), &input_chain)) { | 290 GetCertParsingOptions())); |
291 if (!cert) | |
298 return false; | 292 return false; |
299 } | 293 intermediate_cert_issuer_source.AddCert(cert); |
300 } | 294 } |
301 | 295 |
302 // Use a signature policy compatible with Cast's PKI. | 296 // Use a signature policy compatible with Cast's PKI. |
303 auto signature_policy = CreateCastSignaturePolicy(); | 297 auto signature_policy = CreateCastSignaturePolicy(); |
304 | 298 |
305 // Do RFC 5280 compatible certificate verification using the two Cast | 299 // Do RFC 5280 compatible certificate verification using the two Cast |
eroman
2016/06/27 19:58:52
Should this comment be expanded to mention path bu
mattm
2016/06/27 23:45:45
Done.
| |
306 // trust anchors and Cast signature policy. | 300 // trust anchors and Cast signature policy. |
307 if (!net::VerifyCertificateChain(input_chain, CastTrustStore::Get(), | 301 net::CertPathBuilder::Result result; |
308 signature_policy.get(), | 302 net::CertPathBuilder path_builder(target_cert.get(), &CastTrustStore::Get(), |
309 ConvertExplodedTime(time), nullptr)) { | 303 signature_policy.get(), |
304 ConvertExplodedTime(time), &result); | |
305 path_builder.AddCertIssuerSource(&intermediate_cert_issuer_source); | |
306 net::CompletionStatus rv = path_builder.Run(base::Closure()); | |
307 DCHECK_EQ(rv, net::CompletionStatus::SYNC); | |
308 if (!result.is_success()) | |
310 return false; | 309 return false; |
311 } | |
312 | 310 |
313 // Check properties of the leaf certificate (key usage, policy), and construct | 311 // Check properties of the leaf certificate (key usage, policy), and construct |
314 // a CertVerificationContext that uses its public key. | 312 // a CertVerificationContext that uses its public key. |
315 return CheckTargetCertificate(input_chain[0].get(), context, policy); | 313 return CheckTargetCertificate(target_cert.get(), context, policy); |
316 } | 314 } |
317 | 315 |
318 std::unique_ptr<CertVerificationContext> CertVerificationContextImplForTest( | 316 std::unique_ptr<CertVerificationContext> CertVerificationContextImplForTest( |
319 const base::StringPiece& spki) { | 317 const base::StringPiece& spki) { |
320 // Use a bogus CommonName, since this is just exposed for testing signature | 318 // Use a bogus CommonName, since this is just exposed for testing signature |
321 // verification by unittests. | 319 // verification by unittests. |
322 return base::WrapUnique( | 320 return base::WrapUnique( |
323 new CertVerificationContextImpl(net::der::Input(spki), "CommonName")); | 321 new CertVerificationContextImpl(net::der::Input(spki), "CommonName")); |
324 } | 322 } |
325 | 323 |
326 bool AddTrustAnchorForTest(const uint8_t* data, size_t length) { | 324 bool AddTrustAnchorForTest(const uint8_t* data, size_t length) { |
327 scoped_refptr<net::ParsedCertificate> anchor( | 325 scoped_refptr<net::ParsedCertificate> anchor( |
328 net::ParsedCertificate::CreateFromCertificateData( | 326 net::ParsedCertificate::CreateFromCertificateData( |
329 data, length, net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE, | 327 data, length, net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE, |
330 GetCertParsingOptions())); | 328 GetCertParsingOptions())); |
331 if (!anchor) | 329 if (!anchor) |
332 return false; | 330 return false; |
333 CastTrustStore::Get().AddTrustedCertificate(std::move(anchor)); | 331 CastTrustStore::Get().AddTrustedCertificate(std::move(anchor)); |
334 return true; | 332 return true; |
335 } | 333 } |
336 | 334 |
337 } // namespace cast_certificate | 335 } // namespace cast_certificate |
OLD | NEW |