Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/parsed_certificate.h" | |
| 12 #include "net/cert/internal/signature_algorithm.h" | 13 #include "net/cert/internal/signature_algorithm.h" |
| 13 #include "net/cert/internal/signature_policy.h" | 14 #include "net/cert/internal/signature_policy.h" |
| 14 #include "net/cert/internal/verify_name_match.h" | 15 #include "net/cert/internal/trust_store.h" |
| 15 #include "net/cert/internal/verify_signed_data.h" | 16 #include "net/cert/internal/verify_signed_data.h" |
| 16 #include "net/der/input.h" | 17 #include "net/der/input.h" |
| 17 #include "net/der/parser.h" | 18 #include "net/der/parser.h" |
| 18 | 19 |
| 19 namespace net { | 20 namespace net { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 // Map from OID to ParsedExtension. | |
| 24 using ExtensionsMap = std::map<der::Input, ParsedExtension>; | |
| 25 | |
| 26 // Describes all parsed properties of a certificate that are relevant for | |
| 27 // certificate verification. | |
| 28 struct FullyParsedCert { | |
| 29 der::Input tbs_certificate_tlv; | |
| 30 der::Input signature_algorithm_tlv; | |
| 31 der::BitString signature_value; | |
| 32 ParsedTbsCertificate tbs; | |
| 33 | |
| 34 std::unique_ptr<SignatureAlgorithm> signature_algorithm; | |
| 35 | |
| 36 // Standard extensions that were parsed. | |
| 37 bool has_basic_constraints = false; | |
| 38 ParsedBasicConstraints basic_constraints; | |
| 39 | |
| 40 bool has_key_usage = false; | |
| 41 der::BitString key_usage; | |
| 42 | |
| 43 std::unique_ptr<GeneralNames> subject_alt_names; | |
| 44 | |
| 45 bool has_name_constraints = false; | |
| 46 ParsedExtension name_constraints_extension; | |
| 47 | |
| 48 // The remaining extensions (excludes the standard ones above). | |
| 49 ExtensionsMap unconsumed_extensions; | |
| 50 }; | |
| 51 | |
| 52 // Removes the extension with OID |oid| from |unconsumed_extensions| and fills | |
| 53 // |extension| with the matching extension value. If there was no extension | |
| 54 // matching |oid| then returns |false|. | |
| 55 WARN_UNUSED_RESULT bool ConsumeExtension(const der::Input& oid, | |
| 56 ExtensionsMap* unconsumed_extensions, | |
| 57 ParsedExtension* extension) { | |
| 58 auto it = unconsumed_extensions->find(oid); | |
| 59 if (it == unconsumed_extensions->end()) | |
| 60 return false; | |
| 61 | |
| 62 *extension = it->second; | |
| 63 unconsumed_extensions->erase(it); | |
| 64 return true; | |
| 65 } | |
| 66 | |
| 67 // Returns true if the certificate does not contain any unconsumed _critical_ | 24 // Returns true if the certificate does not contain any unconsumed _critical_ |
| 68 // extensions. | 25 // extensions. |
| 69 WARN_UNUSED_RESULT bool VerifyNoUnconsumedCriticalExtensions( | 26 WARN_UNUSED_RESULT bool VerifyNoUnconsumedCriticalExtensions( |
| 70 const FullyParsedCert& cert) { | 27 const ParsedCertificate& cert) { |
| 71 for (const auto& entry : cert.unconsumed_extensions) { | 28 for (const auto& entry : cert.unconsumed_extensions()) { |
| 72 if (entry.second.critical) | 29 if (entry.second.critical) |
| 73 return false; | 30 return false; |
| 74 } | 31 } |
| 75 return true; | 32 return true; |
| 76 } | 33 } |
| 77 | 34 |
| 78 WARN_UNUSED_RESULT bool GetSequenceValue(const der::Input& tlv, | |
| 79 der::Input* value) { | |
| 80 der::Parser parser(tlv); | |
| 81 return parser.ReadTag(der::kSequence, value) && !parser.HasMore(); | |
| 82 } | |
| 83 | |
| 84 // Parses an X.509 Certificate fully (including the TBSCertificate and | |
| 85 // standard extensions), saving all the properties to |out_|. | |
| 86 WARN_UNUSED_RESULT bool FullyParseCertificate(const der::Input& cert_tlv, | |
| 87 FullyParsedCert* out) { | |
| 88 // Parse the outer Certificate. | |
| 89 if (!ParseCertificate(cert_tlv, &out->tbs_certificate_tlv, | |
| 90 &out->signature_algorithm_tlv, &out->signature_value)) | |
| 91 return false; | |
| 92 | |
| 93 // Parse the signature algorithm contained in the Certificate (there is | |
| 94 // another one in the TBSCertificate, which is checked later by | |
| 95 // VerifySignatureAlgorithmsMatch) | |
| 96 out->signature_algorithm = | |
| 97 SignatureAlgorithm::CreateFromDer(out->signature_algorithm_tlv); | |
| 98 if (!out->signature_algorithm) | |
| 99 return false; | |
| 100 | |
| 101 // Parse the TBSCertificate. | |
| 102 if (!ParseTbsCertificate(out->tbs_certificate_tlv, &out->tbs)) | |
| 103 return false; | |
| 104 | |
| 105 // Reset state relating to extensions (which may not get overwritten). This is | |
| 106 // just a precaution, since in practice |out| will already be default | |
| 107 // initialize. | |
| 108 out->has_basic_constraints = false; | |
| 109 out->has_key_usage = false; | |
| 110 out->unconsumed_extensions.clear(); | |
| 111 out->subject_alt_names.reset(); | |
| 112 out->has_name_constraints = false; | |
| 113 | |
| 114 // Parse the standard X.509 extensions and remove them from | |
| 115 // |unconsumed_extensions|. | |
| 116 if (out->tbs.has_extensions) { | |
| 117 // ParseExtensions() ensures there are no duplicates, and maps the (unique) | |
| 118 // OID to the extension value. | |
| 119 if (!ParseExtensions(out->tbs.extensions_tlv, &out->unconsumed_extensions)) | |
| 120 return false; | |
| 121 | |
| 122 ParsedExtension extension; | |
| 123 | |
| 124 // Basic constraints. | |
| 125 if (ConsumeExtension(BasicConstraintsOid(), &out->unconsumed_extensions, | |
| 126 &extension)) { | |
| 127 out->has_basic_constraints = true; | |
| 128 if (!ParseBasicConstraints(extension.value, &out->basic_constraints)) | |
| 129 return false; | |
| 130 } | |
| 131 | |
| 132 // KeyUsage. | |
| 133 if (ConsumeExtension(KeyUsageOid(), &out->unconsumed_extensions, | |
| 134 &extension)) { | |
| 135 out->has_key_usage = true; | |
| 136 if (!ParseKeyUsage(extension.value, &out->key_usage)) | |
| 137 return false; | |
| 138 } | |
| 139 | |
| 140 // Subject alternative name. | |
| 141 if (ConsumeExtension(SubjectAltNameOid(), &out->unconsumed_extensions, | |
| 142 &extension)) { | |
| 143 // RFC 5280 section 4.2.1.6: | |
| 144 // SubjectAltName ::= GeneralNames | |
| 145 out->subject_alt_names = GeneralNames::CreateFromDer(extension.value); | |
| 146 if (!out->subject_alt_names) | |
| 147 return false; | |
| 148 // RFC 5280 section 4.1.2.6: | |
| 149 // If subject naming information is present only in the subjectAltName | |
| 150 // extension (e.g., a key bound only to an email address or URI), then the | |
| 151 // subject name MUST be an empty sequence and the subjectAltName extension | |
| 152 // MUST be critical. | |
| 153 if (!extension.critical) { | |
| 154 der::Input subject_value; | |
| 155 if (!GetSequenceValue(out->tbs.subject_tlv, &subject_value)) | |
| 156 return false; | |
| 157 if (subject_value.Length() == 0) | |
| 158 return false; | |
| 159 } | |
| 160 } | |
| 161 | |
| 162 // Name constraints. | |
| 163 if (ConsumeExtension(NameConstraintsOid(), &out->unconsumed_extensions, | |
| 164 &out->name_constraints_extension)) { | |
| 165 out->has_name_constraints = true; | |
| 166 } | |
| 167 } | |
| 168 | |
| 169 return true; | |
| 170 } | |
| 171 | |
| 172 // Returns true if |name1_tlv| matches |name2_tlv|. The two inputs must be | |
| 173 // tag-length-value for RFC 5280's Name. | |
| 174 WARN_UNUSED_RESULT bool NameMatches(const der::Input& name1_tlv, | |
| 175 const der::Input& name2_tlv) { | |
| 176 der::Input name1_value; | |
| 177 der::Input name2_value; | |
| 178 | |
| 179 // Assume that the Name is an RDNSequence. VerifyNameMatch() expects the | |
| 180 // value from a SEQUENCE, so strip off the tag. | |
| 181 if (!GetSequenceValue(name1_tlv, &name1_value) || | |
| 182 !GetSequenceValue(name2_tlv, &name2_value)) { | |
| 183 return false; | |
| 184 } | |
| 185 | |
| 186 return VerifyNameMatch(name1_value, name2_value); | |
| 187 } | |
| 188 | |
| 189 // Returns true if |cert| was self-issued. The definition of self-issuance | 35 // Returns true if |cert| was self-issued. The definition of self-issuance |
| 190 // comes from RFC 5280 section 6.1: | 36 // comes from RFC 5280 section 6.1: |
| 191 // | 37 // |
| 192 // A certificate is self-issued if the same DN appears in the subject | 38 // A certificate is self-issued if the same DN appears in the subject |
| 193 // and issuer fields (the two DNs are the same if they match according | 39 // and issuer fields (the two DNs are the same if they match according |
| 194 // to the rules specified in Section 7.1). In general, the issuer and | 40 // to the rules specified in Section 7.1). In general, the issuer and |
| 195 // subject of the certificates that make up a path are different for | 41 // subject of the certificates that make up a path are different for |
| 196 // each certificate. However, a CA may issue a certificate to itself to | 42 // each certificate. However, a CA may issue a certificate to itself to |
| 197 // support key rollover or changes in certificate policies. These | 43 // support key rollover or changes in certificate policies. These |
| 198 // self-issued certificates are not counted when evaluating path length | 44 // self-issued certificates are not counted when evaluating path length |
| 199 // or name constraints. | 45 // or name constraints. |
| 200 WARN_UNUSED_RESULT bool IsSelfIssued(const FullyParsedCert& cert) { | 46 WARN_UNUSED_RESULT bool IsSelfIssued(const ParsedCertificate& cert) { |
| 201 return NameMatches(cert.tbs.subject_tlv, cert.tbs.issuer_tlv); | 47 return cert.normalized_subject() == cert.normalized_issuer(); |
|
eroman
2016/05/12 18:12:30
yay!
| |
| 202 } | 48 } |
| 203 | 49 |
| 204 // Returns true if |cert| is valid at time |time|. | 50 // Returns true if |cert| is valid at time |time|. |
| 205 // | 51 // |
| 206 // The certificate's validity requirements are described by RFC 5280 section | 52 // The certificate's validity requirements are described by RFC 5280 section |
| 207 // 4.1.2.5: | 53 // 4.1.2.5: |
| 208 // | 54 // |
| 209 // The validity period for a certificate is the period of time from | 55 // The validity period for a certificate is the period of time from |
| 210 // notBefore through notAfter, inclusive. | 56 // notBefore through notAfter, inclusive. |
| 211 WARN_UNUSED_RESULT bool VerifyTimeValidity(const FullyParsedCert& cert, | 57 WARN_UNUSED_RESULT bool VerifyTimeValidity(const ParsedCertificate& cert, |
| 212 const der::GeneralizedTime time) { | 58 const der::GeneralizedTime time) { |
| 213 return !(time < cert.tbs.validity_not_before) && | 59 return !(time < cert.parsed_tbs().validity_not_before) && |
|
eroman
2016/05/12 18:12:30
maybe we can call the function just cert.tbs() (
mattm
2016/05/13 02:17:37
Done.
| |
| 214 !(cert.tbs.validity_not_after < time); | 60 !(cert.parsed_tbs().validity_not_after < time); |
| 215 } | 61 } |
| 216 | 62 |
| 217 // Returns true if |signature_algorithm_tlv| is a valid algorithm encoding for | 63 // Returns true if |signature_algorithm_tlv| is a valid algorithm encoding for |
| 218 // RSA with SHA1. | 64 // RSA with SHA1. |
| 219 WARN_UNUSED_RESULT bool IsRsaWithSha1SignatureAlgorithm( | 65 WARN_UNUSED_RESULT bool IsRsaWithSha1SignatureAlgorithm( |
| 220 const der::Input& signature_algorithm_tlv) { | 66 const der::Input& signature_algorithm_tlv) { |
| 221 std::unique_ptr<SignatureAlgorithm> algorithm = | 67 std::unique_ptr<SignatureAlgorithm> algorithm = |
| 222 SignatureAlgorithm::CreateFromDer(signature_algorithm_tlv); | 68 SignatureAlgorithm::CreateFromDer(signature_algorithm_tlv); |
| 223 | 69 |
| 224 return algorithm && | 70 return algorithm && |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 239 // signature field in the sequence tbsCertificate (Section 4.1.2.3). | 85 // signature field in the sequence tbsCertificate (Section 4.1.2.3). |
| 240 // | 86 // |
| 241 // The spec is not explicit about what "the same algorithm identifier" means. | 87 // The spec is not explicit about what "the same algorithm identifier" means. |
| 242 // Our interpretation is that the two DER-encoded fields must be byte-for-byte | 88 // Our interpretation is that the two DER-encoded fields must be byte-for-byte |
| 243 // identical. | 89 // identical. |
| 244 // | 90 // |
| 245 // In practice however there are certificates which use different encodings for | 91 // In practice however there are certificates which use different encodings for |
| 246 // specifying RSA with SHA1 (different OIDs). This is special-cased for | 92 // specifying RSA with SHA1 (different OIDs). This is special-cased for |
| 247 // compatibility sake. | 93 // compatibility sake. |
| 248 WARN_UNUSED_RESULT bool VerifySignatureAlgorithmsMatch( | 94 WARN_UNUSED_RESULT bool VerifySignatureAlgorithmsMatch( |
| 249 const FullyParsedCert& cert) { | 95 const ParsedCertificate& cert) { |
| 250 const der::Input& alg1_tlv = cert.signature_algorithm_tlv; | 96 const der::Input& alg1_tlv = cert.signature_algorithm_tlv(); |
| 251 const der::Input& alg2_tlv = cert.tbs.signature_algorithm_tlv; | 97 const der::Input& alg2_tlv = cert.parsed_tbs().signature_algorithm_tlv; |
| 252 | 98 |
| 253 // Ensure that the two DER-encoded signature algorithms are byte-for-byte | 99 // Ensure that the two DER-encoded signature algorithms are byte-for-byte |
| 254 // equal, but make a compatibility concession for RSA with SHA1. | 100 // equal, but make a compatibility concession for RSA with SHA1. |
| 255 return alg1_tlv == alg2_tlv || (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) && | 101 return alg1_tlv == alg2_tlv || (IsRsaWithSha1SignatureAlgorithm(alg1_tlv) && |
| 256 IsRsaWithSha1SignatureAlgorithm(alg2_tlv)); | 102 IsRsaWithSha1SignatureAlgorithm(alg2_tlv)); |
| 257 } | 103 } |
| 258 | 104 |
| 259 // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate | 105 // This function corresponds to RFC 5280 section 6.1.3's "Basic Certificate |
| 260 // Processing" procedure. | 106 // Processing" procedure. |
| 261 // | 107 // |
| 262 // |skip_issuer_checks| controls whether the function will skip: | 108 // |skip_issuer_checks| controls whether the function will skip: |
| 263 // - Checking that |cert|'s signature using |working_spki| | 109 // - Checking that |cert|'s signature using |working_spki| |
| 264 // - Checkinging that |cert|'s issuer matches |working_issuer_name| | 110 // - Checkinging that |cert|'s issuer matches |working_normalized_issuer_name| |
| 265 // This should be set to true only when verifying a trusted root certificate. | 111 // This should be set to true only when verifying a trusted root certificate. |
| 266 WARN_UNUSED_RESULT bool BasicCertificateProcessing( | 112 WARN_UNUSED_RESULT bool BasicCertificateProcessing( |
| 267 const FullyParsedCert& cert, | 113 const ParsedCertificate& cert, |
| 268 bool is_target_cert, | 114 bool is_target_cert, |
| 269 bool skip_issuer_checks, | 115 bool skip_issuer_checks, |
| 270 const SignaturePolicy* signature_policy, | 116 const SignaturePolicy* signature_policy, |
| 271 const der::GeneralizedTime& time, | 117 const der::GeneralizedTime& time, |
| 272 const der::Input& working_spki, | 118 const der::Input& working_spki, |
| 273 const der::Input& working_issuer_name, | 119 const der::Input& working_normalized_issuer_name, |
| 274 const std::vector<std::unique_ptr<NameConstraints>>& | 120 const std::vector<const NameConstraints*>& name_constraints_list) { |
| 275 name_constraints_list) { | |
| 276 // Check that the signature algorithms in Certificate vs TBSCertificate | 121 // Check that the signature algorithms in Certificate vs TBSCertificate |
| 277 // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by | 122 // match. This isn't part of RFC 5280 section 6.1.3, but is mandated by |
| 278 // sections 4.1.1.2 and 4.1.2.3. | 123 // sections 4.1.1.2 and 4.1.2.3. |
| 279 if (!VerifySignatureAlgorithmsMatch(cert)) | 124 if (!VerifySignatureAlgorithmsMatch(cert)) |
| 280 return false; | 125 return false; |
| 281 | 126 |
| 282 // Verify the digital signature using the previous certificate's key (RFC | 127 // Verify the digital signature using the previous certificate's key (RFC |
| 283 // 5280 section 6.1.3 step a.1). | 128 // 5280 section 6.1.3 step a.1). |
| 284 if (!skip_issuer_checks) { | 129 if (!skip_issuer_checks) { |
| 285 if (!VerifySignedData(*cert.signature_algorithm, cert.tbs_certificate_tlv, | 130 if (!cert.has_supported_signature_algorithm() || |
| 286 cert.signature_value, working_spki, | 131 !VerifySignedData(cert.signature_algorithm(), |
| 287 signature_policy)) { | 132 cert.tbs_certificate_tlv(), cert.signature_value(), |
| 133 working_spki, signature_policy)) { | |
| 288 return false; | 134 return false; |
| 289 } | 135 } |
| 290 } | 136 } |
| 291 | 137 |
| 292 // Check the time range for the certificate's validity, ensuring it is valid | 138 // Check the time range for the certificate's validity, ensuring it is valid |
| 293 // at |time|. | 139 // at |time|. |
| 294 // (RFC 5280 section 6.1.3 step a.2) | 140 // (RFC 5280 section 6.1.3 step a.2) |
| 295 if (!VerifyTimeValidity(cert, time)) | 141 if (!VerifyTimeValidity(cert, time)) |
| 296 return false; | 142 return false; |
| 297 | 143 |
| 298 // TODO(eroman): Check revocation (RFC 5280 section 6.1.3 step a.3) | 144 // TODO(eroman): Check revocation (RFC 5280 section 6.1.3 step a.3) |
| 299 | 145 |
| 300 // Verify the certificate's issuer name matches the issuing certificate's | 146 // Verify the certificate's issuer name matches the issuing certificate's |
| 301 // subject name. (RFC 5280 section 6.1.3 step a.4) | 147 // subject name. (RFC 5280 section 6.1.3 step a.4) |
| 302 if (!skip_issuer_checks) { | 148 if (!skip_issuer_checks) { |
| 303 if (!NameMatches(cert.tbs.issuer_tlv, working_issuer_name)) | 149 if (der::Input(&cert.normalized_issuer()) != working_normalized_issuer_name) |
| 304 return false; | 150 return false; |
| 305 } | 151 } |
| 306 | 152 |
| 307 // Name constraints (RFC 5280 section 6.1.3 step b & c) | 153 // Name constraints (RFC 5280 section 6.1.3 step b & c) |
| 308 // If certificate i is self-issued and it is not the final certificate in the | 154 // If certificate i is self-issued and it is not the final certificate in the |
| 309 // path, skip this step for certificate i. | 155 // path, skip this step for certificate i. |
| 310 if (!name_constraints_list.empty() && | 156 if (!name_constraints_list.empty() && |
| 311 (!IsSelfIssued(cert) || is_target_cert)) { | 157 (!IsSelfIssued(cert) || is_target_cert)) { |
| 312 der::Input subject_value; | 158 for (const NameConstraints* nc : name_constraints_list) { |
| 313 if (!GetSequenceValue(cert.tbs.subject_tlv, &subject_value)) | 159 if (!nc->IsPermittedCert(der::Input(&cert.normalized_subject()), |
| 314 return false; | 160 cert.subject_alt_names())) |
| 315 for (const auto& nc : name_constraints_list) { | |
| 316 if (!nc->IsPermittedCert(subject_value, cert.subject_alt_names.get())) | |
| 317 return false; | 161 return false; |
| 318 } | 162 } |
| 319 } | 163 } |
| 320 | 164 |
| 321 // TODO(eroman): Steps d-f are omitted, as policy constraints are not yet | 165 // TODO(eroman): Steps d-f are omitted, as policy constraints are not yet |
| 322 // implemented. | 166 // implemented. |
| 323 | 167 |
| 324 return true; | 168 return true; |
| 325 } | 169 } |
| 326 | 170 |
| 327 // This function corresponds to RFC 5280 section 6.1.4's "Preparation for | 171 // This function corresponds to RFC 5280 section 6.1.4's "Preparation for |
| 328 // Certificate i+1" procedure. |cert| is expected to be an intermediary. | 172 // Certificate i+1" procedure. |cert| is expected to be an intermediary. |
| 329 WARN_UNUSED_RESULT bool PrepareForNextCertificate( | 173 WARN_UNUSED_RESULT bool PrepareForNextCertificate( |
| 330 const FullyParsedCert& cert, | 174 const ParsedCertificate& cert, |
| 331 size_t* max_path_length_ptr, | 175 size_t* max_path_length_ptr, |
| 332 der::Input* working_spki, | 176 der::Input* working_spki, |
| 333 der::Input* working_issuer_name, | 177 der::Input* working_normalized_issuer_name, |
| 334 std::vector<std::unique_ptr<NameConstraints>>* name_constraints_list) { | 178 std::vector<const NameConstraints*>* name_constraints_list) { |
| 335 // TODO(eroman): Steps a-b are omitted, as policy constraints are not yet | 179 // TODO(eroman): Steps a-b are omitted, as policy constraints are not yet |
| 336 // implemented. | 180 // implemented. |
| 337 | 181 |
| 338 // From RFC 5280 section 6.1.4 step c: | 182 // From RFC 5280 section 6.1.4 step c: |
| 339 // | 183 // |
| 340 // Assign the certificate subject name to working_issuer_name. | 184 // Assign the certificate subject name to working_normalized_issuer_name. |
| 341 *working_issuer_name = cert.tbs.subject_tlv; | 185 *working_normalized_issuer_name = der::Input(&cert.normalized_subject()); |
| 342 | 186 |
| 343 // From RFC 5280 section 6.1.4 step d: | 187 // From RFC 5280 section 6.1.4 step d: |
| 344 // | 188 // |
| 345 // Assign the certificate subjectPublicKey to working_public_key. | 189 // Assign the certificate subjectPublicKey to working_public_key. |
| 346 *working_spki = cert.tbs.spki_tlv; | 190 *working_spki = cert.parsed_tbs().spki_tlv; |
| 347 | 191 |
| 348 // Note that steps e and f are omitted as they are handled by | 192 // Note that steps e and f are omitted as they are handled by |
| 349 // the assignment to |working_spki| above. See the definition | 193 // the assignment to |working_spki| above. See the definition |
| 350 // of |working_spki|. | 194 // of |working_spki|. |
| 351 | 195 |
| 352 // From RFC 5280 section 6.1.4 step g: | 196 // From RFC 5280 section 6.1.4 step g: |
| 353 if (cert.has_name_constraints) { | 197 if (cert.has_name_constraints()) |
| 354 std::unique_ptr<NameConstraints> name_constraints( | 198 name_constraints_list->push_back(&cert.name_constraints()); |
| 355 NameConstraints::CreateFromDer( | |
| 356 cert.name_constraints_extension.value, | |
| 357 cert.name_constraints_extension.critical)); | |
| 358 if (!name_constraints) | |
| 359 return false; | |
| 360 name_constraints_list->push_back(std::move(name_constraints)); | |
| 361 } | |
| 362 | 199 |
| 363 // TODO(eroman): Steps h-j are omitted as policy constraints are not yet | 200 // TODO(eroman): Steps h-j are omitted as policy constraints are not yet |
| 364 // implemented. | 201 // implemented. |
| 365 | 202 |
| 366 // From RFC 5280 section 6.1.4 step k: | 203 // From RFC 5280 section 6.1.4 step k: |
| 367 // | 204 // |
| 368 // If certificate i is a version 3 certificate, verify that the | 205 // If certificate i is a version 3 certificate, verify that the |
| 369 // basicConstraints extension is present and that cA is set to | 206 // basicConstraints extension is present and that cA is set to |
| 370 // TRUE. (If certificate i is a version 1 or version 2 | 207 // TRUE. (If certificate i is a version 1 or version 2 |
| 371 // certificate, then the application MUST either verify that | 208 // certificate, then the application MUST either verify that |
| 372 // certificate i is a CA certificate through out-of-band means | 209 // certificate i is a CA certificate through out-of-band means |
| 373 // or reject the certificate. Conforming implementations may | 210 // or reject the certificate. Conforming implementations may |
| 374 // choose to reject all version 1 and version 2 intermediate | 211 // choose to reject all version 1 and version 2 intermediate |
| 375 // certificates.) | 212 // certificates.) |
| 376 // | 213 // |
| 377 // This code implicitly rejects non version 3 intermediaries, since they | 214 // This code implicitly rejects non version 3 intermediaries, since they |
| 378 // can't contain a BasicConstraints extension. | 215 // can't contain a BasicConstraints extension. |
| 379 if (!cert.has_basic_constraints || !cert.basic_constraints.is_ca) | 216 if (!cert.has_basic_constraints() || !cert.basic_constraints().is_ca) |
| 380 return false; | 217 return false; |
| 381 | 218 |
| 382 // From RFC 5280 section 6.1.4 step l: | 219 // From RFC 5280 section 6.1.4 step l: |
| 383 // | 220 // |
| 384 // If the certificate was not self-issued, verify that | 221 // If the certificate was not self-issued, verify that |
| 385 // max_path_length is greater than zero and decrement | 222 // max_path_length is greater than zero and decrement |
| 386 // max_path_length by 1. | 223 // max_path_length by 1. |
| 387 if (!IsSelfIssued(cert)) { | 224 if (!IsSelfIssued(cert)) { |
| 388 if (*max_path_length_ptr == 0) | 225 if (*max_path_length_ptr == 0) |
| 389 return false; | 226 return false; |
| 390 --(*max_path_length_ptr); | 227 --(*max_path_length_ptr); |
| 391 } | 228 } |
| 392 | 229 |
| 393 // From RFC 5280 section 6.1.4 step m: | 230 // From RFC 5280 section 6.1.4 step m: |
| 394 // | 231 // |
| 395 // If pathLenConstraint is present in the certificate and is | 232 // If pathLenConstraint is present in the certificate and is |
| 396 // less than max_path_length, set max_path_length to the value | 233 // less than max_path_length, set max_path_length to the value |
| 397 // of pathLenConstraint. | 234 // of pathLenConstraint. |
| 398 if (cert.basic_constraints.has_path_len && | 235 if (cert.basic_constraints().has_path_len && |
| 399 cert.basic_constraints.path_len < *max_path_length_ptr) { | 236 cert.basic_constraints().path_len < *max_path_length_ptr) { |
| 400 *max_path_length_ptr = cert.basic_constraints.path_len; | 237 *max_path_length_ptr = cert.basic_constraints().path_len; |
| 401 } | 238 } |
| 402 | 239 |
| 403 // From RFC 5280 section 6.1.4 step n: | 240 // From RFC 5280 section 6.1.4 step n: |
| 404 // | 241 // |
| 405 // If a key usage extension is present, verify that the | 242 // If a key usage extension is present, verify that the |
| 406 // keyCertSign bit is set. | 243 // keyCertSign bit is set. |
| 407 if (cert.has_key_usage && | 244 if (cert.has_key_usage() && |
| 408 !cert.key_usage.AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)) { | 245 !cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)) { |
| 409 return false; | 246 return false; |
| 410 } | 247 } |
| 411 | 248 |
| 412 // From RFC 5280 section 6.1.4 step o: | 249 // From RFC 5280 section 6.1.4 step o: |
| 413 // | 250 // |
| 414 // Recognize and process any other critical extension present in | 251 // Recognize and process any other critical extension present in |
| 415 // the certificate. Process any other recognized non-critical | 252 // the certificate. Process any other recognized non-critical |
| 416 // extension present in the certificate that is relevant to path | 253 // extension present in the certificate that is relevant to path |
| 417 // processing. | 254 // processing. |
| 418 if (!VerifyNoUnconsumedCriticalExtensions(cert)) | 255 if (!VerifyNoUnconsumedCriticalExtensions(cert)) |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 437 // If the cA boolean is not asserted, then the keyCertSign bit in the key | 274 // If the cA boolean is not asserted, then the keyCertSign bit in the key |
| 438 // usage extension MUST NOT be asserted. | 275 // usage extension MUST NOT be asserted. |
| 439 // | 276 // |
| 440 // TODO(eroman): Strictly speaking the first requirement is on CAs and not the | 277 // TODO(eroman): Strictly speaking the first requirement is on CAs and not the |
| 441 // certificate client, so could be skipped. | 278 // certificate client, so could be skipped. |
| 442 // | 279 // |
| 443 // TODO(eroman): I don't believe Firefox enforces the keyCertSign restriction | 280 // TODO(eroman): I don't believe Firefox enforces the keyCertSign restriction |
| 444 // for compatibility reasons. Investigate if we need to similarly relax this | 281 // for compatibility reasons. Investigate if we need to similarly relax this |
| 445 // constraint. | 282 // constraint. |
| 446 WARN_UNUSED_RESULT bool VerifyTargetCertHasConsistentCaBits( | 283 WARN_UNUSED_RESULT bool VerifyTargetCertHasConsistentCaBits( |
| 447 const FullyParsedCert& cert) { | 284 const ParsedCertificate& cert) { |
| 448 // Check if the certificate contains any property specific to CAs. | 285 // Check if the certificate contains any property specific to CAs. |
| 449 bool has_ca_property = | 286 bool has_ca_property = |
| 450 (cert.has_basic_constraints && | 287 (cert.has_basic_constraints() && |
| 451 (cert.basic_constraints.is_ca || cert.basic_constraints.has_path_len)) || | 288 (cert.basic_constraints().is_ca || |
| 452 (cert.has_key_usage && | 289 cert.basic_constraints().has_path_len)) || |
| 453 cert.key_usage.AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); | 290 (cert.has_key_usage() && |
| 291 cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); | |
| 454 | 292 |
| 455 // If it "looks" like a CA because it has a CA-only property, then check that | 293 // If it "looks" like a CA because it has a CA-only property, then check that |
| 456 // it sets ALL the properties expected of a CA. | 294 // it sets ALL the properties expected of a CA. |
| 457 if (has_ca_property) { | 295 if (has_ca_property) { |
| 458 return cert.has_basic_constraints && cert.basic_constraints.is_ca && | 296 return cert.has_basic_constraints() && cert.basic_constraints().is_ca && |
| 459 (!cert.has_key_usage || | 297 (!cert.has_key_usage() || |
| 460 cert.key_usage.AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); | 298 cert.key_usage().AssertsBit(KEY_USAGE_BIT_KEY_CERT_SIGN)); |
| 461 } | 299 } |
| 462 | 300 |
| 463 return true; | 301 return true; |
| 464 } | 302 } |
| 465 | 303 |
| 466 // This function corresponds with RFC 5280 section 6.1.5's "Wrap-Up Procedure". | 304 // This function corresponds with RFC 5280 section 6.1.5's "Wrap-Up Procedure". |
| 467 // It does processing for the final certificate (the target cert). | 305 // It does processing for the final certificate (the target cert). |
| 468 WARN_UNUSED_RESULT bool WrapUp(const FullyParsedCert& cert) { | 306 WARN_UNUSED_RESULT bool WrapUp(const ParsedCertificate& cert) { |
| 469 // TODO(eroman): Steps a-b are omitted as policy constraints are not yet | 307 // TODO(eroman): Steps a-b are omitted as policy constraints are not yet |
| 470 // implemented. | 308 // implemented. |
| 471 | 309 |
| 472 // Note step c-e are omitted the verification function does | 310 // Note step c-e are omitted the verification function does |
| 473 // not output the working public key. | 311 // not output the working public key. |
| 474 | 312 |
| 475 // From RFC 5280 section 6.1.5 step f: | 313 // From RFC 5280 section 6.1.5 step f: |
| 476 // | 314 // |
| 477 // Recognize and process any other critical extension present in | 315 // Recognize and process any other critical extension present in |
| 478 // the certificate n. Process any other recognized non-critical | 316 // the certificate n. Process any other recognized non-critical |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 490 // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure", | 328 // The following check is NOT part of RFC 5280 6.1.5's "Wrap-Up Procedure", |
| 491 // however is implied by RFC 5280 section 4.2.1.9. | 329 // however is implied by RFC 5280 section 4.2.1.9. |
| 492 if (!VerifyTargetCertHasConsistentCaBits(cert)) | 330 if (!VerifyTargetCertHasConsistentCaBits(cert)) |
| 493 return false; | 331 return false; |
| 494 | 332 |
| 495 return true; | 333 return true; |
| 496 } | 334 } |
| 497 | 335 |
| 498 } // namespace | 336 } // namespace |
| 499 | 337 |
| 500 TrustAnchor::TrustAnchor() {} | |
| 501 TrustAnchor::~TrustAnchor() {} | |
| 502 | |
| 503 std::unique_ptr<TrustAnchor> TrustAnchor::CreateFromCertificateData( | |
| 504 const uint8_t* data, | |
| 505 size_t length, | |
| 506 DataSource source) { | |
| 507 std::unique_ptr<TrustAnchor> result(new TrustAnchor); | |
| 508 | |
| 509 switch (source) { | |
| 510 case DataSource::INTERNAL_COPY: | |
| 511 result->cert_data_.assign(data, data + length); | |
| 512 result->cert_ = | |
| 513 der::Input(result->cert_data_.data(), result->cert_data_.size()); | |
| 514 break; | |
| 515 case DataSource::EXTERNAL_REFERENCE: | |
| 516 result->cert_ = der::Input(data, length); | |
| 517 break; | |
| 518 } | |
| 519 | |
| 520 // Parse the certificate to get its name. | |
| 521 der::Input tbs_certificate_tlv; | |
| 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)) | |
| 526 return nullptr; | |
| 527 | |
| 528 ParsedTbsCertificate tbs; | |
| 529 if (!ParseTbsCertificate(tbs_certificate_tlv, &tbs)) | |
| 530 return nullptr; | |
| 531 | |
| 532 result->name_ = tbs.subject_tlv; | |
| 533 | |
| 534 // TODO(eroman): If adding a self-signed certificate, check that its | |
| 535 // signature is correct? This check will not otherwise be done during | |
| 536 // verification. | |
| 537 | |
| 538 return result; | |
| 539 } | |
| 540 | |
| 541 bool TrustAnchor::MatchesName(const der::Input& name) const { | |
| 542 return NameMatches(name, name_); | |
| 543 } | |
| 544 | |
| 545 TrustStore::TrustStore() {} | |
| 546 TrustStore::~TrustStore() {} | |
| 547 | |
| 548 void TrustStore::Clear() { | |
| 549 anchors_.clear(); | |
| 550 } | |
| 551 | |
| 552 bool TrustStore::AddTrustedCertificate(const uint8_t* data, size_t length) { | |
| 553 return AddTrustedCertificate(data, length, | |
| 554 TrustAnchor::DataSource::INTERNAL_COPY); | |
| 555 } | |
| 556 | |
| 557 bool TrustStore::AddTrustedCertificate(const base::StringPiece& data) { | |
| 558 return AddTrustedCertificate(reinterpret_cast<const uint8_t*>(data.data()), | |
| 559 data.size()); | |
| 560 } | |
| 561 | |
| 562 bool TrustStore::AddTrustedCertificateWithoutCopying(const uint8_t* data, | |
| 563 size_t length) { | |
| 564 return AddTrustedCertificate(data, length, | |
| 565 TrustAnchor::DataSource::EXTERNAL_REFERENCE); | |
| 566 } | |
| 567 | |
| 568 const TrustAnchor* TrustStore::FindTrustAnchorByName( | |
| 569 const der::Input& name) const { | |
| 570 for (const auto& anchor : anchors_) { | |
| 571 if (anchor->MatchesName(name)) { | |
| 572 return anchor.get(); | |
| 573 } | |
| 574 } | |
| 575 return nullptr; | |
| 576 } | |
| 577 | |
| 578 bool TrustStore::IsTrustedCertificate(const der::Input& cert_der) const { | |
| 579 for (const auto& anchor : anchors_) { | |
| 580 if (anchor->cert() == cert_der) | |
| 581 return true; | |
| 582 } | |
| 583 return false; | |
| 584 } | |
| 585 | |
| 586 bool TrustStore::AddTrustedCertificate(const uint8_t* data, | |
| 587 size_t length, | |
| 588 TrustAnchor::DataSource source) { | |
| 589 auto anchor = TrustAnchor::CreateFromCertificateData(data, length, source); | |
| 590 if (!anchor) | |
| 591 return false; | |
| 592 anchors_.push_back(std::move(anchor)); | |
| 593 return true; | |
| 594 } | |
| 595 | |
| 596 // TODO(eroman): Move this into existing anonymous namespace. | 338 // TODO(eroman): Move this into existing anonymous namespace. |
| 597 namespace { | 339 namespace { |
| 598 | 340 |
| 599 // This implementation is structured to mimic the description of certificate | 341 // This implementation is structured to mimic the description of certificate |
| 600 // path verification given by RFC 5280 section 6.1. | 342 // path verification given by RFC 5280 section 6.1. |
| 601 // | 343 // |
| 602 // Unlike RFC 5280, the trust anchor is specified as the root certificate in | 344 // Unlike RFC 5280, the trust anchor is specified as the root certificate in |
| 603 // the chain. This root certificate is assumed to be trusted, and neither its | 345 // the chain. This root certificate is assumed to be trusted, and neither its |
| 604 // signature nor issuer name are verified. (It needn't be self-signed). | 346 // signature nor issuer name are verified. (It needn't be self-signed). |
| 605 bool VerifyCertificateChainAssumingTrustedRoot( | 347 bool VerifyCertificateChainAssumingTrustedRoot( |
| 606 const std::vector<der::Input>& certs_der, | 348 const std::vector<scoped_refptr<ParsedCertificate>>& certs, |
| 607 // The trust store is only used for assertions. | 349 // The trust store is only used for assertions. |
| 608 const TrustStore& trust_store, | 350 const TrustStore& trust_store, |
| 609 const SignaturePolicy* signature_policy, | 351 const SignaturePolicy* signature_policy, |
| 610 const der::GeneralizedTime& time) { | 352 const der::GeneralizedTime& time) { |
| 611 // An empty chain is necessarily invalid. | 353 // An empty chain is necessarily invalid. |
| 612 if (certs_der.empty()) | 354 if (certs.empty()) |
| 613 return false; | 355 return false; |
| 614 | 356 |
| 615 // IMPORTANT: the assumption being made is that the root certificate in | 357 // IMPORTANT: the assumption being made is that the root certificate in |
| 616 // the given path is the trust anchor (and has already been verified as | 358 // the given path is the trust anchor (and has already been verified as |
| 617 // such). | 359 // such). |
| 618 DCHECK(trust_store.IsTrustedCertificate(certs_der.back())); | 360 DCHECK(trust_store.IsTrustedCertificate(certs.back().get())); |
| 619 | 361 |
| 620 // Will contain a NameConstraints for each previous cert in the chain which | 362 // Will contain a NameConstraints for each previous cert in the chain which |
| 621 // had nameConstraints. This corresponds to the permitted_subtrees and | 363 // had nameConstraints. This corresponds to the permitted_subtrees and |
| 622 // excluded_subtrees state variables from RFC 5280. | 364 // excluded_subtrees state variables from RFC 5280. |
| 623 std::vector<std::unique_ptr<NameConstraints>> name_constraints_list; | 365 std::vector<const NameConstraints*> name_constraints_list; |
| 624 | 366 |
| 625 // |working_spki| is an amalgamation of 3 separate variables from RFC 5280: | 367 // |working_spki| is an amalgamation of 3 separate variables from RFC 5280: |
| 626 // * working_public_key | 368 // * working_public_key |
| 627 // * working_public_key_algorithm | 369 // * working_public_key_algorithm |
| 628 // * working_public_key_parameters | 370 // * working_public_key_parameters |
| 629 // | 371 // |
| 630 // They are combined for simplicity since the signature verification takes an | 372 // They are combined for simplicity since the signature verification takes an |
| 631 // SPKI, and the parameter inheritence is not applicable for the supported | 373 // SPKI, and the parameter inheritence is not applicable for the supported |
| 632 // key types. | 374 // key types. |
| 633 // | 375 // |
| 634 // An approximate explanation of |working_spki| is this description from RFC | 376 // An approximate explanation of |working_spki| is this description from RFC |
| 635 // 5280 section 6.1.2: | 377 // 5280 section 6.1.2: |
| 636 // | 378 // |
| 637 // working_public_key: the public key used to verify the | 379 // working_public_key: the public key used to verify the |
| 638 // signature of a certificate. | 380 // signature of a certificate. |
| 639 der::Input working_spki; | 381 der::Input working_spki; |
| 640 | 382 |
| 641 // |working_issuer_name| corresponds with the same named variable in RFC 5280 | 383 // |working_normalized_issuer_name| is the normalized value of the |
| 642 // section 6.1.2: | 384 // working_issuer_name variable in RFC 5280 section 6.1.2: |
|
eroman
2016/05/12 18:12:30
thanks for updating the comments throughout!
| |
| 643 // | 385 // |
| 644 // working_issuer_name: the issuer distinguished name expected | 386 // working_issuer_name: the issuer distinguished name expected |
| 645 // in the next certificate in the chain. | 387 // in the next certificate in the chain. |
| 646 der::Input working_issuer_name; | 388 der::Input working_normalized_issuer_name; |
| 647 | 389 |
| 648 // |max_path_length| corresponds with the same named variable in RFC 5280 | 390 // |max_path_length| corresponds with the same named variable in RFC 5280 |
| 649 // section 6.1.2: | 391 // section 6.1.2: |
| 650 // | 392 // |
| 651 // max_path_length: this integer is initialized to n, is | 393 // max_path_length: this integer is initialized to n, is |
| 652 // decremented for each non-self-issued certificate in the path, | 394 // decremented for each non-self-issued certificate in the path, |
| 653 // and may be reduced to the value in the path length constraint | 395 // and may be reduced to the value in the path length constraint |
| 654 // field within the basic constraints extension of a CA | 396 // field within the basic constraints extension of a CA |
| 655 // certificate. | 397 // certificate. |
| 656 size_t max_path_length = certs_der.size(); | 398 size_t max_path_length = certs.size(); |
| 657 | 399 |
| 658 // Iterate over all the certificates in the reverse direction: starting from | 400 // Iterate over all the certificates in the reverse direction: starting from |
| 659 // the trust anchor and progressing towards the target certificate. | 401 // the trust anchor and progressing towards the target certificate. |
| 660 // | 402 // |
| 661 // Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based. | 403 // Note that |i| uses 0-based indexing whereas in RFC 5280 it is 1-based. |
| 662 // | 404 // |
| 663 // * i=0 : Trust anchor. | 405 // * i=0 : Trust anchor. |
| 664 // * i=N-1 : Target certificate. | 406 // * i=N-1 : Target certificate. |
| 665 for (size_t i = 0; i < certs_der.size(); ++i) { | 407 for (size_t i = 0; i < certs.size(); ++i) { |
| 666 const size_t index_into_certs_der = certs_der.size() - i - 1; | 408 const size_t index_into_certs = certs.size() - i - 1; |
| 667 | 409 |
| 668 // |is_target_cert| is true if the current certificate is the target | 410 // |is_target_cert| is true if the current certificate is the target |
| 669 // certificate being verified. The target certificate isn't necessarily an | 411 // certificate being verified. The target certificate isn't necessarily an |
| 670 // end-entity certificate. | 412 // end-entity certificate. |
| 671 const bool is_target_cert = index_into_certs_der == 0; | 413 const bool is_target_cert = index_into_certs == 0; |
| 672 | 414 |
| 673 // |is_trust_anchor| is true if the current certificate is the trust | 415 // |is_trust_anchor| is true if the current certificate is the trust |
| 674 // anchor. This certificate is implicitly trusted. | 416 // anchor. This certificate is implicitly trusted. |
| 675 const bool is_trust_anchor = i == 0; | 417 const bool is_trust_anchor = i == 0; |
| 676 | 418 |
| 677 // Parse the current certificate into |cert|. | 419 const ParsedCertificate& cert = *certs[index_into_certs]; |
| 678 FullyParsedCert cert; | |
| 679 const der::Input& cert_der = certs_der[index_into_certs_der]; | |
| 680 if (!FullyParseCertificate(cert_der, &cert)) | |
| 681 return false; | |
| 682 | 420 |
| 683 // Per RFC 5280 section 6.1: | 421 // Per RFC 5280 section 6.1: |
| 684 // * Do basic processing for each certificate | 422 // * Do basic processing for each certificate |
| 685 // * If it is the last certificate in the path (target certificate) | 423 // * If it is the last certificate in the path (target certificate) |
| 686 // - Then run "Wrap up" | 424 // - Then run "Wrap up" |
| 687 // - Otherwise run "Prepare for Next cert" | 425 // - Otherwise run "Prepare for Next cert" |
| 688 if (!BasicCertificateProcessing( | 426 if (!BasicCertificateProcessing(cert, is_target_cert, is_trust_anchor, |
| 689 cert, is_target_cert, is_trust_anchor, signature_policy, time, | 427 signature_policy, time, working_spki, |
| 690 working_spki, working_issuer_name, name_constraints_list)) { | 428 working_normalized_issuer_name, |
| 429 name_constraints_list)) { | |
| 691 return false; | 430 return false; |
| 692 } | 431 } |
| 693 if (!is_target_cert) { | 432 if (!is_target_cert) { |
| 694 if (!PrepareForNextCertificate(cert, &max_path_length, &working_spki, | 433 if (!PrepareForNextCertificate(cert, &max_path_length, &working_spki, |
| 695 &working_issuer_name, | 434 &working_normalized_issuer_name, |
| 696 &name_constraints_list)) { | 435 &name_constraints_list)) { |
| 697 return false; | 436 return false; |
| 698 } | 437 } |
| 699 } else { | 438 } else { |
| 700 if (!WrapUp(cert)) | 439 if (!WrapUp(cert)) |
| 701 return false; | 440 return false; |
| 702 } | 441 } |
| 703 } | 442 } |
| 704 | 443 |
| 705 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: | 444 // TODO(eroman): RFC 5280 forbids duplicate certificates per section 6.1: |
| 706 // | 445 // |
| 707 // A certificate MUST NOT appear more than once in a prospective | 446 // A certificate MUST NOT appear more than once in a prospective |
| 708 // certification path. | 447 // certification path. |
| 709 | 448 |
| 710 return true; | 449 return true; |
| 711 } | 450 } |
| 712 | 451 |
| 713 // TODO(eroman): This function is a temporary hack in the absence of full | 452 // TODO(eroman): This function is a temporary hack in the absence of full |
| 714 // path building. It may insert 1 certificate at the root of the | 453 // path building. It may insert 1 certificate at the root of the |
| 715 // chain to ensure that the path's root certificate is a trust anchor. | 454 // chain to ensure that the path's root certificate is a trust anchor. |
| 716 // | 455 // |
| 717 // Beyond this no other verification is done on the chain. The caller is | 456 // Beyond this no other verification is done on the chain. The caller is |
| 718 // responsible for verifying the subsequent chain's correctness. | 457 // responsible for verifying the subsequent chain's correctness. |
| 719 WARN_UNUSED_RESULT bool BuildSimplePathToTrustAnchor( | 458 WARN_UNUSED_RESULT bool BuildSimplePathToTrustAnchor( |
| 720 const std::vector<der::Input>& certs_der, | |
| 721 const TrustStore& trust_store, | 459 const TrustStore& trust_store, |
| 722 std::vector<der::Input>* certs_der_trusted_root) { | 460 std::vector<scoped_refptr<ParsedCertificate>>* certs) { |
| 723 // Copy the input chain. | 461 if (certs->empty()) |
| 724 *certs_der_trusted_root = certs_der; | |
| 725 | |
| 726 if (certs_der.empty()) | |
| 727 return false; | 462 return false; |
| 728 | 463 |
| 729 // Check if the current root certificate is trusted. If it is then no | 464 // Check if the current root certificate is trusted. If it is then no |
| 730 // extra work is needed. | 465 // extra work is needed. |
| 731 if (trust_store.IsTrustedCertificate(certs_der_trusted_root->back())) | 466 if (trust_store.IsTrustedCertificate(certs->back().get())) |
| 732 return true; | 467 return true; |
| 733 | 468 |
| 734 // Otherwise if it is not trusted, check whether its issuer is trusted. If | 469 std::vector<scoped_refptr<ParsedCertificate>> trust_anchors; |
| 735 // so, make *that* trusted certificate the root. If the issuer is not in | 470 trust_store.FindTrustAnchorsByNormalizedName( |
| 736 // the trust store then give up and fail (this is not full path building). | 471 certs->back()->normalized_issuer(), &trust_anchors); |
| 737 der::Input tbs_certificate_tlv; | 472 if (trust_anchors.empty()) |
| 738 der::Input signature_algorithm_tlv; | |
| 739 der::BitString signature_value; | |
| 740 ParsedTbsCertificate tbs; | |
| 741 if (!ParseCertificate(certs_der.back(), &tbs_certificate_tlv, | |
| 742 &signature_algorithm_tlv, &signature_value) || | |
| 743 !ParseTbsCertificate(tbs_certificate_tlv, &tbs)) { | |
| 744 return false; | 473 return false; |
| 745 } | 474 certs->push_back(std::move(trust_anchors[0])); |
| 746 | |
| 747 auto trust_anchor = trust_store.FindTrustAnchorByName(tbs.issuer_tlv); | |
| 748 if (!trust_anchor) | |
| 749 return false; | |
| 750 certs_der_trusted_root->push_back(trust_anchor->cert()); | |
| 751 return true; | 475 return true; |
| 752 } | 476 } |
| 753 | 477 |
| 754 } // namespace | 478 } // namespace |
| 755 | 479 |
| 756 bool VerifyCertificateChain(const std::vector<der::Input>& certs_der, | 480 bool VerifyCertificateChain( |
| 757 const TrustStore& trust_store, | 481 const std::vector<scoped_refptr<ParsedCertificate>>& cert_chain, |
| 758 const SignaturePolicy* signature_policy, | 482 const TrustStore& trust_store, |
| 759 const der::GeneralizedTime& time) { | 483 const SignaturePolicy* signature_policy, |
| 484 const der::GeneralizedTime& time) { | |
| 485 if (cert_chain.empty()) | |
| 486 return false; | |
| 487 | |
| 488 std::vector<scoped_refptr<ParsedCertificate>> full_chain = cert_chain; | |
| 489 | |
| 760 // Modify the certificate chain so that its root is a trusted certificate. | 490 // Modify the certificate chain so that its root is a trusted certificate. |
| 761 std::vector<der::Input> certs_der_trusted_root; | 491 if (!BuildSimplePathToTrustAnchor(trust_store, &full_chain)) { |
| 762 if (!BuildSimplePathToTrustAnchor(certs_der, trust_store, | |
| 763 &certs_der_trusted_root)) { | |
| 764 return false; | 492 return false; |
| 765 } | 493 } |
| 766 | 494 |
| 767 // Verify the chain. | 495 // Verify the chain. |
| 768 return VerifyCertificateChainAssumingTrustedRoot( | 496 return VerifyCertificateChainAssumingTrustedRoot(full_chain, trust_store, |
| 769 certs_der_trusted_root, trust_store, signature_policy, time); | 497 signature_policy, time); |
| 770 } | 498 } |
| 771 | 499 |
| 772 } // namespace net | 500 } // namespace net |
| OLD | NEW |