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

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

Issue 1976433002: Add new ParsedCertificate class, move TrustStore to own file. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cert-parsing-remove-old-parsedcertificate
Patch Set: more comments Created 4 years, 7 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
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/certificate_policies.h" 16 #include "net/cert/internal/certificate_policies.h"
17 #include "net/cert/internal/extended_key_usage.h" 17 #include "net/cert/internal/extended_key_usage.h"
18 #include "net/cert/internal/parse_certificate.h" 18 #include "net/cert/internal/parse_certificate.h"
19 #include "net/cert/internal/parse_name.h" 19 #include "net/cert/internal/parse_name.h"
20 #include "net/cert/internal/parsed_certificate.h"
20 #include "net/cert/internal/signature_algorithm.h" 21 #include "net/cert/internal/signature_algorithm.h"
21 #include "net/cert/internal/signature_policy.h" 22 #include "net/cert/internal/signature_policy.h"
23 #include "net/cert/internal/trust_store.h"
22 #include "net/cert/internal/verify_certificate_chain.h" 24 #include "net/cert/internal/verify_certificate_chain.h"
23 #include "net/cert/internal/verify_signed_data.h" 25 #include "net/cert/internal/verify_signed_data.h"
24 #include "net/der/input.h" 26 #include "net/der/input.h"
25 27
26 namespace cast_certificate { 28 namespace cast_certificate {
27 namespace { 29 namespace {
28 30
29 // ------------------------------------------------------------------------- 31 // -------------------------------------------------------------------------
30 // Cast trust anchors. 32 // Cast trust anchors.
31 // ------------------------------------------------------------------------- 33 // -------------------------------------------------------------------------
(...skipping 16 matching lines...) Expand all
48 base::LeakySingletonTraits<CastTrustStore>>::get(); 50 base::LeakySingletonTraits<CastTrustStore>>::get();
49 } 51 }
50 52
51 static net::TrustStore& Get() { return GetInstance()->store_; } 53 static net::TrustStore& Get() { return GetInstance()->store_; }
52 54
53 private: 55 private:
54 friend struct base::DefaultSingletonTraits<CastTrustStore>; 56 friend struct base::DefaultSingletonTraits<CastTrustStore>;
55 57
56 CastTrustStore() { 58 CastTrustStore() {
57 // Initialize the trust store with two root certificates. 59 // Initialize the trust store with two root certificates.
58 CHECK(store_.AddTrustedCertificateWithoutCopying(kCastRootCaDer, 60 scoped_refptr<net::ParsedCertificate> root;
59 sizeof(kCastRootCaDer))); 61 CHECK(root = net::ParsedCertificate::CreateFromCertificateData(
eroman 2016/05/31 18:28:57 nit: I prefer the style where these are separate l
mattm 2016/05/31 19:48:09 Done.
60 CHECK(store_.AddTrustedCertificateWithoutCopying(kEurekaRootCaDer, 62 kCastRootCaDer, sizeof(kCastRootCaDer),
61 sizeof(kEurekaRootCaDer))); 63 net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE));
64 store_.AddTrustedCertificate(std::move(root));
65 CHECK(root = net::ParsedCertificate::CreateFromCertificateData(
66 kEurekaRootCaDer, sizeof(kEurekaRootCaDer),
67 net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE));
68 store_.AddTrustedCertificate(std::move(root));
62 } 69 }
63 70
64 net::TrustStore store_; 71 net::TrustStore store_;
65 DISALLOW_COPY_AND_ASSIGN(CastTrustStore); 72 DISALLOW_COPY_AND_ASSIGN(CastTrustStore);
66 }; 73 };
67 74
68 using ExtensionsMap = std::map<net::der::Input, net::ParsedExtension>; 75 using ExtensionsMap = std::map<net::der::Input, net::ParsedExtension>;
69 76
70 // Helper that looks up an extension by OID given a map of extensions. 77 // Helper that looks up an extension by OID given a map of extensions.
71 bool GetExtensionValue(const ExtensionsMap& extensions, 78 bool GetExtensionValue(const ExtensionsMap& extensions,
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 for (const auto& oid : ekus) { 167 for (const auto& oid : ekus) {
161 if (oid == net::ClientAuth()) 168 if (oid == net::ClientAuth())
162 return true; 169 return true;
163 } 170 }
164 return false; 171 return false;
165 } 172 }
166 173
167 // Checks properties on the target certificate. 174 // Checks properties on the target certificate.
168 // 175 //
169 // * The Key Usage must include Digital Signature 176 // * The Key Usage must include Digital Signature
170 // * THe Extended Key Usage must includ TLS Client Auth 177 // * THe Extended Key Usage must includ TLS Client Auth
eroman 2016/05/31 18:28:57 optional: While here can fix my "THe" typo, and "i
mattm 2016/05/31 19:48:09 Done.
171 // * May have the policy 1.3.6.1.4.1.11129.2.5.2 to indicate it 178 // * May have the policy 1.3.6.1.4.1.11129.2.5.2 to indicate it
172 // is an audio-only device. 179 // is an audio-only device.
173 WARN_UNUSED_RESULT bool CheckTargetCertificate( 180 WARN_UNUSED_RESULT bool CheckTargetCertificate(
174 const net::der::Input& cert_der, 181 const net::ParsedCertificate* cert,
175 std::unique_ptr<CertVerificationContext>* context, 182 std::unique_ptr<CertVerificationContext>* context,
176 CastDeviceCertPolicy* policy) { 183 CastDeviceCertPolicy* policy) {
177 // TODO(eroman): Simplify this. The certificate chain verification
178 // function already parses this stuff, awkward to re-do it here.
179
180 net::der::Input tbs_certificate_tlv;
181 net::der::Input signature_algorithm_tlv;
182 net::der::BitString signature_value;
183 if (!net::ParseCertificate(cert_der, &tbs_certificate_tlv,
184 &signature_algorithm_tlv, &signature_value))
185 return false;
186
187 net::ParsedTbsCertificate tbs;
188 if (!net::ParseTbsCertificate(tbs_certificate_tlv, &tbs))
189 return false;
190
191 // Get the extensions.
192 if (!tbs.has_extensions)
193 return false;
194 ExtensionsMap extensions;
195 if (!net::ParseExtensions(tbs.extensions_tlv, &extensions))
196 return false;
197
198 net::der::Input extension_value;
199
200 // Get the Key Usage extension. 184 // Get the Key Usage extension.
201 if (!GetExtensionValue(extensions, net::KeyUsageOid(), &extension_value)) 185 if (!cert->has_key_usage())
202 return false;
203 net::der::BitString key_usage;
204 if (!net::ParseKeyUsage(extension_value, &key_usage))
205 return false; 186 return false;
206 187
207 // Ensure Key Usage contains digitalSignature. 188 // Ensure Key Usage contains digitalSignature.
208 if (!key_usage.AssertsBit(net::KEY_USAGE_BIT_DIGITAL_SIGNATURE)) 189 if (!cert->key_usage().AssertsBit(net::KEY_USAGE_BIT_DIGITAL_SIGNATURE))
209 return false; 190 return false;
210 191
211 // Get the Extended Key Usage extension. 192 // Get the Extended Key Usage extension.
212 if (!GetExtensionValue(extensions, net::ExtKeyUsageOid(), &extension_value)) 193 net::der::Input extension_value;
194 if (!GetExtensionValue(cert->unparsed_extensions(), net::ExtKeyUsageOid(),
195 &extension_value)) {
213 return false; 196 return false;
197 }
214 std::vector<net::der::Input> ekus; 198 std::vector<net::der::Input> ekus;
215 if (!net::ParseEKUExtension(extension_value, &ekus)) 199 if (!net::ParseEKUExtension(extension_value, &ekus))
216 return false; 200 return false;
217 201
218 // Ensure Extended Key Usage contains client auth. 202 // Ensure Extended Key Usage contains client auth.
219 if (!HasClientAuth(ekus)) 203 if (!HasClientAuth(ekus))
220 return false; 204 return false;
221 205
222 // Check for an optional audio-only policy extension. 206 // Check for an optional audio-only policy extension.
223 *policy = CastDeviceCertPolicy::NONE; 207 *policy = CastDeviceCertPolicy::NONE;
224 if (GetExtensionValue(extensions, net::CertificatePoliciesOid(), 208 if (GetExtensionValue(cert->unparsed_extensions(),
225 &extension_value)) { 209 net::CertificatePoliciesOid(), &extension_value)) {
226 std::vector<net::der::Input> policies; 210 std::vector<net::der::Input> policies;
227 if (!net::ParseCertificatePoliciesExtension(extension_value, &policies)) 211 if (!net::ParseCertificatePoliciesExtension(extension_value, &policies))
228 return false; 212 return false;
229 213
230 // Look for an audio-only policy. Disregard any other policy found. 214 // Look for an audio-only policy. Disregard any other policy found.
231 if (std::find(policies.begin(), policies.end(), AudioOnlyPolicyOid()) != 215 if (std::find(policies.begin(), policies.end(), AudioOnlyPolicyOid()) !=
232 policies.end()) { 216 policies.end()) {
233 *policy = CastDeviceCertPolicy::AUDIO_ONLY; 217 *policy = CastDeviceCertPolicy::AUDIO_ONLY;
234 } 218 }
235 } 219 }
236 220
237 // Get the Common Name for the certificate. 221 // Get the Common Name for the certificate.
238 std::string common_name; 222 std::string common_name;
239 if (!GetCommonNameFromSubject(tbs.subject_tlv, &common_name)) 223 if (!GetCommonNameFromSubject(cert->tbs().subject_tlv, &common_name))
240 return false; 224 return false;
241 225
242 context->reset(new CertVerificationContextImpl(tbs.spki_tlv, common_name)); 226 context->reset(
227 new CertVerificationContextImpl(cert->tbs().spki_tlv, common_name));
243 return true; 228 return true;
244 } 229 }
245 230
246 // Converts a base::Time::Exploded to a net::der::GeneralizedTime. 231 // Converts a base::Time::Exploded to a net::der::GeneralizedTime.
247 net::der::GeneralizedTime ConvertExplodedTime( 232 net::der::GeneralizedTime ConvertExplodedTime(
248 const base::Time::Exploded& exploded) { 233 const base::Time::Exploded& exploded) {
249 net::der::GeneralizedTime result; 234 net::der::GeneralizedTime result;
250 result.year = exploded.year; 235 result.year = exploded.year;
251 result.month = exploded.month; 236 result.month = exploded.month;
252 result.day = exploded.day_of_month; 237 result.day = exploded.day_of_month;
253 result.hours = exploded.hour; 238 result.hours = exploded.hour;
254 result.minutes = exploded.minute; 239 result.minutes = exploded.minute;
255 result.seconds = exploded.second; 240 result.seconds = exploded.second;
256 return result; 241 return result;
257 } 242 }
258 243
259 } // namespace 244 } // namespace
260 245
261 bool VerifyDeviceCert(const std::vector<std::string>& certs, 246 bool VerifyDeviceCert(const std::vector<std::string>& certs,
262 const base::Time::Exploded& time, 247 const base::Time::Exploded& time,
263 std::unique_ptr<CertVerificationContext>* context, 248 std::unique_ptr<CertVerificationContext>* context,
264 CastDeviceCertPolicy* policy) { 249 CastDeviceCertPolicy* policy) {
265 // The underlying verification function expects a sequence of 250 // The underlying verification function expects a sequence of
266 // der::Input, so wrap the data in it (cheap). 251 // ParsedCertificate.
267 std::vector<net::der::Input> input_chain; 252 std::vector<scoped_refptr<net::ParsedCertificate>> input_chain;
268 for (const auto& cert : certs) 253 for (const auto& cert_der : certs) {
269 input_chain.push_back(net::der::Input(&cert)); 254 // No reference to the ParsedCertificate is kept past the end of this
eroman 2016/05/31 18:28:57 optional: You could also add weight to this by add
mattm 2016/05/31 19:48:09 Done.
255 // function, so using EXTERNAL_REFERENCE here is safe.
256 if (!net::ParsedCertificate::CreateAndAddToVector(
257 reinterpret_cast<const uint8_t*>(cert_der.data()), cert_der.size(),
258 net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE,
259 &input_chain)) {
260 return false;
261 }
262 }
270 263
271 // Use a signature policy compatible with Cast's PKI. 264 // Use a signature policy compatible with Cast's PKI.
272 auto signature_policy = CreateCastSignaturePolicy(); 265 auto signature_policy = CreateCastSignaturePolicy();
273 266
274 // Do RFC 5280 compatible certificate verification using the two Cast 267 // Do RFC 5280 compatible certificate verification using the two Cast
275 // trust anchors and Cast signature policy. 268 // trust anchors and Cast signature policy.
276 if (!net::VerifyCertificateChain(input_chain, CastTrustStore::Get(), 269 if (!net::VerifyCertificateChain(input_chain, CastTrustStore::Get(),
277 signature_policy.get(), 270 signature_policy.get(),
278 ConvertExplodedTime(time))) { 271 ConvertExplodedTime(time))) {
279 return false; 272 return false;
280 } 273 }
281 274
282 // Check properties of the leaf certificate (key usage, policy), and construct 275 // Check properties of the leaf certificate (key usage, policy), and construct
283 // a CertVerificationContext that uses its public key. 276 // a CertVerificationContext that uses its public key.
284 return CheckTargetCertificate(input_chain[0], context, policy); 277 return CheckTargetCertificate(input_chain[0].get(), context, policy);
285 } 278 }
286 279
287 std::unique_ptr<CertVerificationContext> CertVerificationContextImplForTest( 280 std::unique_ptr<CertVerificationContext> CertVerificationContextImplForTest(
288 const base::StringPiece& spki) { 281 const base::StringPiece& spki) {
289 // Use a bogus CommonName, since this is just exposed for testing signature 282 // Use a bogus CommonName, since this is just exposed for testing signature
290 // verification by unittests. 283 // verification by unittests.
291 return base::WrapUnique( 284 return base::WrapUnique(
292 new CertVerificationContextImpl(net::der::Input(spki), "CommonName")); 285 new CertVerificationContextImpl(net::der::Input(spki), "CommonName"));
293 } 286 }
294 287
295 bool AddTrustAnchorForTest(const uint8_t* data, size_t length) { 288 bool AddTrustAnchorForTest(const uint8_t* data, size_t length) {
296 return CastTrustStore::Get().AddTrustedCertificateWithoutCopying(data, 289 scoped_refptr<net::ParsedCertificate> anchor(
297 length); 290 net::ParsedCertificate::CreateFromCertificateData(
291 kCastRootCaDer, sizeof(kCastRootCaDer),
292 net::ParsedCertificate::DataSource::EXTERNAL_REFERENCE));
293 if (!anchor)
294 return false;
295 CastTrustStore::Get().AddTrustedCertificate(std::move(anchor));
296 return true;
298 } 297 }
299 298
300 } // namespace cast_certificate 299 } // namespace cast_certificate
OLDNEW
« no previous file with comments | « no previous file | net/cert/internal/parse_certificate.h » ('j') | net/cert/internal/parsed_certificate.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698