OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/cert/internal/verify_certificate_chain.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "net/cert/internal/parse_certificate.h" | |
9 #include "net/cert/internal/signature_algorithm.h" | |
10 #include "net/cert/internal/signature_policy.h" | |
11 #include "net/cert/internal/verify_signed_data.h" | |
12 #include "net/der/input.h" | |
13 | |
14 namespace net { | |
15 | |
16 namespace { | |
17 | |
18 // TODO(eroman): Move into net/der (duplicated from test_helpers.cc). | |
19 static der::Input InputFromString(const std::string* s) { | |
20 return der::Input(reinterpret_cast<const uint8_t*>(s->data()), s->size()); | |
21 } | |
22 | |
23 // Describes all parsed properties of a certificate. | |
24 struct FullyParsedCert { | |
25 CertificateVersion version; | |
26 scoped_ptr<SignatureAlgorithm> signature_algorithm; | |
27 scoped_ptr<SignatureAlgorithm> tbs_signature_algorithm; | |
28 der::BitString signature_value; | |
29 der::Input tbs_tlv; | |
30 | |
31 // TODO(eroman): Everywhere this is consumed should also consider | |
32 // issuerAltName. | |
mattm
2015/11/11 23:55:44
Did you mean "consider issuerAltName" like "should
eroman
2015/11/12 01:58:43
Thanks, Done.
The TODO was basically to figure ou
| |
33 der::Input issuer_tlv; | |
34 der::GeneralizedTime validity_not_before; | |
35 der::GeneralizedTime validity_not_after; | |
36 | |
37 // TODO(eroman): Everywhere this is consumed should also consider | |
38 // subjectAltName. | |
39 der::Input subject_tlv; | |
40 der::Input spki_tlv; | |
41 | |
42 // Extensions | |
43 bool has_basic_constraints = false; | |
44 ParsedBasicConstraints basic_constraints; | |
45 bool has_key_usage = false; | |
46 der::BitString key_usage; | |
47 }; | |
48 | |
49 // Removes the extension with OID |oid| from |extensions| and fills |extension| | |
50 // with the matching extension value. If there was no extension matching |oid| | |
51 // then returns |false|. | |
52 WARN_UNUSED_RESULT bool ConsumeExtension( | |
53 const der::Input& oid, | |
54 std::map<der::Input, ParsedExtension>* extensions, | |
55 ParsedExtension* extension) { | |
56 auto it = extensions->find(oid); | |
57 if (it == extensions->end()) | |
58 return false; | |
59 | |
60 *extension = it->second; | |
61 | |
62 // TODO(eroman): Could be faster to just reset the entry instead of | |
63 // deleting it, although a bit less clear. | |
64 extensions->erase(it); | |
65 return true; | |
66 } | |
67 | |
68 // Parses a Certificate and saves all properties to |out|. | |
69 WARN_UNUSED_RESULT bool FullyParseCertificate(const der::Input& cert_tlv, | |
70 FullyParsedCert* out) { | |
71 // Parse the Certificate. | |
72 ParsedCertificate cert; | |
73 if (!ParseCertificate(cert_tlv, &cert)) | |
74 return false; | |
75 | |
76 // Extract values of interested from the parsed Certificate. | |
mattm
2015/11/11 23:55:44
interest
eroman
2015/11/12 01:58:43
Done.
| |
77 out->tbs_tlv = cert.tbs_certificate_tlv; | |
78 out->signature_value = cert.signature_value; | |
79 | |
80 // Parse the signature algorithm in the Certificate. | |
81 out->signature_algorithm = | |
82 SignatureAlgorithm::CreateFromDer(cert.signature_algorithm_tlv); | |
83 if (!out->signature_algorithm) | |
84 return false; | |
85 | |
86 // Parse the TBSCertificate. | |
87 ParsedTbsCertificate tbs; | |
88 if (!ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs)) | |
89 return false; | |
90 | |
91 // Parse the signature algorithm in the TBSCertificate. | |
92 out->tbs_signature_algorithm = | |
93 SignatureAlgorithm::CreateFromDer(tbs.signature_algorithm_tlv); | |
94 if (!out->tbs_signature_algorithm) | |
95 return false; | |
96 | |
97 // Copy fields of interest from the TBSCertificate (just copying pointers to | |
98 // the data, not the actual DER). | |
99 out->issuer_tlv = tbs.issuer_tlv; | |
100 out->version = tbs.version; | |
101 out->spki_tlv = tbs.spki_tlv; | |
102 out->subject_tlv = tbs.subject_tlv; | |
103 out->validity_not_after = tbs.validity_not_after; | |
104 out->validity_not_before = tbs.validity_not_before; | |
105 | |
106 // Parse the X.509 extensions. | |
107 out->has_basic_constraints = false; | |
108 out->has_key_usage = false; | |
109 | |
110 if (tbs.has_extensions) { | |
111 // ParseExtensions() ensures there are no duplicates, and maps the (unique) | |
112 // OID to the extension value. The verification code must ensure that every | |
113 // critical extension is understood. | |
114 std::map<der::Input, ParsedExtension> extensions; | |
115 if (!ParseExtensions(tbs.extensions_tlv, &extensions)) | |
116 return false; | |
117 | |
118 ParsedExtension extension; | |
119 | |
120 // Process each of the recognized extensions. In doing so, the processed | |
121 // extension is cleared from the |extensions| map. | |
122 if (ConsumeExtension(BasicConstraintsOid(), &extensions, &extension)) { | |
123 out->has_basic_constraints = true; | |
124 if (!ParseBasicConstraints(extension.value, &out->basic_constraints)) | |
125 return false; | |
126 } | |
127 | |
128 if (ConsumeExtension(KeyUsageOid(), &extensions, &extension)) { | |
129 out->has_key_usage = true; | |
130 if (!ParseKeyUsage(extension.value, &out->key_usage)) | |
131 return false; | |
132 } | |
133 | |
134 // Check that there aren't any unconsumed (unprocessed) critical | |
135 // extensions in |extensions|. It is OK however for there to be | |
136 // unconsumed non-critical extensions. | |
137 for (const auto& entry : extensions) { | |
138 if (entry.second.critical) | |
139 return false; | |
140 } | |
141 } | |
142 | |
143 return true; | |
144 } | |
145 | |
146 // Returns true if |name1| matches |name2|. | |
147 WARN_UNUSED_RESULT bool NameMatches(const der::Input& name1, | |
148 const der::Input& name2) { | |
149 // TODO(eroman): Should account for normalization (taht work is part of a | |
150 // different change). | |
151 return name1.Equals(name2); | |
152 } | |
153 | |
154 // Returns true if |cert| was self-issued. Note that self-issued is not the | |
155 // same thing as self-signed, see RFC 5280 for the explanation. | |
156 WARN_UNUSED_RESULT bool IsSelfIssued(const FullyParsedCert& cert) { | |
157 return NameMatches(cert.subject_tlv, cert.issuer_tlv); | |
158 } | |
159 | |
160 // Finds a mapping in the trust store that matches |name|, or returns nullptr. | |
161 // | |
162 // TODO(eroman): This implementation is linear in the size of the trust store, | |
163 // and also presumes that all names are unique. In practice it is possible to | |
164 // have have multiple SPKIs with the same name. Also this mechanism of | |
165 // searching is fairly primitive, and does not take advantage of other | |
166 // properties like the authority key id. | |
167 WARN_UNUSED_RESULT const TrustedRoot* FindTrustedRootByName( | |
168 const TrustStore& trust_store, | |
169 const der::Input& name) { | |
170 for (const auto& root : trust_store.roots) { | |
171 if (NameMatches(name, InputFromString(&root.name))) | |
172 return &root; | |
173 } | |
174 return nullptr; | |
175 } | |
176 | |
177 // Returns true if |cert| is valid at time |time|. | |
178 // | |
179 // The certificate's validity requirements are described by RFC 5280 section | |
180 // 4.1.2.5: | |
181 // | |
182 // The validity period for a certificate is the period of time from | |
183 // notBefore through notAfter, inclusive. | |
184 WARN_UNUSED_RESULT bool VerifyValidity(const FullyParsedCert& cert, | |
185 const der::GeneralizedTime time) { | |
186 return (!(time < cert.validity_not_before) && | |
187 !(cert.validity_not_after < time)); | |
188 } | |
189 | |
190 // Returns true if |cert| has internally consistent signature algorithms. | |
191 // | |
192 // X.509 certificates contain two signature algorithms: | |
193 // (1) The signatureAlgorithm field of Certificate | |
194 // (2) The signature of TBSCertificate | |
195 // | |
196 // According to RFC 5280 section 4.1.1.2 these two fields must be in agreement: | |
197 // | |
198 // This field MUST contain the same algorithm identifier as the | |
199 // signature field in the sequence tbsCertificate (Section 4.1.2.3). | |
200 // | |
201 // The mechanism through which equality is determined is unspecified. | |
202 // The interpretation taken here is that they identify the same algorithm, | |
203 // but the DER-encoded AlgorithmIdentifier needn't be byte-for-byte equal. | |
204 // There are a small number of certificates that require this (having for | |
205 // instance specified a different OID for RSA with SHA-1). | |
206 WARN_UNUSED_RESULT bool VerifySignatureAlgorithsMatch( | |
207 const FullyParsedCert& cert) { | |
208 return cert.signature_algorithm->Equals(*cert.tbs_signature_algorithm); | |
209 } | |
210 | |
211 // Returns true if |cert| has a correct key usage for the issuance of other | |
212 // certificates. | |
213 WARN_UNUSED_RESULT bool VerifyKeyUsageForIssuer(const FullyParsedCert& cert) { | |
214 // If the Key Usage extension is not present, then the key can be used for | |
215 // any operation. | |
216 if (!cert.has_key_usage) | |
217 return true; | |
218 | |
219 // RFC 5280 section 4.2.1.9: | |
220 // | |
221 // If the keyUsage extension is present, then the subject public key | |
222 // MUST NOT be used to verify signatures on certificates or CRLs unless | |
223 // the corresponding keyCertSign or cRLSign bit is set. | |
224 if (!KeyUsageAssertsBit(cert.key_usage, KeyUsageBit::KEY_CERT_SIGN)) | |
225 return false; | |
226 | |
227 // RFC 5280 section 4.2.1.9: | |
228 // | |
229 // If the keyCertSign bit is asserted, then the cA bit in the basic | |
230 // constraints extension (Section 4.2.1.9) MUST also be asserted. | |
231 // | |
232 // NOTE: this normative requirement is not enforced by this function, but | |
233 // rather by VerifyBasicConstraintsForIssuer(). | |
234 return true; | |
235 } | |
236 | |
237 // Returns true if |cert| has a correct BasicConstraints extension for the | |
238 // issuance of other certificates. | |
239 WARN_UNUSED_RESULT bool VerifyBasicConstraintsForIssuer( | |
240 const FullyParsedCert& cert, | |
241 size_t current_cert_index, | |
242 size_t num_prev_self_issued_certs) { | |
243 DCHECK_GT(current_cert_index, 0u); | |
244 | |
245 // Only V3 certificates have the concept of extensions. | |
246 if (cert.version == CertificateVersion::V1 || | |
247 cert.version == CertificateVersion::V2) { | |
248 // RFC 5280: | |
249 // | |
250 // (If certificate i is a version 1 or version 2 certificate, then the | |
251 // application MUST either verify that certificate i is a CA | |
252 // certificate through out-of-band means or reject the certificate. | |
253 // Conforming implementations may choose to reject all version 1 and | |
254 // version 2 intermediate certificates.) | |
255 return false; | |
256 } | |
257 | |
258 // RFC 5280 section 4.2.1.9: | |
259 // | |
260 // If the basic constraints extension is not present in a version 3 | |
261 // certificate, or the extension is present but the cA boolean | |
262 // is not asserted, then the certified public key MUST NOT be used to | |
263 // verify certificate signatures. | |
264 if (!cert.has_basic_constraints || !cert.basic_constraints.is_ca) | |
265 return false; | |
266 | |
267 // RFC 5280 section 4.2.1.9: | |
268 // | |
269 // Where pathLenConstraint does not appear, no limit is imposed. | |
270 if (cert.basic_constraints.has_path_len) { | |
271 // RFC 5280 section 4.2.1.9: | |
272 // | |
273 // ... In this case, it gives the maximum number of non-self-issued | |
274 // intermediate certificates that may follow this certificate in a valid | |
275 // certification path. (Note: The last certificate in the certification | |
276 // path is not an intermediate certificate, and is not included in this | |
277 // limit. Usually, the last certificate is an end entity certificate, | |
278 // but it can be a CA certificate.) | |
279 size_t current_path_len = | |
280 current_cert_index - 1 - num_prev_self_issued_certs; | |
281 if (current_path_len > cert.basic_constraints.path_len) | |
282 return false; | |
283 } | |
284 | |
285 return true; | |
286 } | |
287 | |
288 // Returns true if the subject of |issuing_cert| matches the issuer of | |
289 // |subordinate_cert|. | |
290 WARN_UNUSED_RESULT bool VerifyIssuerMatchesSubject( | |
291 const FullyParsedCert& issuing_cert, | |
292 const FullyParsedCert& subordinate_cert) { | |
293 // TODO(eroman): subjectAltName and issuerAltName ? | |
294 return NameMatches(issuing_cert.subject_tlv, subordinate_cert.issuer_tlv); | |
295 } | |
296 | |
297 // Returns true if |cert| was signed by a trusted root in |trust_store|. | |
298 WARN_UNUSED_RESULT bool IsSignedByTrustAnchor( | |
299 const FullyParsedCert& cert, | |
300 const TrustStore& trust_store, | |
301 const SignaturePolicy* signature_policy) { | |
302 const TrustedRoot* trusted_root = | |
303 FindTrustedRootByName(trust_store, cert.issuer_tlv); | |
304 | |
305 if (!trusted_root) | |
306 return false; | |
307 | |
308 if (!VerifySignedData( | |
309 *cert.signature_algorithm, cert.tbs_tlv, cert.signature_value, | |
310 InputFromString(&trusted_root->spki), signature_policy)) { | |
311 return false; | |
312 } | |
313 | |
314 return true; | |
315 } | |
316 | |
317 // Returns true if |cert| has BasicConstraints and KeyUsage consistent with | |
318 // being an end-entity certificate. | |
319 WARN_UNUSED_RESULT bool VerifyTargetCertificateIsEndEntity( | |
320 const FullyParsedCert& cert) { | |
321 if (cert.has_basic_constraints) { | |
322 if (cert.basic_constraints.is_ca) | |
323 return false; // Not an end-entity certificate. | |
324 | |
325 // RFC 5280 section 4.2.1.9: | |
326 // | |
327 // CAs MUST NOT include the pathLenConstraint field unless the cA | |
328 // boolean is asserted and the key usage extension asserts the | |
329 // keyCertSign bit. | |
330 if (cert.basic_constraints.has_path_len) | |
331 return false; | |
332 } | |
333 | |
334 // RFC 5280 section 4.2.1.9: | |
335 // | |
336 // If the cA boolean is not asserted, then the keyCertSign bit in the key | |
337 // usage extension MUST NOT be asserted. | |
338 // | |
339 // TODO(eroman): Should "asserted" in the above apply only when the basic | |
340 // constraints extension is actually present? (In other words, if Basic | |
341 // Constraints was omitted, should keyCertSign be allowed even though it | |
342 // doesn't make sense?) | |
343 if (cert.has_key_usage && | |
344 KeyUsageAssertsBit(cert.key_usage, KeyUsageBit::KEY_CERT_SIGN)) { | |
345 return false; | |
346 } | |
347 | |
348 return true; | |
349 } | |
350 | |
351 } // namespace | |
352 | |
353 TrustedRoot::~TrustedRoot() {} | |
354 | |
355 TrustStore::TrustStore() {} | |
356 TrustStore::~TrustStore() {} | |
357 | |
358 bool VerifyCertificateChain(const std::vector<der::Input>& certs_der, | |
359 const TrustStore& trust_store, | |
360 const SignaturePolicy* signature_policy, | |
361 const der::GeneralizedTime& time) { | |
362 // An empty chain is invalid. Fail early since the rest of the code | |
363 // assumes a non-empty chain. | |
364 if (certs_der.empty()) | |
365 return false; | |
366 | |
367 // Fully parse all of the certificates. This is done up-front to simply | |
368 // access to properties. | |
369 std::vector<FullyParsedCert> certs(certs_der.size()); | |
370 for (size_t i = 0; i < certs_der.size(); ++i) { | |
371 if (!FullyParseCertificate(certs_der[i], &certs[i])) | |
372 return false; | |
373 } | |
374 | |
375 // TODO(eroman): Relax this and allow the caller to decide. | |
376 if (!VerifyTargetCertificateIsEndEntity(certs.front())) | |
377 return false; | |
378 | |
379 // The last intermediary must be issued by a trusted root. | |
380 if (!IsSignedByTrustAnchor(certs.back(), trust_store, signature_policy)) | |
381 return false; | |
382 | |
383 // Walk the chain in the forward direction (from end entity towards trust | |
384 // anchor) and check all properties of the certificate, including issuance. | |
385 size_t num_prev_self_issued_certs = 0; | |
386 for (size_t i = 0; i < certs_der.size(); ++i) { | |
387 // |cert| is the current certificate -- either the target or an | |
388 // intermediary, but never a root. | |
389 const auto& cert = certs[i]; | |
390 | |
391 if (!VerifyValidity(cert, time)) | |
392 return false; | |
393 | |
394 if (!VerifySignatureAlgorithsMatch(cert)) | |
395 return false; | |
396 | |
397 // With the exception of the target (i=0), every other certificate (i) must | |
398 // be a CA. This section verifies that it is in fact a CA, and that it | |
399 // issued certificate (i-1). | |
400 if (i > 0) { | |
401 // The previous certificate in the chain, that purports to be issued by | |
402 // |cert|. | |
403 const auto& subordinate_cert = certs[i - 1]; | |
404 | |
405 if (!VerifyKeyUsageForIssuer(cert)) | |
406 return false; | |
407 | |
408 if (!VerifyBasicConstraintsForIssuer(cert, i, num_prev_self_issued_certs)) | |
409 return false; | |
410 | |
411 if (!VerifyIssuerMatchesSubject(cert, subordinate_cert)) | |
412 return false; | |
413 | |
414 // Verify the digital signature. | |
415 if (!VerifySignedData(*subordinate_cert.signature_algorithm, | |
416 subordinate_cert.tbs_tlv, | |
417 subordinate_cert.signature_value, cert.spki_tlv, | |
418 signature_policy)) { | |
419 return false; | |
420 } | |
421 } | |
422 | |
423 // Keep track of how many certificates were self-issued, since some rules | |
424 // are different for self-issued certificates (notably pathlen for | |
425 // BasicConstraints). | |
426 if (IsSelfIssued(cert)) | |
427 num_prev_self_issued_certs++; | |
428 } | |
429 | |
430 // TODO(eroman): | |
431 // * Name constraints | |
432 // * Policy constraints | |
433 // * Extended Key Usage | |
434 | |
435 return true; | |
436 } | |
437 | |
438 } // namespace net | |
OLD | NEW |