| 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 <utility> | 
|  | 8 | 
|  | 9 #include "net/cert/internal/parse_certificate.h" | 
|  | 10 #include "net/cert/internal/signature_algorithm.h" | 
|  | 11 #include "net/cert/internal/signature_policy.h" | 
|  | 12 #include "net/cert/internal/verify_signed_data.h" | 
|  | 13 #include "net/der/input.h" | 
|  | 14 | 
|  | 15 namespace net { | 
|  | 16 | 
|  | 17 TrustedRoot::~TrustedRoot() {} | 
|  | 18 | 
|  | 19 TrustStore::TrustStore() {} | 
|  | 20 TrustStore::~TrustStore() {} | 
|  | 21 | 
|  | 22 // TODO(eroman): Move into net/der (duplicated this from test_helpers.cc). | 
|  | 23 der::Input InputFromString(const std::string* s) { | 
|  | 24   return der::Input(reinterpret_cast<const uint8_t*>(s->data()), s->size()); | 
|  | 25 } | 
|  | 26 | 
|  | 27 struct FullyParsedCert { | 
|  | 28   CertificateVersion version; | 
|  | 29   scoped_ptr<SignatureAlgorithm> signature_algorithm; | 
|  | 30   scoped_ptr<SignatureAlgorithm> tbs_signature_algorithm; | 
|  | 31   der::BitString signature_value; | 
|  | 32   der::Input tbs_tlv; | 
|  | 33 | 
|  | 34   // TODO(eroman): Everywhere this is consumed should also consider | 
|  | 35   // issuerAltName. | 
|  | 36   der::Input issuer_tlv; | 
|  | 37   der::GeneralizedTime validity_not_before; | 
|  | 38   der::GeneralizedTime validity_not_after; | 
|  | 39 | 
|  | 40   // TODO(eroman): Everywhere this is consumed should also consider | 
|  | 41   // subjectAltName. | 
|  | 42   der::Input subject_tlv; | 
|  | 43   der::Input spki_tlv; | 
|  | 44 | 
|  | 45   // Extensions | 
|  | 46 }; | 
|  | 47 | 
|  | 48 WARN_UNUSED_RESULT bool FullyParseCertificate(const der::Input& cert_tlv, | 
|  | 49                                               FullyParsedCert* out) { | 
|  | 50   ParsedCertificate cert; | 
|  | 51   if (!ParseCertificate(cert_tlv, &cert)) | 
|  | 52     return false; | 
|  | 53 | 
|  | 54   out->tbs_tlv = cert.tbs_certificate_tlv; | 
|  | 55   out->signature_value = cert.signature_value; | 
|  | 56   out->signature_algorithm = | 
|  | 57       SignatureAlgorithm::CreateFromDer(cert.signature_algorithm_tlv); | 
|  | 58 | 
|  | 59   if (!out->signature_algorithm) | 
|  | 60     return false; | 
|  | 61 | 
|  | 62   ParsedTbsCertificate tbs; | 
|  | 63   if (!ParseTbsCertificate(cert.tbs_certificate_tlv, &tbs)) | 
|  | 64     return false; | 
|  | 65 | 
|  | 66   out->tbs_signature_algorithm = | 
|  | 67       SignatureAlgorithm::CreateFromDer(tbs.signature_algorithm_tlv); | 
|  | 68   if (!out->tbs_signature_algorithm) | 
|  | 69     return false; | 
|  | 70 | 
|  | 71   out->issuer_tlv = tbs.issuer_tlv; | 
|  | 72   out->version = tbs.version; | 
|  | 73   out->spki_tlv = tbs.spki_tlv; | 
|  | 74   out->subject_tlv = tbs.subject_tlv; | 
|  | 75   out->validity_not_after = tbs.validity_not_after; | 
|  | 76   out->validity_not_before = tbs.validity_not_before; | 
|  | 77 | 
|  | 78   // Note that the serial_number, issuer_unique_id and subject_unique_id are | 
|  | 79   // unused by verification at this time. Invalid encodings will be rejected | 
|  | 80   // while parsing, but other then that are unused. | 
|  | 81 | 
|  | 82   return true; | 
|  | 83 } | 
|  | 84 | 
|  | 85 WARN_UNUSED_RESULT bool IsValidAtTime(const der::GeneralizedTime& time, | 
|  | 86                                       const der::GeneralizedTime& not_before, | 
|  | 87                                       const der::GeneralizedTime& not_after) { | 
|  | 88   // TODO(eroman): IMPORTANT: Return true if time >= not_before && time <= | 
|  | 89   // not_after | 
|  | 90   return true; | 
|  | 91 } | 
|  | 92 | 
|  | 93 WARN_UNUSED_RESULT bool NameMatches(const der::Input& name1, | 
|  | 94                                     const der::Input& name2) { | 
|  | 95   // TODO(eroman): Should account for normalization. | 
|  | 96   return name1.Equals(name2); | 
|  | 97 } | 
|  | 98 | 
|  | 99 WARN_UNUSED_RESULT bool IsSelfIssued(const FullyParsedCert& cert) { | 
|  | 100   return NameMatches(cert.subject_tlv, cert.issuer_tlv); | 
|  | 101 } | 
|  | 102 | 
|  | 103 // Finds a mapping in the trust for matching |name|, or returns nullptr. | 
|  | 104 // | 
|  | 105 // TODO(eroman): This implementation is linear in the size of the trust store, | 
|  | 106 // and also presumes that all names are unique (in practice could have multiple | 
|  | 107 // SPKIs with the same name). | 
|  | 108 WARN_UNUSED_RESULT const TrustedRoot* FindTrustedRootByName( | 
|  | 109     const TrustStore& trust_store, | 
|  | 110     const der::Input& name) { | 
|  | 111   for (const auto& root : trust_store.roots) { | 
|  | 112     if (NameMatches(name, InputFromString(&root.name))) | 
|  | 113       return &root; | 
|  | 114   } | 
|  | 115 | 
|  | 116   return nullptr; | 
|  | 117 } | 
|  | 118 | 
|  | 119 bool VerifyCertificateChain(const std::vector<der::Input>& certs_der, | 
|  | 120                             const TrustStore& trust_store, | 
|  | 121                             const SignaturePolicy* signature_policy, | 
|  | 122                             const der::GeneralizedTime time) { | 
|  | 123   // An empty chain is invalid input. Fail early since the rest of the code | 
|  | 124   // assumes a non-empty chain. | 
|  | 125   if (certs_der.empty()) | 
|  | 126     return false; | 
|  | 127 | 
|  | 128   // Fully parse all of the certificates. | 
|  | 129   std::vector<FullyParsedCert> certs(certs_der.size()); | 
|  | 130   for (size_t i = 0; i < certs_der.size(); ++i) { | 
|  | 131     if (!FullyParseCertificate(certs_der[i], &certs[i])) | 
|  | 132       return false; | 
|  | 133   } | 
|  | 134 | 
|  | 135   // Walk the chain in the forward direction (from end entity towards trust | 
|  | 136   // anchor) and check all properties of the certificate except for name | 
|  | 137   // constraints. | 
|  | 138   size_t num_prev_self_issued_certs = 0; | 
|  | 139   for (size_t i = 0; i < certs_der.size(); ++i) { | 
|  | 140     const auto& cert = certs[i]; | 
|  | 141 | 
|  | 142     // Check for expiration. | 
|  | 143     if (!IsValidAtTime(time, cert.validity_not_before, cert.validity_not_after)) | 
|  | 144       return false; | 
|  | 145 | 
|  | 146     // Verify that the signature algorithm provided in tbsCertificate | 
|  | 147     // matches that provided in the certificate. This requirement comes from | 
|  | 148     // RFC 5280 section 4.1.1.2. | 
|  | 149     if (!cert.signature_algorithm->Equals(*cert.tbs_signature_algorithm)) | 
|  | 150       return false; | 
|  | 151 | 
|  | 152     // TODO: use is_self_issued | 
|  | 153 | 
|  | 154     // TODO(eroman): the usage must allow signing if i > 0. Otherwise .... | 
|  | 155 | 
|  | 156     // Verify that the previous certificate (i-1) was signed by the current one | 
|  | 157     // (i). | 
|  | 158     // Note that the signature for the final certificate in the chain is checked | 
|  | 159     // separately outside this loop. | 
|  | 160     if (i > 0) { | 
|  | 161       const auto& subordinate_cert = certs[i - 1]; | 
|  | 162 | 
|  | 163       // The issuer and subject must match. | 
|  | 164       if (!NameMatches(cert.subject_tlv, subordinate_cert.issuer_tlv)) | 
|  | 165         return false; | 
|  | 166 | 
|  | 167       // The digital signature must be correct. | 
|  | 168       if (!VerifySignedData(*subordinate_cert.signature_algorithm, | 
|  | 169                             subordinate_cert.tbs_tlv, | 
|  | 170                             subordinate_cert.signature_value, cert.spki_tlv, | 
|  | 171                             signature_policy)) { | 
|  | 172         return false; | 
|  | 173       } | 
|  | 174 | 
|  | 175       // The last certificate must chain up to a trust anchor. | 
|  | 176       if (i + 1 == certs.size()) { | 
|  | 177         const TrustedRoot* trusted_root = | 
|  | 178             FindTrustedRootByName(trust_store, cert.issuer_tlv); | 
|  | 179 | 
|  | 180         if (!trusted_root) | 
|  | 181           return false; | 
|  | 182 | 
|  | 183         if (!VerifySignedData( | 
|  | 184                 *cert.signature_algorithm, cert.tbs_tlv, cert.signature_value, | 
|  | 185                 InputFromString(&trusted_root->spki), signature_policy)) { | 
|  | 186           return false; | 
|  | 187         } | 
|  | 188       } | 
|  | 189     } | 
|  | 190 | 
|  | 191     // Keep track of how many certificates were self-issued, since some of the | 
|  | 192     // rules are different for self-issued certificates. | 
|  | 193     bool is_self_issued = IsSelfIssued(cert); | 
|  | 194     if (is_self_issued) | 
|  | 195       num_prev_self_issued_certs++; | 
|  | 196   } | 
|  | 197 | 
|  | 198   // TODO(eroman): Verify that no certificate in the chain violates the name | 
|  | 199   // constraints extension. This can be done by walking the chain in the | 
|  | 200   // reverse direction. | 
|  | 201 | 
|  | 202   return true; | 
|  | 203 } | 
|  | 204 | 
|  | 205 }  // namespace net | 
| OLD | NEW | 
|---|