cert_verify_proc_builtin.cc 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922
  1. // Copyright (c) 2017 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. #include "net/cert/cert_verify_proc_builtin.h"
  5. #include <memory>
  6. #include <string>
  7. #include <vector>
  8. #include "base/logging.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/strings/string_piece.h"
  11. #include "base/values.h"
  12. #include "crypto/sha2.h"
  13. #include "net/base/net_errors.h"
  14. #include "net/cert/cert_net_fetcher.h"
  15. #include "net/cert/cert_status_flags.h"
  16. #include "net/cert/cert_verifier.h"
  17. #include "net/cert/cert_verify_proc.h"
  18. #include "net/cert/cert_verify_result.h"
  19. #include "net/cert/ev_root_ca_metadata.h"
  20. #include "net/cert/internal/cert_issuer_source_aia.h"
  21. #include "net/cert/internal/revocation_checker.h"
  22. #include "net/cert/internal/system_trust_store.h"
  23. #include "net/cert/known_roots.h"
  24. #include "net/cert/pki/cert_errors.h"
  25. #include "net/cert/pki/cert_issuer_source_static.h"
  26. #include "net/cert/pki/common_cert_errors.h"
  27. #include "net/cert/pki/parsed_certificate.h"
  28. #include "net/cert/pki/path_builder.h"
  29. #include "net/cert/pki/simple_path_builder_delegate.h"
  30. #include "net/cert/pki/trust_store_collection.h"
  31. #include "net/cert/pki/trust_store_in_memory.h"
  32. #include "net/cert/test_root_certs.h"
  33. #include "net/cert/x509_certificate.h"
  34. #include "net/cert/x509_util.h"
  35. #include "net/der/encode_values.h"
  36. #include "net/log/net_log_values.h"
  37. #include "net/log/net_log_with_source.h"
  38. namespace net {
  39. namespace {
  40. // Very conservative iteration count limit.
  41. // TODO(https://crbug.com/634470): Make this smaller.
  42. constexpr uint32_t kPathBuilderIterationLimit = 25000;
  43. constexpr base::TimeDelta kMaxVerificationTime = base::Seconds(60);
  44. constexpr base::TimeDelta kPerAttemptMinVerificationTimeLimit =
  45. base::Seconds(5);
  46. DEFINE_CERT_ERROR_ID(kPathLacksEVPolicy, "Path does not have an EV policy");
  47. const void* kResultDebugDataKey = &kResultDebugDataKey;
  48. base::Value NetLogCertParams(const CRYPTO_BUFFER* cert_handle,
  49. const CertErrors& errors) {
  50. base::Value::Dict results;
  51. std::string pem_encoded;
  52. if (X509Certificate::GetPEMEncodedFromDER(
  53. x509_util::CryptoBufferAsStringPiece(cert_handle), &pem_encoded)) {
  54. results.Set("certificate", pem_encoded);
  55. }
  56. std::string errors_string = errors.ToDebugString();
  57. if (!errors_string.empty())
  58. results.Set("errors", errors_string);
  59. return base::Value(std::move(results));
  60. }
  61. #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
  62. base::Value NetLogChromeRootStoreVersion(int64_t chrome_root_store_version) {
  63. base::Value::Dict results;
  64. results.Set("version_major", NetLogNumberValue(chrome_root_store_version));
  65. return base::Value(std::move(results));
  66. }
  67. #endif
  68. base::Value PEMCertListValue(const ParsedCertificateList& certs) {
  69. base::Value value(base::Value::Type::LIST);
  70. for (const auto& cert : certs) {
  71. std::string pem;
  72. X509Certificate::GetPEMEncodedFromDER(cert->der_cert().AsStringPiece(),
  73. &pem);
  74. value.GetList().Append(std::move(pem));
  75. }
  76. return value;
  77. }
  78. base::Value NetLogPathBuilderResultPath(
  79. const CertPathBuilderResultPath& result_path) {
  80. base::Value::Dict dict;
  81. dict.Set("is_valid", result_path.IsValid());
  82. dict.Set("last_cert_trust",
  83. static_cast<int>(result_path.last_cert_trust.type));
  84. dict.Set("certificates", PEMCertListValue(result_path.certs));
  85. // TODO(crbug.com/634484): netlog user_constrained_policy_set.
  86. std::string errors_string =
  87. result_path.errors.ToDebugString(result_path.certs);
  88. if (!errors_string.empty())
  89. dict.Set("errors", errors_string);
  90. return base::Value(std::move(dict));
  91. }
  92. base::Value NetLogPathBuilderResult(const CertPathBuilder::Result& result) {
  93. base::Value::Dict dict;
  94. // TODO(crbug.com/634484): include debug data (or just have things netlog it
  95. // directly).
  96. dict.Set("has_valid_path", result.HasValidPath());
  97. dict.Set("best_result_index", static_cast<int>(result.best_result_index));
  98. if (result.exceeded_iteration_limit)
  99. dict.Set("exceeded_iteration_limit", true);
  100. if (result.exceeded_deadline)
  101. dict.Set("exceeded_deadline", true);
  102. return base::Value(std::move(dict));
  103. }
  104. RevocationPolicy NoRevocationChecking() {
  105. RevocationPolicy policy;
  106. policy.check_revocation = false;
  107. policy.networking_allowed = false;
  108. policy.crl_allowed = false;
  109. policy.allow_missing_info = true;
  110. policy.allow_unable_to_check = true;
  111. return policy;
  112. }
  113. // Gets the set of policy OIDs in |cert| that are recognized as EV OIDs for some
  114. // root.
  115. void GetEVPolicyOids(const EVRootCAMetadata* ev_metadata,
  116. const ParsedCertificate* cert,
  117. std::set<der::Input>* oids) {
  118. oids->clear();
  119. if (!cert->has_policy_oids())
  120. return;
  121. for (const der::Input& oid : cert->policy_oids()) {
  122. if (ev_metadata->IsEVPolicyOIDGivenBytes(oid))
  123. oids->insert(oid);
  124. }
  125. }
  126. // Returns true if |cert| could be an EV certificate, based on its policies
  127. // extension. A return of false means it definitely is not an EV certificate,
  128. // whereas a return of true means it could be EV.
  129. bool IsEVCandidate(const EVRootCAMetadata* ev_metadata,
  130. const ParsedCertificate* cert) {
  131. std::set<der::Input> oids;
  132. GetEVPolicyOids(ev_metadata, cert, &oids);
  133. return !oids.empty();
  134. }
  135. // CertVerifyProcTrustStore wraps a SystemTrustStore with additional trust
  136. // anchors and TestRootCerts.
  137. class CertVerifyProcTrustStore {
  138. public:
  139. // |system_trust_store| must outlive this object.
  140. explicit CertVerifyProcTrustStore(SystemTrustStore* system_trust_store)
  141. : system_trust_store_(system_trust_store) {
  142. trust_store_.AddTrustStore(&additional_trust_store_);
  143. trust_store_.AddTrustStore(system_trust_store_->GetTrustStore());
  144. // When running in test mode, also layer in the test-only root certificates.
  145. //
  146. // Note that this integration requires TestRootCerts::HasInstance() to be
  147. // true by the time CertVerifyProcTrustStore is created - a limitation which
  148. // is acceptable for the test-only code that consumes this.
  149. if (TestRootCerts::HasInstance()) {
  150. trust_store_.AddTrustStore(
  151. TestRootCerts::GetInstance()->test_trust_store());
  152. }
  153. }
  154. TrustStore* trust_store() { return &trust_store_; }
  155. void AddTrustAnchor(scoped_refptr<ParsedCertificate> cert) {
  156. additional_trust_store_.AddTrustAnchor(std::move(cert));
  157. }
  158. bool IsKnownRoot(const ParsedCertificate* trust_anchor) const {
  159. return system_trust_store_->IsKnownRoot(trust_anchor);
  160. }
  161. bool IsAdditionalTrustAnchor(const ParsedCertificate* trust_anchor) const {
  162. return additional_trust_store_.Contains(trust_anchor);
  163. }
  164. private:
  165. raw_ptr<SystemTrustStore> system_trust_store_;
  166. TrustStoreInMemory additional_trust_store_;
  167. TrustStoreCollection trust_store_;
  168. };
  169. // Enum for whether path building is attempting to verify a certificate as EV or
  170. // as DV.
  171. enum class VerificationType {
  172. kEV, // Extended Validation
  173. kDV, // Domain Validation
  174. };
  175. class PathBuilderDelegateDataImpl : public CertPathBuilderDelegateData {
  176. public:
  177. ~PathBuilderDelegateDataImpl() override = default;
  178. static const PathBuilderDelegateDataImpl* Get(
  179. const CertPathBuilderResultPath& path) {
  180. return static_cast<PathBuilderDelegateDataImpl*>(path.delegate_data.get());
  181. }
  182. static PathBuilderDelegateDataImpl* GetOrCreate(
  183. CertPathBuilderResultPath* path) {
  184. if (!path->delegate_data)
  185. path->delegate_data = std::make_unique<PathBuilderDelegateDataImpl>();
  186. return static_cast<PathBuilderDelegateDataImpl*>(path->delegate_data.get());
  187. }
  188. OCSPVerifyResult stapled_ocsp_verify_result;
  189. };
  190. // TODO(eroman): The path building code in this file enforces its idea of weak
  191. // keys, and signature algorithms, but separately cert_verify_proc.cc also
  192. // checks the chains with its own policy. These policies must be aligned to
  193. // give path building the best chance of finding a good path.
  194. class PathBuilderDelegateImpl : public SimplePathBuilderDelegate {
  195. public:
  196. // Uses the default policy from SimplePathBuilderDelegate, which requires RSA
  197. // keys to be at least 1024-bits large, and optionally accepts SHA1
  198. // certificates.
  199. PathBuilderDelegateImpl(const CRLSet* crl_set,
  200. CertNetFetcher* net_fetcher,
  201. VerificationType verification_type,
  202. SimplePathBuilderDelegate::DigestPolicy digest_policy,
  203. int flags,
  204. const CertVerifyProcTrustStore* trust_store,
  205. base::StringPiece stapled_leaf_ocsp_response,
  206. const EVRootCAMetadata* ev_metadata,
  207. bool* checked_revocation_for_some_path)
  208. : SimplePathBuilderDelegate(1024, digest_policy),
  209. crl_set_(crl_set),
  210. net_fetcher_(net_fetcher),
  211. verification_type_(verification_type),
  212. flags_(flags),
  213. trust_store_(trust_store),
  214. stapled_leaf_ocsp_response_(stapled_leaf_ocsp_response),
  215. ev_metadata_(ev_metadata),
  216. checked_revocation_for_some_path_(checked_revocation_for_some_path) {}
  217. // This is called for each built chain, including ones which failed. It is
  218. // responsible for adding errors to the built chain if it is not acceptable.
  219. void CheckPathAfterVerification(const CertPathBuilder& path_builder,
  220. CertPathBuilderResultPath* path) override {
  221. // If the path is already invalid, don't check revocation status. The chain
  222. // is expected to be valid when doing revocation checks (since for instance
  223. // the correct issuer for a certificate may need to be known). Also if
  224. // certificates are already expired, obtaining their revocation status may
  225. // fail.
  226. //
  227. // TODO(eroman): When CertVerifyProcBuiltin fails to find a valid path,
  228. // whatever (partial/incomplete) path it does return should
  229. // minimally be checked with the CRLSet.
  230. if (!path->IsValid())
  231. return;
  232. // If EV was requested the certificate must chain to a recognized EV root
  233. // and have one of its recognized EV policy OIDs.
  234. if (verification_type_ == VerificationType::kEV) {
  235. if (!ConformsToEVPolicy(path)) {
  236. path->errors.GetErrorsForCert(0)->AddError(kPathLacksEVPolicy);
  237. return;
  238. }
  239. }
  240. // Select an appropriate revocation policy for this chain based on the
  241. // verifier flags and root.
  242. RevocationPolicy policy = ChooseRevocationPolicy(path->certs);
  243. // Check for revocations using the CRLSet.
  244. switch (
  245. CheckChainRevocationUsingCRLSet(crl_set_, path->certs, &path->errors)) {
  246. case CRLSet::Result::REVOKED:
  247. return;
  248. case CRLSet::Result::GOOD:
  249. break;
  250. case CRLSet::Result::UNKNOWN:
  251. // CRLSet was inconclusive.
  252. break;
  253. }
  254. if (policy.check_revocation)
  255. *checked_revocation_for_some_path_ = true;
  256. // Check the revocation status for each certificate in the chain according
  257. // to |policy|. Depending on the policy, errors will be added to the
  258. // respective certificates, so |errors->ContainsHighSeverityErrors()| will
  259. // reflect the revocation status of the chain after this call.
  260. CheckValidatedChainRevocation(
  261. path->certs, policy, path_builder.deadline(),
  262. stapled_leaf_ocsp_response_, net_fetcher_, &path->errors,
  263. &PathBuilderDelegateDataImpl::GetOrCreate(path)
  264. ->stapled_ocsp_verify_result);
  265. }
  266. private:
  267. // Selects a revocation policy based on the CertVerifier flags and the given
  268. // certificate chain.
  269. RevocationPolicy ChooseRevocationPolicy(const ParsedCertificateList& certs) {
  270. // Use hard-fail revocation checking for local trust anchors, if requested
  271. // by the load flag and the chain uses a non-public root.
  272. if ((flags_ & CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) &&
  273. !certs.empty() && !trust_store_->IsKnownRoot(certs.back().get())) {
  274. RevocationPolicy policy;
  275. policy.check_revocation = true;
  276. policy.networking_allowed = true;
  277. policy.crl_allowed = true;
  278. policy.allow_missing_info = false;
  279. policy.allow_unable_to_check = false;
  280. return policy;
  281. }
  282. // Use soft-fail revocation checking for VERIFY_REV_CHECKING_ENABLED.
  283. if (flags_ & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED) {
  284. RevocationPolicy policy;
  285. policy.check_revocation = true;
  286. policy.networking_allowed = true;
  287. // Publicly trusted certs are required to have OCSP by the Baseline
  288. // Requirements and CRLs can be quite large, so disable the fallback to
  289. // CRLs for chains to known roots.
  290. policy.crl_allowed =
  291. !certs.empty() && !trust_store_->IsKnownRoot(certs.back().get());
  292. policy.allow_missing_info = true;
  293. policy.allow_unable_to_check = true;
  294. return policy;
  295. }
  296. return NoRevocationChecking();
  297. }
  298. // Returns true if |path| chains to an EV root, and the chain conforms to one
  299. // of its EV policy OIDs. When building paths all candidate EV policy OIDs
  300. // were requested, so it is just a matter of testing each of the policies the
  301. // chain conforms to.
  302. bool ConformsToEVPolicy(const CertPathBuilderResultPath* path) {
  303. const ParsedCertificate* root = path->GetTrustedCert();
  304. if (!root)
  305. return false;
  306. SHA256HashValue root_fingerprint;
  307. crypto::SHA256HashString(root->der_cert().AsStringPiece(),
  308. root_fingerprint.data,
  309. sizeof(root_fingerprint.data));
  310. for (const der::Input& oid : path->user_constrained_policy_set) {
  311. if (ev_metadata_->HasEVPolicyOIDGivenBytes(root_fingerprint, oid))
  312. return true;
  313. }
  314. return false;
  315. }
  316. // The CRLSet may be null.
  317. raw_ptr<const CRLSet> crl_set_;
  318. raw_ptr<CertNetFetcher> net_fetcher_;
  319. const VerificationType verification_type_;
  320. const int flags_;
  321. raw_ptr<const CertVerifyProcTrustStore> trust_store_;
  322. const base::StringPiece stapled_leaf_ocsp_response_;
  323. raw_ptr<const EVRootCAMetadata> ev_metadata_;
  324. raw_ptr<bool> checked_revocation_for_some_path_;
  325. };
  326. class CertVerifyProcBuiltin : public CertVerifyProc {
  327. public:
  328. CertVerifyProcBuiltin(scoped_refptr<CertNetFetcher> net_fetcher,
  329. std::unique_ptr<SystemTrustStore> system_trust_store);
  330. bool SupportsAdditionalTrustAnchors() const override;
  331. protected:
  332. ~CertVerifyProcBuiltin() override;
  333. private:
  334. int VerifyInternal(X509Certificate* cert,
  335. const std::string& hostname,
  336. const std::string& ocsp_response,
  337. const std::string& sct_list,
  338. int flags,
  339. CRLSet* crl_set,
  340. const CertificateList& additional_trust_anchors,
  341. CertVerifyResult* verify_result,
  342. const NetLogWithSource& net_log) override;
  343. scoped_refptr<CertNetFetcher> net_fetcher_;
  344. std::unique_ptr<SystemTrustStore> system_trust_store_;
  345. };
  346. CertVerifyProcBuiltin::CertVerifyProcBuiltin(
  347. scoped_refptr<CertNetFetcher> net_fetcher,
  348. std::unique_ptr<SystemTrustStore> system_trust_store)
  349. : net_fetcher_(std::move(net_fetcher)),
  350. system_trust_store_(std::move(system_trust_store)) {
  351. DCHECK(system_trust_store_);
  352. }
  353. CertVerifyProcBuiltin::~CertVerifyProcBuiltin() = default;
  354. bool CertVerifyProcBuiltin::SupportsAdditionalTrustAnchors() const {
  355. return true;
  356. }
  357. scoped_refptr<ParsedCertificate> ParseCertificateFromBuffer(
  358. CRYPTO_BUFFER* cert_handle,
  359. CertErrors* errors) {
  360. return ParsedCertificate::Create(bssl::UpRef(cert_handle),
  361. x509_util::DefaultParseCertificateOptions(),
  362. errors);
  363. }
  364. void AddIntermediatesToIssuerSource(X509Certificate* x509_cert,
  365. CertIssuerSourceStatic* intermediates,
  366. const NetLogWithSource& net_log) {
  367. for (const auto& intermediate : x509_cert->intermediate_buffers()) {
  368. CertErrors errors;
  369. scoped_refptr<ParsedCertificate> cert =
  370. ParseCertificateFromBuffer(intermediate.get(), &errors);
  371. // TODO(crbug.com/634484): this duplicates the logging of the input chain
  372. // maybe should only log if there is a parse error/warning?
  373. net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_INPUT_CERT, [&] {
  374. return NetLogCertParams(intermediate.get(), errors);
  375. });
  376. if (cert)
  377. intermediates->AddCert(std::move(cert));
  378. }
  379. }
  380. // Appends the SHA256 hashes of |spki_bytes| to |*hashes|.
  381. // TODO(eroman): Hashes are also calculated at other times (such as when
  382. // checking CRLSet). Consider caching to avoid recalculating (say
  383. // in the delegate's PathInfo).
  384. void AppendPublicKeyHashes(const der::Input& spki_bytes,
  385. HashValueVector* hashes) {
  386. HashValue sha256(HASH_VALUE_SHA256);
  387. crypto::SHA256HashString(spki_bytes.AsStringPiece(), sha256.data(),
  388. crypto::kSHA256Length);
  389. hashes->push_back(sha256);
  390. }
  391. // Appends the SubjectPublicKeyInfo hashes for all certificates in
  392. // |path| to |*hashes|.
  393. void AppendPublicKeyHashes(const CertPathBuilderResultPath& path,
  394. HashValueVector* hashes) {
  395. for (const scoped_refptr<ParsedCertificate>& cert : path.certs)
  396. AppendPublicKeyHashes(cert->tbs().spki_tlv, hashes);
  397. }
  398. // Sets the bits on |cert_status| for all the errors present in |errors| (the
  399. // errors for a particular path).
  400. void MapPathBuilderErrorsToCertStatus(const CertPathErrors& errors,
  401. CertStatus* cert_status) {
  402. // If there were no errors, nothing to do.
  403. if (!errors.ContainsHighSeverityErrors())
  404. return;
  405. if (errors.ContainsError(cert_errors::kCertificateRevoked))
  406. *cert_status |= CERT_STATUS_REVOKED;
  407. if (errors.ContainsError(cert_errors::kNoRevocationMechanism))
  408. *cert_status |= CERT_STATUS_NO_REVOCATION_MECHANISM;
  409. if (errors.ContainsError(cert_errors::kUnableToCheckRevocation))
  410. *cert_status |= CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
  411. if (errors.ContainsError(cert_errors::kUnacceptablePublicKey))
  412. *cert_status |= CERT_STATUS_WEAK_KEY;
  413. if (errors.ContainsError(cert_errors::kValidityFailedNotAfter) ||
  414. errors.ContainsError(cert_errors::kValidityFailedNotBefore)) {
  415. *cert_status |= CERT_STATUS_DATE_INVALID;
  416. }
  417. if (errors.ContainsError(cert_errors::kDistrustedByTrustStore) ||
  418. errors.ContainsError(cert_errors::kVerifySignedDataFailed) ||
  419. errors.ContainsError(cert_errors::kNoIssuersFound) ||
  420. errors.ContainsError(cert_errors::kDeadlineExceeded) ||
  421. errors.ContainsError(cert_errors::kIterationLimitExceeded)) {
  422. *cert_status |= CERT_STATUS_AUTHORITY_INVALID;
  423. }
  424. // IMPORTANT: If the path was invalid for a reason that was not
  425. // explicity checked above, set a general error. This is important as
  426. // |cert_status| is what ultimately indicates whether verification was
  427. // successful or not (absense of errors implies success).
  428. if (!IsCertStatusError(*cert_status))
  429. *cert_status |= CERT_STATUS_INVALID;
  430. }
  431. bssl::UniquePtr<CRYPTO_BUFFER> CreateCertBuffers(
  432. const scoped_refptr<ParsedCertificate>& certificate) {
  433. return X509Certificate::CreateCertBufferFromBytes(
  434. certificate->der_cert().AsSpan());
  435. }
  436. // Creates a X509Certificate (chain) to return as the verified result.
  437. //
  438. // * |target_cert|: The original X509Certificate that was passed in to
  439. // VerifyInternal()
  440. // * |path|: The result (possibly failed) from path building.
  441. scoped_refptr<X509Certificate> CreateVerifiedCertChain(
  442. X509Certificate* target_cert,
  443. const CertPathBuilderResultPath& path) {
  444. std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
  445. // Skip the first certificate in the path as that is the target certificate
  446. for (size_t i = 1; i < path.certs.size(); ++i)
  447. intermediates.push_back(CreateCertBuffers(path.certs[i]));
  448. scoped_refptr<X509Certificate> result = X509Certificate::CreateFromBuffer(
  449. bssl::UpRef(target_cert->cert_buffer()), std::move(intermediates));
  450. // |target_cert| was already successfully parsed, so this should never fail.
  451. DCHECK(result);
  452. return result;
  453. }
  454. // Describes the parameters for a single path building attempt. Path building
  455. // may be re-tried with different parameters for EV and for accepting SHA1
  456. // certificates.
  457. struct BuildPathAttempt {
  458. BuildPathAttempt(VerificationType verification_type,
  459. SimplePathBuilderDelegate::DigestPolicy digest_policy)
  460. : verification_type(verification_type), digest_policy(digest_policy) {}
  461. explicit BuildPathAttempt(VerificationType verification_type)
  462. : BuildPathAttempt(verification_type,
  463. SimplePathBuilderDelegate::DigestPolicy::kStrong) {}
  464. VerificationType verification_type;
  465. SimplePathBuilderDelegate::DigestPolicy digest_policy;
  466. };
  467. CertPathBuilder::Result TryBuildPath(
  468. const scoped_refptr<ParsedCertificate>& target,
  469. CertIssuerSourceStatic* intermediates,
  470. CertVerifyProcTrustStore* trust_store,
  471. const der::GeneralizedTime& der_verification_time,
  472. base::TimeTicks deadline,
  473. VerificationType verification_type,
  474. SimplePathBuilderDelegate::DigestPolicy digest_policy,
  475. int flags,
  476. const std::string& ocsp_response,
  477. const CRLSet* crl_set,
  478. CertNetFetcher* net_fetcher,
  479. const EVRootCAMetadata* ev_metadata,
  480. bool* checked_revocation) {
  481. // Path building will require candidate paths to conform to at least one of
  482. // the policies in |user_initial_policy_set|.
  483. std::set<der::Input> user_initial_policy_set;
  484. if (verification_type == VerificationType::kEV) {
  485. GetEVPolicyOids(ev_metadata, target.get(), &user_initial_policy_set);
  486. // TODO(crbug.com/634484): netlog user_initial_policy_set.
  487. } else {
  488. user_initial_policy_set = {der::Input(kAnyPolicyOid)};
  489. }
  490. PathBuilderDelegateImpl path_builder_delegate(
  491. crl_set, net_fetcher, verification_type, digest_policy, flags,
  492. trust_store, ocsp_response, ev_metadata, checked_revocation);
  493. // Initialize the path builder.
  494. CertPathBuilder path_builder(
  495. target, trust_store->trust_store(), &path_builder_delegate,
  496. der_verification_time, KeyPurpose::SERVER_AUTH,
  497. InitialExplicitPolicy::kFalse, user_initial_policy_set,
  498. InitialPolicyMappingInhibit::kFalse, InitialAnyPolicyInhibit::kFalse);
  499. // Allow the path builder to discover the explicitly provided intermediates in
  500. // |input_cert|.
  501. path_builder.AddCertIssuerSource(intermediates);
  502. // Allow the path builder to discover intermediates through AIA fetching.
  503. // TODO(crbug.com/634484): hook up netlog to AIA.
  504. std::unique_ptr<CertIssuerSourceAia> aia_cert_issuer_source;
  505. if (net_fetcher) {
  506. aia_cert_issuer_source = std::make_unique<CertIssuerSourceAia>(net_fetcher);
  507. path_builder.AddCertIssuerSource(aia_cert_issuer_source.get());
  508. } else {
  509. LOG(ERROR) << "No net_fetcher for performing AIA chasing.";
  510. }
  511. path_builder.SetIterationLimit(kPathBuilderIterationLimit);
  512. path_builder.SetDeadline(deadline);
  513. return path_builder.Run();
  514. }
  515. int AssignVerifyResult(X509Certificate* input_cert,
  516. const std::string& hostname,
  517. CertPathBuilder::Result& result,
  518. VerificationType verification_type,
  519. bool checked_revocation_for_some_path,
  520. CertVerifyProcTrustStore* trust_store,
  521. CertVerifyResult* verify_result) {
  522. // Clone debug data from the CertPathBuilder::Result into CertVerifyResult.
  523. verify_result->CloneDataFrom(result);
  524. const CertPathBuilderResultPath* best_path_possibly_invalid =
  525. result.GetBestPathPossiblyInvalid();
  526. if (!best_path_possibly_invalid) {
  527. // TODO(crbug.com/634443): What errors to communicate? Maybe the path
  528. // builder should always return some partial path (even if just containing
  529. // the target), then there is a CertErrors to test.
  530. verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
  531. return ERR_CERT_AUTHORITY_INVALID;
  532. }
  533. const CertPathBuilderResultPath& partial_path = *best_path_possibly_invalid;
  534. AppendPublicKeyHashes(partial_path, &verify_result->public_key_hashes);
  535. for (auto it = verify_result->public_key_hashes.rbegin();
  536. it != verify_result->public_key_hashes.rend() &&
  537. !verify_result->is_issued_by_known_root;
  538. ++it) {
  539. verify_result->is_issued_by_known_root =
  540. GetNetTrustAnchorHistogramIdForSPKI(*it) != 0;
  541. }
  542. bool path_is_valid = partial_path.IsValid();
  543. const ParsedCertificate* trusted_cert = partial_path.GetTrustedCert();
  544. if (trusted_cert) {
  545. if (!verify_result->is_issued_by_known_root) {
  546. verify_result->is_issued_by_known_root =
  547. trust_store->IsKnownRoot(trusted_cert);
  548. }
  549. verify_result->is_issued_by_additional_trust_anchor =
  550. trust_store->IsAdditionalTrustAnchor(trusted_cert);
  551. }
  552. if (path_is_valid && (verification_type == VerificationType::kEV)) {
  553. verify_result->cert_status |= CERT_STATUS_IS_EV;
  554. }
  555. // TODO(eroman): Add documentation for the meaning of
  556. // CERT_STATUS_REV_CHECKING_ENABLED. Based on the current tests it appears to
  557. // mean whether revocation checking was attempted during path building,
  558. // although does not necessarily mean that revocation checking was done for
  559. // the final returned path.
  560. if (checked_revocation_for_some_path)
  561. verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
  562. verify_result->verified_cert =
  563. CreateVerifiedCertChain(input_cert, partial_path);
  564. MapPathBuilderErrorsToCertStatus(partial_path.errors,
  565. &verify_result->cert_status);
  566. // TODO(eroman): Is it possible that IsValid() fails but no errors were set in
  567. // partial_path.errors?
  568. CHECK(path_is_valid || IsCertStatusError(verify_result->cert_status));
  569. if (!path_is_valid) {
  570. LOG(ERROR) << "CertVerifyProcBuiltin for " << hostname << " failed:\n"
  571. << partial_path.errors.ToDebugString(partial_path.certs);
  572. }
  573. const PathBuilderDelegateDataImpl* delegate_data =
  574. PathBuilderDelegateDataImpl::Get(partial_path);
  575. if (delegate_data)
  576. verify_result->ocsp_result = delegate_data->stapled_ocsp_verify_result;
  577. return IsCertStatusError(verify_result->cert_status)
  578. ? MapCertStatusToNetError(verify_result->cert_status)
  579. : OK;
  580. }
  581. // Returns true if retrying path building with a less stringent signature
  582. // algorithm *might* successfully build a path, based on the earlier failed
  583. // |result|.
  584. //
  585. // This implementation is simplistic, and looks only for the presence of the
  586. // kUnacceptableSignatureAlgorithm error somewhere among the built paths.
  587. bool CanTryAgainWithWeakerDigestPolicy(const CertPathBuilder::Result& result) {
  588. return result.AnyPathContainsError(
  589. cert_errors::kUnacceptableSignatureAlgorithm);
  590. }
  591. int CertVerifyProcBuiltin::VerifyInternal(
  592. X509Certificate* input_cert,
  593. const std::string& hostname,
  594. const std::string& ocsp_response,
  595. const std::string& sct_list,
  596. int flags,
  597. CRLSet* crl_set,
  598. const CertificateList& additional_trust_anchors,
  599. CertVerifyResult* verify_result,
  600. const NetLogWithSource& net_log) {
  601. // VerifyInternal() is expected to carry out verifications using the current
  602. // time stamp.
  603. base::Time verification_time = base::Time::Now();
  604. base::TimeTicks deadline = base::TimeTicks::Now() + kMaxVerificationTime;
  605. der::GeneralizedTime der_verification_time;
  606. if (!der::EncodeTimeAsGeneralizedTime(verification_time,
  607. &der_verification_time)) {
  608. // This shouldn't be possible.
  609. // We don't really have a good error code for this type of error.
  610. verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
  611. return ERR_CERT_AUTHORITY_INVALID;
  612. }
  613. absl::optional<int64_t> chrome_root_store_version_opt = absl::nullopt;
  614. #if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
  615. int64_t chrome_root_store_version =
  616. system_trust_store_->chrome_root_store_version();
  617. if (chrome_root_store_version != 0) {
  618. net_log.AddEvent(
  619. NetLogEventType::CERT_VERIFY_PROC_CHROME_ROOT_STORE_VERSION, [&] {
  620. return NetLogChromeRootStoreVersion(chrome_root_store_version);
  621. });
  622. chrome_root_store_version_opt = chrome_root_store_version;
  623. }
  624. #endif
  625. CertVerifyProcBuiltinResultDebugData::Create(verify_result, verification_time,
  626. der_verification_time,
  627. chrome_root_store_version_opt);
  628. // Parse the target certificate.
  629. scoped_refptr<ParsedCertificate> target;
  630. {
  631. CertErrors parsing_errors;
  632. target =
  633. ParseCertificateFromBuffer(input_cert->cert_buffer(), &parsing_errors);
  634. // TODO(crbug.com/634484): this duplicates the logging of the input chain
  635. // maybe should only log if there is a parse error/warning?
  636. net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_TARGET_CERT, [&] {
  637. return NetLogCertParams(input_cert->cert_buffer(), parsing_errors);
  638. });
  639. if (!target) {
  640. verify_result->cert_status |= CERT_STATUS_INVALID;
  641. return ERR_CERT_INVALID;
  642. }
  643. }
  644. // Parse the provided intermediates.
  645. CertIssuerSourceStatic intermediates;
  646. AddIntermediatesToIssuerSource(input_cert, &intermediates, net_log);
  647. // Parse the additional trust anchors and setup trust store.
  648. CertVerifyProcTrustStore trust_store(system_trust_store_.get());
  649. for (const auto& x509_cert : additional_trust_anchors) {
  650. CertErrors parsing_errors;
  651. scoped_refptr<ParsedCertificate> cert =
  652. ParseCertificateFromBuffer(x509_cert->cert_buffer(), &parsing_errors);
  653. if (cert)
  654. trust_store.AddTrustAnchor(std::move(cert));
  655. // TODO(crbug.com/634484): this duplicates the logging of the
  656. // additional_trust_anchors maybe should only log if there is a parse
  657. // error/warning?
  658. net_log.AddEvent(
  659. NetLogEventType::CERT_VERIFY_PROC_ADDITIONAL_TRUST_ANCHOR, [&] {
  660. return NetLogCertParams(x509_cert->cert_buffer(), parsing_errors);
  661. });
  662. }
  663. // Get the global dependencies.
  664. const EVRootCAMetadata* ev_metadata = EVRootCAMetadata::GetInstance();
  665. // This boolean tracks whether online revocation checking was performed for
  666. // *any* of the built paths, and not just the final path returned (used for
  667. // setting output flag CERT_STATUS_REV_CHECKING_ENABLED).
  668. bool checked_revocation_for_some_path = false;
  669. // Run path building with the different parameters (attempts) until a valid
  670. // path is found. Earlier successful attempts have priority over later
  671. // attempts.
  672. //
  673. // Attempts are enqueued into |attempts| and drained in FIFO order.
  674. std::vector<BuildPathAttempt> attempts;
  675. // First try EV validation. Can skip this if the leaf certificate has no
  676. // chance of verifying as EV (lacks an EV policy).
  677. if (IsEVCandidate(ev_metadata, target.get()))
  678. attempts.emplace_back(VerificationType::kEV);
  679. // Next try DV validation.
  680. attempts.emplace_back(VerificationType::kDV);
  681. CertPathBuilder::Result result;
  682. VerificationType verification_type = VerificationType::kDV;
  683. // Iterate over |attempts| until there are none left to try, or an attempt
  684. // succeeded.
  685. for (size_t cur_attempt_index = 0; cur_attempt_index < attempts.size();
  686. ++cur_attempt_index) {
  687. const auto& cur_attempt = attempts[cur_attempt_index];
  688. verification_type = cur_attempt.verification_type;
  689. net_log.BeginEvent(
  690. NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT, [&] {
  691. base::Value::Dict results;
  692. if (verification_type == VerificationType::kEV)
  693. results.Set("is_ev_attempt", true);
  694. results.Set("digest_policy",
  695. static_cast<int>(cur_attempt.digest_policy));
  696. return base::Value(std::move(results));
  697. });
  698. // If a previous attempt used up most/all of the deadline, extend the
  699. // deadline a little bit to give this verification attempt a chance at
  700. // success.
  701. deadline = std::max(
  702. deadline, base::TimeTicks::Now() + kPerAttemptMinVerificationTimeLimit);
  703. // Run the attempt through the path builder.
  704. result = TryBuildPath(
  705. target, &intermediates, &trust_store, der_verification_time, deadline,
  706. cur_attempt.verification_type, cur_attempt.digest_policy, flags,
  707. ocsp_response, crl_set, net_fetcher_.get(), ev_metadata,
  708. &checked_revocation_for_some_path);
  709. // TODO(crbug.com/634484): Log these in path_builder.cc so they include
  710. // correct timing information.
  711. for (const auto& path : result.paths) {
  712. net_log.AddEvent(NetLogEventType::CERT_VERIFY_PROC_PATH_BUILT,
  713. [&] { return NetLogPathBuilderResultPath(*path); });
  714. }
  715. net_log.EndEvent(NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT,
  716. [&] { return NetLogPathBuilderResult(result); });
  717. if (result.HasValidPath())
  718. break;
  719. if (result.exceeded_deadline) {
  720. // Stop immediately if an attempt exceeds the deadline.
  721. break;
  722. }
  723. // If this path building attempt (may have) failed due to the chain using a
  724. // weak signature algorithm, enqueue a similar attempt but with weaker
  725. // signature algorithms (SHA1) permitted.
  726. //
  727. // This fallback is necessary because the CertVerifyProc layer may decide to
  728. // allow SHA1 based on its own policy, so path building should return
  729. // possibly weak chains too.
  730. //
  731. // TODO(eroman): Would be better for the SHA1 policy to be part of the
  732. // delegate instead so it can interact with path building.
  733. if (cur_attempt.digest_policy ==
  734. SimplePathBuilderDelegate::DigestPolicy::kStrong &&
  735. CanTryAgainWithWeakerDigestPolicy(result)) {
  736. BuildPathAttempt sha1_fallback_attempt = cur_attempt;
  737. sha1_fallback_attempt.digest_policy =
  738. SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1;
  739. attempts.push_back(sha1_fallback_attempt);
  740. }
  741. }
  742. // Write the results to |*verify_result|.
  743. int error = AssignVerifyResult(
  744. input_cert, hostname, result, verification_type,
  745. checked_revocation_for_some_path, &trust_store, verify_result);
  746. if (error == OK) {
  747. LogNameNormalizationMetrics(".Builtin", verify_result->verified_cert.get(),
  748. verify_result->is_issued_by_known_root);
  749. }
  750. return error;
  751. }
  752. } // namespace
  753. CertVerifyProcBuiltinResultDebugData::CertVerifyProcBuiltinResultDebugData(
  754. base::Time verification_time,
  755. const der::GeneralizedTime& der_verification_time,
  756. absl::optional<int64_t> chrome_root_store_version)
  757. : verification_time_(verification_time),
  758. der_verification_time_(der_verification_time),
  759. chrome_root_store_version_(chrome_root_store_version) {}
  760. // static
  761. const CertVerifyProcBuiltinResultDebugData*
  762. CertVerifyProcBuiltinResultDebugData::Get(
  763. const base::SupportsUserData* debug_data) {
  764. return static_cast<CertVerifyProcBuiltinResultDebugData*>(
  765. debug_data->GetUserData(kResultDebugDataKey));
  766. }
  767. // static
  768. void CertVerifyProcBuiltinResultDebugData::Create(
  769. base::SupportsUserData* debug_data,
  770. base::Time verification_time,
  771. const der::GeneralizedTime& der_verification_time,
  772. absl::optional<int64_t> chrome_root_store_version) {
  773. debug_data->SetUserData(
  774. kResultDebugDataKey,
  775. std::make_unique<CertVerifyProcBuiltinResultDebugData>(
  776. verification_time, der_verification_time, chrome_root_store_version));
  777. }
  778. std::unique_ptr<base::SupportsUserData::Data>
  779. CertVerifyProcBuiltinResultDebugData::Clone() {
  780. return std::make_unique<CertVerifyProcBuiltinResultDebugData>(*this);
  781. }
  782. scoped_refptr<CertVerifyProc> CreateCertVerifyProcBuiltin(
  783. scoped_refptr<CertNetFetcher> net_fetcher,
  784. std::unique_ptr<SystemTrustStore> system_trust_store) {
  785. return base::MakeRefCounted<CertVerifyProcBuiltin>(
  786. std::move(net_fetcher), std::move(system_trust_store));
  787. }
  788. base::TimeDelta GetCertVerifyProcBuiltinTimeLimitForTesting() {
  789. return kMaxVerificationTime;
  790. }
  791. } // namespace net