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

Side by Side Diff: net/cert/internal/verify_certificate_chain.cc

Issue 1969293002: Remove net::ParsedCertificate struct. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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
« no previous file with comments | « net/cert/internal/parse_ocsp_unittest.cc ('k') | net/cert/x509_util_openssl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "net/cert/internal/verify_certificate_chain.h" 5 #include "net/cert/internal/verify_certificate_chain.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "net/cert/internal/name_constraints.h" 10 #include "net/cert/internal/name_constraints.h"
11 #include "net/cert/internal/parse_certificate.h" 11 #include "net/cert/internal/parse_certificate.h"
12 #include "net/cert/internal/signature_algorithm.h" 12 #include "net/cert/internal/signature_algorithm.h"
13 #include "net/cert/internal/signature_policy.h" 13 #include "net/cert/internal/signature_policy.h"
14 #include "net/cert/internal/verify_name_match.h" 14 #include "net/cert/internal/verify_name_match.h"
15 #include "net/cert/internal/verify_signed_data.h" 15 #include "net/cert/internal/verify_signed_data.h"
16 #include "net/der/input.h" 16 #include "net/der/input.h"
17 #include "net/der/parser.h" 17 #include "net/der/parser.h"
18 18
19 namespace net { 19 namespace net {
20 20
21 namespace { 21 namespace {
22 22
23 // Map from OID to ParsedExtension. 23 // Map from OID to ParsedExtension.
24 using ExtensionsMap = std::map<der::Input, ParsedExtension>; 24 using ExtensionsMap = std::map<der::Input, ParsedExtension>;
25 25
26 // Describes all parsed properties of a certificate that are relevant for 26 // Describes all parsed properties of a certificate that are relevant for
27 // certificate verification. 27 // certificate verification.
28 struct FullyParsedCert { 28 struct FullyParsedCert {
29 ParsedCertificate cert; 29 der::Input tbs_certificate_tlv;
30 der::Input signature_algorithm_tlv;
31 der::BitString signature_value;
30 ParsedTbsCertificate tbs; 32 ParsedTbsCertificate tbs;
31 33
32 std::unique_ptr<SignatureAlgorithm> signature_algorithm; 34 std::unique_ptr<SignatureAlgorithm> signature_algorithm;
33 35
34 // Standard extensions that were parsed. 36 // Standard extensions that were parsed.
35 bool has_basic_constraints = false; 37 bool has_basic_constraints = false;
36 ParsedBasicConstraints basic_constraints; 38 ParsedBasicConstraints basic_constraints;
37 39
38 bool has_key_usage = false; 40 bool has_key_usage = false;
39 der::BitString key_usage; 41 der::BitString key_usage;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 der::Input* value) { 79 der::Input* value) {
78 der::Parser parser(tlv); 80 der::Parser parser(tlv);
79 return parser.ReadTag(der::kSequence, value) && !parser.HasMore(); 81 return parser.ReadTag(der::kSequence, value) && !parser.HasMore();
80 } 82 }
81 83
82 // Parses an X.509 Certificate fully (including the TBSCertificate and 84 // Parses an X.509 Certificate fully (including the TBSCertificate and
83 // standard extensions), saving all the properties to |out_|. 85 // standard extensions), saving all the properties to |out_|.
84 WARN_UNUSED_RESULT bool FullyParseCertificate(const der::Input& cert_tlv, 86 WARN_UNUSED_RESULT bool FullyParseCertificate(const der::Input& cert_tlv,
85 FullyParsedCert* out) { 87 FullyParsedCert* out) {
86 // Parse the outer Certificate. 88 // Parse the outer Certificate.
87 if (!ParseCertificate(cert_tlv, &out->cert)) 89 if (!ParseCertificate(cert_tlv, &out->tbs_certificate_tlv,
90 &out->signature_algorithm_tlv, &out->signature_value))
88 return false; 91 return false;
89 92
90 // Parse the signature algorithm contained in the Certificate (there is 93 // Parse the signature algorithm contained in the Certificate (there is
91 // another one in the TBSCertificate, which is checked later by 94 // another one in the TBSCertificate, which is checked later by
92 // VerifySignatureAlgorithmsMatch) 95 // VerifySignatureAlgorithmsMatch)
93 out->signature_algorithm = 96 out->signature_algorithm =
94 SignatureAlgorithm::CreateFromDer(out->cert.signature_algorithm_tlv); 97 SignatureAlgorithm::CreateFromDer(out->signature_algorithm_tlv);
95 if (!out->signature_algorithm) 98 if (!out->signature_algorithm)
96 return false; 99 return false;
97 100
98 // Parse the TBSCertificate. 101 // Parse the TBSCertificate.
99 if (!ParseTbsCertificate(out->cert.tbs_certificate_tlv, &out->tbs)) 102 if (!ParseTbsCertificate(out->tbs_certificate_tlv, &out->tbs))
100 return false; 103 return false;
101 104
102 // Reset state relating to extensions (which may not get overwritten). This is 105 // Reset state relating to extensions (which may not get overwritten). This is
103 // just a precaution, since in practice |out| will already be default 106 // just a precaution, since in practice |out| will already be default
104 // initialize. 107 // initialize.
105 out->has_basic_constraints = false; 108 out->has_basic_constraints = false;
106 out->has_key_usage = false; 109 out->has_key_usage = false;
107 out->unconsumed_extensions.clear(); 110 out->unconsumed_extensions.clear();
108 out->subject_alt_names.reset(); 111 out->subject_alt_names.reset();
109 out->has_name_constraints = false; 112 out->has_name_constraints = false;
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 // 240 //
238 // The spec is not explicit about what "the same algorithm identifier" means. 241 // The spec is not explicit about what "the same algorithm identifier" means.
239 // Our interpretation is that the two DER-encoded fields must be byte-for-byte 242 // Our interpretation is that the two DER-encoded fields must be byte-for-byte
240 // identical. 243 // identical.
241 // 244 //
242 // In practice however there are certificates which use different encodings for 245 // In practice however there are certificates which use different encodings for
243 // specifying RSA with SHA1 (different OIDs). This is special-cased for 246 // specifying RSA with SHA1 (different OIDs). This is special-cased for
244 // compatibility sake. 247 // compatibility sake.
245 WARN_UNUSED_RESULT bool VerifySignatureAlgorithmsMatch( 248 WARN_UNUSED_RESULT bool VerifySignatureAlgorithmsMatch(
246 const FullyParsedCert& cert) { 249 const FullyParsedCert& cert) {
247 const der::Input& alg1_tlv = cert.cert.signature_algorithm_tlv; 250 const der::Input& alg1_tlv = cert.signature_algorithm_tlv;
248 const der::Input& alg2_tlv = cert.tbs.signature_algorithm_tlv; 251 const der::Input& alg2_tlv = cert.tbs.signature_algorithm_tlv;
249 252
250 // Ensure that the two DER-encoded signature algorithms are byte-for-byte 253 // Ensure that the two DER-encoded signature algorithms are byte-for-byte
251 // equal, but make a compatibility concession for RSA with SHA1. 254 // equal, but make a compatibility concession for RSA with SHA1.
252 return alg1_tlv == alg2_tlv || (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) && 255 return alg1_tlv == alg2_tlv || (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) &&
253 IsRsaWithSha1SignatureAlgorithm(alg2_tlv)); 256 IsRsaWithSha1SignatureAlgorithm(alg2_tlv));
254 } 257 }
255 258
256 // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate 259 // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate
257 // Processing" procedure. 260 // Processing" procedure.
(...skipping 14 matching lines...) Expand all
272 name_constraints_list) { 275 name_constraints_list) {
273 // Check that the signature algorithms in Certificate vs TBSCertificate 276 // Check that the signature algorithms in Certificate vs TBSCertificate
274 // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by 277 // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by
275 // sections 4.1.1.2 and 4.1.2.3. 278 // sections 4.1.1.2 and 4.1.2.3.
276 if (!VerifySignatureAlgorithmsMatch(cert)) 279 if (!VerifySignatureAlgorithmsMatch(cert))
277 return false; 280 return false;
278 281
279 // Verify the digital signature using the previous certificate's key (RFC 282 // Verify the digital signature using the previous certificate's key (RFC
280 // 5280 section 6.1.3 step a.1). 283 // 5280 section 6.1.3 step a.1).
281 if (!skip_issuer_checks) { 284 if (!skip_issuer_checks) {
282 if (!VerifySignedData( 285 if (!VerifySignedData(*cert.signature_algorithm, cert.tbs_certificate_tlv,
283 *cert.signature_algorithm, cert.cert.tbs_certificate_tlv, 286 cert.signature_value, working_spki,
284 cert.cert.signature_value, working_spki, signature_policy)) { 287 signature_policy)) {
285 return false; 288 return false;
286 } 289 }
287 } 290 }
288 291
289 // Check the time range for the certificate's validity, ensuring it is valid 292 // Check the time range for the certificate's validity, ensuring it is valid
290 // at |time|. 293 // at |time|.
291 // (RFC 5280 section 6.1.3 step a.2) 294 // (RFC 5280 section 6.1.3 step a.2)
292 if (!VerifyTimeValidity(cert, time)) 295 if (!VerifyTimeValidity(cert, time))
293 return false; 296 return false;
294 297
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 result->cert_data_.assign(data, data + length); 511 result->cert_data_.assign(data, data + length);
509 result->cert_ = 512 result->cert_ =
510 der::Input(result->cert_data_.data(), result->cert_data_.size()); 513 der::Input(result->cert_data_.data(), result->cert_data_.size());
511 break; 514 break;
512 case DataSource::EXTERNAL_REFERENCE: 515 case DataSource::EXTERNAL_REFERENCE:
513 result->cert_ = der::Input(data, length); 516 result->cert_ = der::Input(data, length);
514 break; 517 break;
515 } 518 }
516 519
517 // Parse the certificate to get its name. 520 // Parse the certificate to get its name.
518 ParsedCertificate cert; 521 der::Input tbs_certificate_tlv;
519 if (!ParseCertificate(result->cert(), &cert)) 522 der::Input signature_algorithm_tlv;
523 der::BitString signature_value;
524 if (!ParseCertificate(result->cert(), &tbs_certificate_tlv,
525 &signature_algorithm_tlv, &signature_value))
520 return nullptr; 526 return nullptr;
521 527
522 ParsedTbsCertificate tbs; 528 ParsedTbsCertificate tbs;
523 if (!ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs)) 529 if (!ParseTbsCertificate(tbs_certificate_tlv, &tbs))
524 return nullptr; 530 return nullptr;
525 531
526 result->name_ = tbs.subject_tlv; 532 result->name_ = tbs.subject_tlv;
527 533
528 // TODO(eroman): If adding a self-signed certificate, check that its 534 // TODO(eroman): If adding a self-signed certificate, check that its
529 // signature is correct? This check will not otherwise be done during 535 // signature is correct? This check will not otherwise be done during
530 // verification. 536 // verification.
531 537
532 return result; 538 return result;
533 } 539 }
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 return false; 727 return false;
722 728
723 // Check if the current root certificate is trusted. If it is then no 729 // Check if the current root certificate is trusted. If it is then no
724 // extra work is needed. 730 // extra work is needed.
725 if (trust_store.IsTrustedCertificate(certs_der_trusted_root->back())) 731 if (trust_store.IsTrustedCertificate(certs_der_trusted_root->back()))
726 return true; 732 return true;
727 733
728 // Otherwise if it is not trusted, check whether its issuer is trusted. If 734 // Otherwise if it is not trusted, check whether its issuer is trusted. If
729 // so, make *that* trusted certificate the root. If the issuer is not in 735 // so, make *that* trusted certificate the root. If the issuer is not in
730 // the trust store then give up and fail (this is not full path building). 736 // the trust store then give up and fail (this is not full path building).
731 ParsedCertificate cert; 737 der::Input tbs_certificate_tlv;
738 der::Input signature_algorithm_tlv;
739 der::BitString signature_value;
732 ParsedTbsCertificate tbs; 740 ParsedTbsCertificate tbs;
733 if (!ParseCertificate(certs_der.back(), &cert) || 741 if (!ParseCertificate(certs_der.back(), &tbs_certificate_tlv,
734 !ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs)) { 742 &signature_algorithm_tlv, &signature_value) ||
743 !ParseTbsCertificate(tbs_certificate_tlv, &tbs)) {
735 return false; 744 return false;
736 } 745 }
737 746
738 auto trust_anchor = trust_store.FindTrustAnchorByName(tbs.issuer_tlv); 747 auto trust_anchor = trust_store.FindTrustAnchorByName(tbs.issuer_tlv);
739 if (!trust_anchor) 748 if (!trust_anchor)
740 return false; 749 return false;
741 certs_der_trusted_root->push_back(trust_anchor->cert()); 750 certs_der_trusted_root->push_back(trust_anchor->cert());
742 return true; 751 return true;
743 } 752 }
744 753
745 } // namespace 754 } // namespace
746 755
747 bool VerifyCertificateChain(const std::vector<der::Input>& certs_der, 756 bool VerifyCertificateChain(const std::vector<der::Input>& certs_der,
748 const TrustStore& trust_store, 757 const TrustStore& trust_store,
749 const SignaturePolicy* signature_policy, 758 const SignaturePolicy* signature_policy,
750 const der::GeneralizedTime& time) { 759 const der::GeneralizedTime& time) {
751 // Modify the certificate chain so that its root is a trusted certificate. 760 // Modify the certificate chain so that its root is a trusted certificate.
752 std::vector<der::Input> certs_der_trusted_root; 761 std::vector<der::Input> certs_der_trusted_root;
753 if (!BuildSimplePathToTrustAnchor(certs_der, trust_store, 762 if (!BuildSimplePathToTrustAnchor(certs_der, trust_store,
754 &certs_der_trusted_root)) { 763 &certs_der_trusted_root)) {
755 return false; 764 return false;
756 } 765 }
757 766
758 // Verify the chain. 767 // Verify the chain.
759 return VerifyCertificateChainAssumingTrustedRoot( 768 return VerifyCertificateChainAssumingTrustedRoot(
760 certs_der_trusted_root, trust_store, signature_policy, time); 769 certs_der_trusted_root, trust_store, signature_policy, time);
761 } 770 }
762 771
763 } // namespace net 772 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/internal/parse_ocsp_unittest.cc ('k') | net/cert/x509_util_openssl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698