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