xref: /aosp_15_r20/external/cronet/net/cert/internal/trust_store_android.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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/x509_certificate.h"
14 #include "net/cert/x509_util.h"
15 #include "third_party/boringssl/src/pki/cert_errors.h"
16 #include "third_party/boringssl/src/pki/parse_name.h"
17 #include "third_party/boringssl/src/pki/parsed_certificate.h"
18 
19 namespace net {
20 
21 class TrustStoreAndroid::Impl
22     : public base::RefCountedThreadSafe<TrustStoreAndroid::Impl> {
23  public:
Impl(int generation)24   explicit Impl(int generation) : generation_(generation) {
25     base::ScopedBlockingCall scoped_blocking_call(
26         FROM_HERE, base::BlockingType::MAY_BLOCK);
27     std::vector<std::string> roots = net::android::GetUserAddedRoots();
28 
29     for (auto& root : roots) {
30       bssl::CertErrors errors;
31       auto parsed = bssl::ParsedCertificate::Create(
32           net::x509_util::CreateCryptoBuffer(root),
33           net::x509_util::DefaultParseCertificateOptions(), &errors);
34       if (!parsed) {
35         LOG(ERROR) << "Error parsing certificate:\n" << errors.ToDebugString();
36         continue;
37       }
38       trust_store_.AddTrustAnchor(std::move(parsed));
39     }
40   }
41 
42   // TODO(hchao): see if we can get SyncGetIssueresOf marked const
SyncGetIssuersOf(const bssl::ParsedCertificate * cert,bssl::ParsedCertificateList * issuers)43   void SyncGetIssuersOf(const bssl::ParsedCertificate* cert,
44                         bssl::ParsedCertificateList* issuers) {
45     trust_store_.SyncGetIssuersOf(cert, issuers);
46   }
47 
48   // TODO(hchao): see if we can get GetTrust marked const again
GetTrust(const bssl::ParsedCertificate * cert)49   bssl::CertificateTrust GetTrust(const bssl::ParsedCertificate* cert) {
50     return trust_store_.GetTrust(cert);
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   bssl::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. CertDatabase observation is added here
78 // rather than in the constructor to avoid having to add a TaskEnvironment to
79 // every unit test that uses 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 
OnTrustStoreChanged()87 void TrustStoreAndroid::OnTrustStoreChanged() {
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 
99   // It is possible that generation_ might be incremented in between the various
100   // statements here, but that's okay as the worst case is that we will cause a
101   // bit of extra work in reloading the android trust store if we get many
102   // OnTrustStoreChanged() calls in rapid succession.
103   int current_generation = generation_.load();
104   if (!impl_ || impl_->generation() != current_generation) {
105     SCOPED_UMA_HISTOGRAM_LONG_TIMER("Net.CertVerifier.AndroidTrustStoreInit");
106     impl_ = base::MakeRefCounted<TrustStoreAndroid::Impl>(current_generation);
107   }
108 
109   return impl_;
110 }
111 
SyncGetIssuersOf(const bssl::ParsedCertificate * cert,bssl::ParsedCertificateList * issuers)112 void TrustStoreAndroid::SyncGetIssuersOf(const bssl::ParsedCertificate* cert,
113                                          bssl::ParsedCertificateList* issuers) {
114   MaybeInitializeAndGetImpl()->SyncGetIssuersOf(cert, issuers);
115 }
116 
GetTrust(const bssl::ParsedCertificate * cert)117 bssl::CertificateTrust TrustStoreAndroid::GetTrust(
118     const bssl::ParsedCertificate* cert) {
119   return MaybeInitializeAndGetImpl()->GetTrust(cert);
120 }
121 
122 }  // namespace net
123