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