• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The Chromium Authors
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/trust_store_android.h"
6 
7 #include "base/logging.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "base/task/task_traits.h"
10 #include "base/task/thread_pool.h"
11 #include "base/threading/scoped_blocking_call.h"
12 #include "net/android/network_library.h"
13 #include "net/cert/internal/platform_trust_store.h"
14 #include "net/cert/x509_certificate.h"
15 #include "net/cert/x509_util.h"
16 #include "third_party/boringssl/src/pki/cert_errors.h"
17 #include "third_party/boringssl/src/pki/parse_name.h"
18 #include "third_party/boringssl/src/pki/parsed_certificate.h"
19 
20 namespace net {
21 
22 class TrustStoreAndroid::Impl
23     : public base::RefCountedThreadSafe<TrustStoreAndroid::Impl> {
24  public:
Impl(int generation)25   explicit Impl(int generation) : generation_(generation) {
26     base::ScopedBlockingCall scoped_blocking_call(
27         FROM_HERE, base::BlockingType::MAY_BLOCK);
28     std::vector<std::string> roots = net::android::GetUserAddedRoots();
29 
30     for (auto& root : roots) {
31       bssl::CertErrors errors;
32       auto parsed = bssl::ParsedCertificate::Create(
33           net::x509_util::CreateCryptoBuffer(root),
34           net::x509_util::DefaultParseCertificateOptions(), &errors);
35       if (!parsed) {
36         LOG(ERROR) << "Error parsing certificate:\n" << errors.ToDebugString();
37         continue;
38       }
39       trust_store_.AddTrustAnchor(std::move(parsed));
40     }
41   }
42 
43   // TODO(hchao): see if we can get SyncGetIssueresOf marked const
SyncGetIssuersOf(const bssl::ParsedCertificate * cert,bssl::ParsedCertificateList * issuers)44   void SyncGetIssuersOf(const bssl::ParsedCertificate* cert,
45                         bssl::ParsedCertificateList* issuers) {
46     trust_store_.SyncGetIssuersOf(cert, issuers);
47   }
48 
49   // TODO(hchao): see if we can get GetTrust marked const again
GetTrust(const bssl::ParsedCertificate * cert)50   bssl::CertificateTrust GetTrust(const bssl::ParsedCertificate* cert) {
51     return trust_store_.GetTrust(cert);
52   }
53 
generation()54   int generation() { return generation_; }
55 
56  private:
57   friend class base::RefCountedThreadSafe<TrustStoreAndroid::Impl>;
58   ~Impl() = default;
59 
60   // Generation # that trust_store_ was loaded at.
61   const int generation_;
62 
63   bssl::TrustStoreInMemory trust_store_;
64 };
65 
TrustStoreAndroid()66 TrustStoreAndroid::TrustStoreAndroid() {
67   // It's okay for ObserveCertDBChanges to be called on a different sequence
68   // than the object was constructed on.
69   DETACH_FROM_SEQUENCE(certdb_observer_sequence_checker_);
70 }
71 
~TrustStoreAndroid()72 TrustStoreAndroid::~TrustStoreAndroid() {
73   DCHECK_CALLED_ON_VALID_SEQUENCE(certdb_observer_sequence_checker_);
74   if (is_observing_certdb_changes_) {
75     CertDatabase::GetInstance()->RemoveObserver(this);
76   }
77 }
78 
Initialize()79 void TrustStoreAndroid::Initialize() {
80   MaybeInitializeAndGetImpl();
81 }
82 
83 // This function is not thread safe. CertDatabase observation is added here
84 // rather than in the constructor to avoid having to add a TaskEnvironment to
85 // every unit test that uses TrustStoreAndroid.
ObserveCertDBChanges()86 void TrustStoreAndroid::ObserveCertDBChanges() {
87   DCHECK_CALLED_ON_VALID_SEQUENCE(certdb_observer_sequence_checker_);
88   if (!is_observing_certdb_changes_) {
89     is_observing_certdb_changes_ = true;
90     CertDatabase::GetInstance()->AddObserver(this);
91   }
92 }
93 
OnTrustStoreChanged()94 void TrustStoreAndroid::OnTrustStoreChanged() {
95   // Increment the generation number. This will regenerate the impl_ next time
96   // it is fetched. It would be neater to regenerate the impl_ here but
97   // complications around blocking of threads prevents this from being easily
98   // accomplished.
99   generation_++;
100 }
101 
102 scoped_refptr<TrustStoreAndroid::Impl>
MaybeInitializeAndGetImpl()103 TrustStoreAndroid::MaybeInitializeAndGetImpl() {
104   base::AutoLock lock(init_lock_);
105 
106   // It is possible that generation_ might be incremented in between the various
107   // statements here, but that's okay as the worst case is that we will cause a
108   // bit of extra work in reloading the android trust store if we get many
109   // OnTrustStoreChanged() calls in rapid succession.
110   int current_generation = generation_.load();
111   if (!impl_ || impl_->generation() != current_generation) {
112     SCOPED_UMA_HISTOGRAM_LONG_TIMER("Net.CertVerifier.AndroidTrustStoreInit");
113     impl_ = base::MakeRefCounted<TrustStoreAndroid::Impl>(current_generation);
114   }
115 
116   return impl_;
117 }
118 
SyncGetIssuersOf(const bssl::ParsedCertificate * cert,bssl::ParsedCertificateList * issuers)119 void TrustStoreAndroid::SyncGetIssuersOf(const bssl::ParsedCertificate* cert,
120                                          bssl::ParsedCertificateList* issuers) {
121   MaybeInitializeAndGetImpl()->SyncGetIssuersOf(cert, issuers);
122 }
123 
GetTrust(const bssl::ParsedCertificate * cert)124 bssl::CertificateTrust TrustStoreAndroid::GetTrust(
125     const bssl::ParsedCertificate* cert) {
126   return MaybeInitializeAndGetImpl()->GetTrust(cert);
127 }
128 
129 std::vector<net::PlatformTrustStore::CertWithTrust>
GetAllUserAddedCerts()130 TrustStoreAndroid::GetAllUserAddedCerts() {
131   // TODO(crbug.com/40928765): implement this.
132   return {};
133 }
134 
135 }  // namespace net
136