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 "extensions/common/cast/cast_cert_validator.h" | 5 #include "extensions/common/cast/cast_cert_validator.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <utility> | 10 #include <utility> |
11 | 11 |
| 12 #include "base/memory/singleton.h" |
12 #include "net/cert/internal/certificate_policies.h" | 13 #include "net/cert/internal/certificate_policies.h" |
13 #include "net/cert/internal/extended_key_usage.h" | 14 #include "net/cert/internal/extended_key_usage.h" |
14 #include "net/cert/internal/parse_certificate.h" | 15 #include "net/cert/internal/parse_certificate.h" |
15 #include "net/cert/internal/parse_name.h" | 16 #include "net/cert/internal/parse_name.h" |
16 #include "net/cert/internal/signature_algorithm.h" | 17 #include "net/cert/internal/signature_algorithm.h" |
17 #include "net/cert/internal/signature_policy.h" | 18 #include "net/cert/internal/signature_policy.h" |
18 #include "net/cert/internal/verify_certificate_chain.h" | 19 #include "net/cert/internal/verify_certificate_chain.h" |
19 #include "net/cert/internal/verify_signed_data.h" | 20 #include "net/cert/internal/verify_signed_data.h" |
20 #include "net/der/input.h" | 21 #include "net/der/input.h" |
21 | 22 |
22 namespace extensions { | 23 namespace extensions { |
23 namespace api { | 24 namespace api { |
24 namespace cast_crypto { | 25 namespace cast_crypto { |
25 namespace { | 26 namespace { |
26 | 27 |
27 // ------------------------------------------------------------------------- | 28 // ------------------------------------------------------------------------- |
28 // Cast trust anchors. | 29 // Cast trust anchors. |
29 // ------------------------------------------------------------------------- | 30 // ------------------------------------------------------------------------- |
30 | 31 |
31 // There are two trusted roots for Cast certificate chains: | 32 // There are two trusted roots for Cast certificate chains: |
32 // | 33 // |
33 // (1) CN=Cast Root CA | 34 // (1) CN=Cast Root CA (kCastRootCaDer) |
34 // (2) CN=Eureka Root CA | 35 // (2) CN=Eureka Root CA (kEurekaRootCaDer) |
35 // | 36 // |
36 // Note that only the subject/spki are saved here, not the full certificate. | 37 // These constants are defined by the files included next: |
37 // See the TODO in CreateCastTrustStore(). | |
38 | 38 |
39 unsigned char kCastRootCaSubjectDer[119] = { | 39 #include "extensions/common/cast/cast_root_ca_cert_der-inc.h" |
40 0x30, 0x75, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, | 40 #include "extensions/common/cast/eureka_root_ca_der-inc.h" |
41 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, | 41 |
42 0x0C, 0x0A, 0x43, 0x61, 0x6C, 0x69, 0x66, 0x6F, 0x72, 0x6E, 0x69, 0x61, | 42 // Singleton for the Cast trust store. |
43 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x0D, 0x4D, | 43 class CastTrustStore { |
44 0x6F, 0x75, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x20, 0x56, 0x69, 0x65, 0x77, | 44 public: |
45 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0A, 0x47, | 45 static CastTrustStore* GetInstance() { |
46 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x0D, 0x30, | 46 return base::Singleton<CastTrustStore, |
47 0x0B, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x04, 0x43, 0x61, 0x73, 0x74, | 47 base::LeakySingletonTraits<CastTrustStore>>::get(); |
48 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0C, 0x43, | 48 } |
49 0x61, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, | 49 |
| 50 static net::TrustStore& Get() { return GetInstance()->store_; } |
| 51 |
| 52 private: |
| 53 friend struct base::DefaultSingletonTraits<CastTrustStore>; |
| 54 |
| 55 CastTrustStore() { |
| 56 // Initialize the trust store with two root certificates. |
| 57 CHECK(store_.AddTrustedCertificateWithoutCopying(kCastRootCaDer, |
| 58 sizeof(kCastRootCaDer))); |
| 59 CHECK(store_.AddTrustedCertificateWithoutCopying(kEurekaRootCaDer, |
| 60 sizeof(kEurekaRootCaDer))); |
| 61 } |
| 62 |
| 63 net::TrustStore store_; |
| 64 DISALLOW_COPY_AND_ASSIGN(CastTrustStore); |
50 }; | 65 }; |
51 | 66 |
52 unsigned char kCastRootCaSpkiDer[294] = { | |
53 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, | |
54 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, | |
55 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBA, 0xD9, 0x65, | |
56 0x9D, 0xDA, 0x39, 0xD3, 0xC1, 0x77, 0xF6, 0xD4, 0xD0, 0xAE, 0x8F, 0x58, | |
57 0x08, 0x68, 0x39, 0x4A, 0x95, 0xED, 0x70, 0xCF, 0xFD, 0x79, 0x08, 0xA9, | |
58 0xAA, 0xE5, 0xE9, 0xB8, 0xA7, 0x2D, 0xA0, 0x67, 0x47, 0x8A, 0x9E, 0xC9, | |
59 0xCF, 0x70, 0xB3, 0x05, 0x87, 0x69, 0x11, 0xEC, 0x70, 0x98, 0x97, 0xC3, | |
60 0xE6, 0xC3, 0xC3, 0xEB, 0xBD, 0xC6, 0xB0, 0x3D, 0xFC, 0x4F, 0xC1, 0x5E, | |
61 0x38, 0x9F, 0xDA, 0xCF, 0x73, 0x30, 0x06, 0x5B, 0x79, 0x37, 0xC1, 0x5E, | |
62 0x8C, 0x87, 0x47, 0x94, 0x9A, 0x41, 0x92, 0x2A, 0xD6, 0x95, 0xC4, 0x71, | |
63 0x5C, 0x27, 0x5D, 0x08, 0xB1, 0x80, 0xC6, 0x92, 0xBD, 0x1B, 0xE3, 0x41, | |
64 0x97, 0xA1, 0xEC, 0x75, 0x9F, 0x55, 0x9E, 0x3E, 0x9F, 0x8F, 0x1C, 0xC7, | |
65 0x65, 0x64, 0x07, 0xD3, 0xB3, 0x96, 0xA1, 0x04, 0x9F, 0x91, 0xC4, 0xDE, | |
66 0x0A, 0x7B, 0x6C, 0xD9, 0xC8, 0xC0, 0x78, 0x31, 0xA0, 0x19, 0x42, 0xA9, | |
67 0xE8, 0x83, 0xE3, 0xCE, 0xFC, 0xF1, 0xCE, 0xC2, 0x2E, 0x24, 0x46, 0x95, | |
68 0x09, 0x19, 0xCA, 0xC0, 0x46, 0xB2, 0xE5, 0x01, 0xBA, 0xD7, 0x4F, 0xF3, | |
69 0xBF, 0xF6, 0x69, 0xAD, 0x99, 0x04, 0xFA, 0xA0, 0x07, 0x39, 0x0E, 0xE6, | |
70 0xDF, 0x51, 0x47, 0x07, 0xC0, 0xE4, 0xA9, 0x5C, 0x4B, 0x94, 0xC5, 0x2F, | |
71 0xB3, 0xA0, 0x30, 0x7F, 0xE7, 0x95, 0x6B, 0xB2, 0xAF, 0x32, 0x0D, 0xF1, | |
72 0x8C, 0xD5, 0x6D, 0xCB, 0x7B, 0x47, 0xA7, 0x08, 0xAB, 0xCB, 0x27, 0xA3, | |
73 0x4D, 0xCF, 0x4A, 0x5A, 0xF1, 0x05, 0xD1, 0xF8, 0x62, 0xC5, 0x10, 0x2A, | |
74 0x74, 0x69, 0xAA, 0xE6, 0x4B, 0x96, 0xFB, 0x9B, 0xD8, 0x63, 0xE4, 0x58, | |
75 0x66, 0xD3, 0xAD, 0x8A, 0x6E, 0xFF, 0x7B, 0x5E, 0xF9, 0xA5, 0x56, 0x1E, | |
76 0x2D, 0x82, 0x31, 0x5B, 0xF0, 0xE2, 0x24, 0xE6, 0x41, 0x4A, 0x1F, 0xAE, | |
77 0x13, 0x02, 0x03, 0x01, 0x00, 0x01, | |
78 }; | |
79 | |
80 unsigned char kEurekaRootCaSubjectDer[126] = { | |
81 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, | |
82 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, | |
83 0x0C, 0x0A, 0x43, 0x61, 0x6C, 0x69, 0x66, 0x6F, 0x72, 0x6E, 0x69, 0x61, | |
84 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x0D, 0x4D, | |
85 0x6F, 0x75, 0x6E, 0x74, 0x61, 0x69, 0x6E, 0x20, 0x56, 0x69, 0x65, 0x77, | |
86 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0A, 0x47, | |
87 0x6F, 0x6F, 0x67, 0x6C, 0x65, 0x20, 0x49, 0x6E, 0x63, 0x31, 0x12, 0x30, | |
88 0x10, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x09, 0x47, 0x6F, 0x6F, 0x67, | |
89 0x6C, 0x65, 0x20, 0x54, 0x56, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, | |
90 0x04, 0x03, 0x0C, 0x0E, 0x45, 0x75, 0x72, 0x65, 0x6B, 0x61, 0x20, 0x52, | |
91 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x41, | |
92 }; | |
93 | |
94 unsigned char kEurekaRootCaSpkiDer[294] = { | |
95 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, | |
96 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, | |
97 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB9, 0x11, 0xD0, | |
98 0xEA, 0x12, 0xDC, 0x32, 0xE1, 0xDF, 0x5C, 0x33, 0x6B, 0x19, 0x73, 0x1D, | |
99 0x9D, 0x9E, 0xD0, 0x39, 0x76, 0xBF, 0xA5, 0x84, 0x09, 0xA6, 0xFD, 0x6E, | |
100 0x6D, 0xE9, 0xDC, 0x8F, 0x36, 0x4E, 0xE9, 0x88, 0x02, 0xBD, 0x9F, 0xF4, | |
101 0xE8, 0x44, 0xFD, 0x4C, 0xF5, 0x9A, 0x02, 0x56, 0x6A, 0x47, 0x2A, 0x63, | |
102 0x6C, 0x58, 0x45, 0xCC, 0x7C, 0x66, 0x24, 0xDC, 0x79, 0x79, 0xC3, 0x2A, | |
103 0xA4, 0xB2, 0x8B, 0xA0, 0xF7, 0xA2, 0xB5, 0xCD, 0x06, 0x7E, 0xDB, 0xBE, | |
104 0xEC, 0x0C, 0x86, 0xF2, 0x0D, 0x24, 0x60, 0x74, 0x84, 0xCA, 0x29, 0x23, | |
105 0x84, 0x02, 0xD8, 0xA7, 0xED, 0x3B, 0xF1, 0xEC, 0x26, 0x47, 0x54, 0xE3, | |
106 0xB1, 0x2D, 0xE6, 0x64, 0x0F, 0xF6, 0x72, 0xC5, 0xE9, 0x98, 0x52, 0x17, | |
107 0xC0, 0xFC, 0xF2, 0x2C, 0x20, 0xC8, 0x40, 0xF8, 0x47, 0xC9, 0x32, 0x9E, | |
108 0x3B, 0x97, 0xB1, 0x8B, 0xF5, 0x98, 0x24, 0x70, 0x63, 0x66, 0x19, 0xC1, | |
109 0x52, 0xE8, 0x04, 0x05, 0x3D, 0x5F, 0x8D, 0xBC, 0xD8, 0x4B, 0xAF, 0x77, | |
110 0x98, 0x6F, 0x1F, 0x78, 0xD1, 0xB6, 0x50, 0x27, 0x4D, 0xE4, 0xEC, 0x14, | |
111 0x69, 0x67, 0x1F, 0x58, 0xAF, 0xA9, 0xA0, 0x11, 0x26, 0x3C, 0x94, 0x32, | |
112 0x07, 0x7F, 0xD7, 0xE9, 0x69, 0x1F, 0xAE, 0x3F, 0x4F, 0x63, 0x8A, 0x8F, | |
113 0x89, 0xD6, 0xF2, 0x19, 0x78, 0x5C, 0x21, 0x8E, 0xB1, 0xB6, 0x57, 0xD8, | |
114 0xC0, 0xE1, 0xEE, 0x7D, 0x6E, 0xDD, 0xF1, 0x3A, 0x0A, 0x6A, 0xF1, 0xBA, | |
115 0xFF, 0xF9, 0x83, 0x2F, 0xDC, 0xB5, 0xA4, 0x20, 0x17, 0x63, 0x36, 0xEF, | |
116 0xC8, 0x62, 0x19, 0xCC, 0x56, 0xCE, 0xB2, 0xEA, 0x31, 0x89, 0x4B, 0x78, | |
117 0x58, 0xC1, 0xBF, 0x03, 0x13, 0x99, 0xE0, 0x12, 0xF2, 0x88, 0xAA, 0x9B, | |
118 0x94, 0xDA, 0xDD, 0x76, 0x79, 0x17, 0x1E, 0x34, 0xD1, 0x0A, 0xC4, 0x07, | |
119 0x45, 0x02, 0x03, 0x01, 0x00, 0x01, | |
120 }; | |
121 | |
122 // Helper function that creates and initializes a TrustAnchor struct given | |
123 // arrays for the subject's DER and the SPKI's DER. | |
124 template <size_t SubjectSize, size_t SpkiSize> | |
125 net::TrustAnchor CreateTrustAnchor(const uint8_t (&subject)[SubjectSize], | |
126 const uint8_t (&spki)[SpkiSize]) { | |
127 net::TrustAnchor anchor; | |
128 anchor.name = std::string(subject, subject + SubjectSize); | |
129 anchor.spki = std::string(spki, spki + SpkiSize); | |
130 return anchor; | |
131 } | |
132 | |
133 // Creates a trust store with the two Cast roots. | |
134 // | |
135 // TODO(eroman): The root certificates themselves are not included in the trust | |
136 // store (just their subject/SPKI). The problem with this approach is any | |
137 // restrictions encoded in their (like path length, or policy) are not known | |
138 // when verifying, and hence not enforced. | |
139 net::TrustStore CreateCastTrustStore() { | |
140 net::TrustStore store; | |
141 store.anchors.push_back( | |
142 CreateTrustAnchor(kEurekaRootCaSubjectDer, kEurekaRootCaSpkiDer)); | |
143 store.anchors.push_back( | |
144 CreateTrustAnchor(kCastRootCaSubjectDer, kCastRootCaSpkiDer)); | |
145 return store; | |
146 } | |
147 | |
148 using ExtensionsMap = std::map<net::der::Input, net::ParsedExtension>; | 67 using ExtensionsMap = std::map<net::der::Input, net::ParsedExtension>; |
149 | 68 |
150 // Helper that looks up an extension by OID given a map of extensions. | 69 // Helper that looks up an extension by OID given a map of extensions. |
151 bool GetExtensionValue(const ExtensionsMap& extensions, | 70 bool GetExtensionValue(const ExtensionsMap& extensions, |
152 const net::der::Input& oid, | 71 const net::der::Input& oid, |
153 net::der::Input* value) { | 72 net::der::Input* value) { |
154 auto it = extensions.find(oid); | 73 auto it = extensions.find(oid); |
155 if (it == extensions.end()) | 74 if (it == extensions.end()) |
156 return false; | 75 return false; |
157 *value = it->second.value; | 76 *value = it->second.value; |
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 result.seconds = exploded.second; | 252 result.seconds = exploded.second; |
334 return result; | 253 return result; |
335 } | 254 } |
336 | 255 |
337 } // namespace | 256 } // namespace |
338 | 257 |
339 bool VerifyDeviceCert(const std::vector<std::string>& certs, | 258 bool VerifyDeviceCert(const std::vector<std::string>& certs, |
340 const base::Time::Exploded& time, | 259 const base::Time::Exploded& time, |
341 scoped_ptr<CertVerificationContext>* context, | 260 scoped_ptr<CertVerificationContext>* context, |
342 CastDeviceCertPolicy* policy) { | 261 CastDeviceCertPolicy* policy) { |
343 // Initialize the trust store used for verifying Cast | |
344 // device certificates. | |
345 // | |
346 // Performance: This code is re-building a TrustStore object each | |
347 // time a chain needs to be verified rather than caching it, to | |
348 // avoid memory bloat. | |
349 auto trust_store = CreateCastTrustStore(); | |
350 | |
351 // The underlying verification function expects a sequence of | 262 // The underlying verification function expects a sequence of |
352 // der::Input, so wrap the data in it (cheap). | 263 // der::Input, so wrap the data in it (cheap). |
353 std::vector<net::der::Input> input_chain; | 264 std::vector<net::der::Input> input_chain; |
354 for (const auto& cert : certs) | 265 for (const auto& cert : certs) |
355 input_chain.push_back(net::der::Input(&cert)); | 266 input_chain.push_back(net::der::Input(&cert)); |
356 | 267 |
357 // Use a signature policy compatible with Cast's PKI. | 268 // Use a signature policy compatible with Cast's PKI. |
358 auto signature_policy = CreateCastSignaturePolicy(); | 269 auto signature_policy = CreateCastSignaturePolicy(); |
359 | 270 |
360 // Do RFC 5280 compatible certificate verification using the two Cast | 271 // Do RFC 5280 compatible certificate verification using the two Cast |
361 // trust anchors and Cast signature policy. | 272 // trust anchors and Cast signature policy. |
362 if (!net::VerifyCertificateChain(input_chain, trust_store, | 273 if (!net::VerifyCertificateChain(input_chain, CastTrustStore::Get(), |
363 signature_policy.get(), | 274 signature_policy.get(), |
364 ConvertExplodedTime(time))) { | 275 ConvertExplodedTime(time))) { |
365 return false; | 276 return false; |
366 } | 277 } |
367 | 278 |
368 // Check properties of the leaf certificate (key usage, policy), and construct | 279 // Check properties of the leaf certificate (key usage, policy), and construct |
369 // a CertVerificationContext that uses its public key. | 280 // a CertVerificationContext that uses its public key. |
370 return CheckTargetCertificate(input_chain[0], context, policy); | 281 return CheckTargetCertificate(input_chain[0], context, policy); |
371 } | 282 } |
372 | 283 |
373 scoped_ptr<CertVerificationContext> CertVerificationContextImplForTest( | 284 scoped_ptr<CertVerificationContext> CertVerificationContextImplForTest( |
374 const base::StringPiece& spki) { | 285 const base::StringPiece& spki) { |
375 // Use a bogus CommonName, since this is just exposed for testing signature | 286 // Use a bogus CommonName, since this is just exposed for testing signature |
376 // verification by unittests. | 287 // verification by unittests. |
377 return make_scoped_ptr( | 288 return make_scoped_ptr( |
378 new CertVerificationContextImpl(net::der::Input(spki), "CommonName")); | 289 new CertVerificationContextImpl(net::der::Input(spki), "CommonName")); |
379 } | 290 } |
380 | 291 |
381 } // namespace cast_crypto | 292 } // namespace cast_crypto |
382 } // namespace api | 293 } // namespace api |
383 } // namespace extensions | 294 } // namespace extensions |
OLD | NEW |