1 // Copyright 2019 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 "chrome/browser/chromeos/arc/enterprise/cert_store/arc_smart_card_manager_bridge.h"
6
7 #include <algorithm>
8 #include <iterator>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/callback.h"
13 #include "base/logging.h"
14 #include "base/memory/singleton.h"
15 #include "chrome/browser/chromeos/arc/policy/arc_policy_bridge.h"
16 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_service.h"
17 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.h"
18 #include "chrome/browser/chromeos/platform_keys/platform_keys.h"
19 #include "chrome/common/net/x509_certificate_model_nss.h"
20 #include "components/arc/arc_browser_context_keyed_service_factory_base.h"
21 #include "components/policy/core/common/policy_map.h"
22 #include "components/policy/core/common/policy_namespace.h"
23 #include "crypto/rsa_private_key.h"
24 #include "net/cert/x509_util_nss.h"
25
26 namespace arc {
27
28 namespace {
29
30 // Singleton factory for ArcSmartCardManagerBridge.
31 class ArcSmartCardManagerBridgeFactory
32 : public internal::ArcBrowserContextKeyedServiceFactoryBase<
33 ArcSmartCardManagerBridge,
34 ArcSmartCardManagerBridgeFactory> {
35 public:
36 // Factory name used by ArcBrowserContextKeyedServiceFactoryBase.
37 static constexpr const char* kName = "ArcSmartCardManagerBridgeFactory";
38
GetInstance()39 static ArcSmartCardManagerBridgeFactory* GetInstance() {
40 return base::Singleton<ArcSmartCardManagerBridgeFactory>::get();
41 }
42
43 private:
44 friend base::DefaultSingletonTraits<ArcSmartCardManagerBridgeFactory>;
ArcSmartCardManagerBridgeFactory()45 ArcSmartCardManagerBridgeFactory() {
46 DependsOn(chromeos::CertificateProviderServiceFactory::GetInstance());
47 }
48
49 ~ArcSmartCardManagerBridgeFactory() override = default;
50 };
51
52 } // namespace
53
54 // static
GetForBrowserContext(content::BrowserContext * context)55 ArcSmartCardManagerBridge* ArcSmartCardManagerBridge::GetForBrowserContext(
56 content::BrowserContext* context) {
57 return ArcSmartCardManagerBridgeFactory::GetForBrowserContext(context);
58 }
59
60 // static
GetFactory()61 BrowserContextKeyedServiceFactory* ArcSmartCardManagerBridge::GetFactory() {
62 return ArcSmartCardManagerBridgeFactory::GetInstance();
63 }
64
ArcSmartCardManagerBridge(content::BrowserContext * context,ArcBridgeService * bridge_service)65 ArcSmartCardManagerBridge::ArcSmartCardManagerBridge(
66 content::BrowserContext* context,
67 ArcBridgeService* bridge_service)
68 : ArcSmartCardManagerBridge(
69 context,
70 bridge_service,
71 chromeos::CertificateProviderServiceFactory::GetForBrowserContext(
72 context)
73 ->CreateCertificateProvider(),
74 std::make_unique<ArcCertInstaller>(context)) {}
75
ArcSmartCardManagerBridge(content::BrowserContext * context,ArcBridgeService * bridge_service,std::unique_ptr<chromeos::CertificateProvider> certificate_provider,std::unique_ptr<ArcCertInstaller> installer)76 ArcSmartCardManagerBridge::ArcSmartCardManagerBridge(
77 content::BrowserContext* context,
78 ArcBridgeService* bridge_service,
79 std::unique_ptr<chromeos::CertificateProvider> certificate_provider,
80 std::unique_ptr<ArcCertInstaller> installer)
81 : context_(context),
82 arc_bridge_service_(bridge_service),
83 certificate_provider_(std::move(certificate_provider)),
84 installer_(std::move(installer)),
85 weak_ptr_factory_(this) {
86 VLOG(1) << "ArcSmartCardManagerBridge::ArcSmartCardManagerBridge";
87 arc_bridge_service_->smart_card_manager()->SetHost(this);
88 }
89
~ArcSmartCardManagerBridge()90 ArcSmartCardManagerBridge::~ArcSmartCardManagerBridge() {
91 VLOG(1) << "ArcSmartCardManagerBridge::~ArcSmartCardManagerBridge";
92
93 arc_bridge_service_->smart_card_manager()->SetHost(nullptr);
94 }
95
Refresh(RefreshCallback callback)96 void ArcSmartCardManagerBridge::Refresh(RefreshCallback callback) {
97 VLOG(1) << "ArcSmartCardManagerBridge::Refresh";
98
99 certificate_provider_->GetCertificates(
100 base::BindOnce(&ArcSmartCardManagerBridge::DidGetCerts,
101 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
102 }
103
GetRealSpkiForDummySpki(const std::string & dummy_spki)104 std::string ArcSmartCardManagerBridge::GetRealSpkiForDummySpki(
105 const std::string& dummy_spki) {
106 return certificate_cache_.GetRealSpkiForDummySpki(dummy_spki);
107 }
108
109 ArcSmartCardManagerBridge::CertificateCache::CertificateCache() = default;
110 ArcSmartCardManagerBridge::CertificateCache::~CertificateCache() = default;
111
DidGetCerts(RefreshCallback callback,net::ClientCertIdentityList cert_identities)112 void ArcSmartCardManagerBridge::DidGetCerts(
113 RefreshCallback callback,
114 net::ClientCertIdentityList cert_identities) {
115 VLOG(1) << "ArcSmartCardManagerBridge::DidGetCerts";
116
117 certificate_cache_.clear_need_policy_update();
118 std::vector<net::ScopedCERTCertificate> certificates =
119 certificate_cache_.Update(std::move(cert_identities));
120
121 // Maps cert name to dummy SPKI.
122 std::map<std::string, std::string> installed_keys =
123 installer_->InstallArcCerts(std::move(certificates), std::move(callback));
124
125 certificate_cache_.Update(installed_keys);
126
127 if (certificate_cache_.need_policy_update()) {
128 ArcPolicyBridge* const policy_bridge =
129 ArcPolicyBridge::GetForBrowserContext(context_);
130 if (policy_bridge) {
131 policy_bridge->OnPolicyUpdated(policy::PolicyNamespace(),
132 policy::PolicyMap(), policy::PolicyMap());
133 }
134 }
135 }
136
137 std::vector<net::ScopedCERTCertificate>
Update(net::ClientCertIdentityList cert_identities)138 ArcSmartCardManagerBridge::CertificateCache::Update(
139 net::ClientCertIdentityList cert_identities) {
140 std::vector<net::ScopedCERTCertificate> certificates;
141 // Map cert name to real SPKI.
142 real_spki_by_name_cache_.clear();
143 std::set<std::string> new_required_cert_names;
144 for (const auto& identity : cert_identities) {
145 net::ScopedCERTCertificate nss_cert(
146 net::x509_util::CreateCERTCertificateFromX509Certificate(
147 identity->certificate()));
148 if (!nss_cert) {
149 LOG(ERROR) << "Certificate provider returned an invalid smart card "
150 << "certificate.";
151 continue;
152 }
153 std::string cert_name =
154 x509_certificate_model::GetCertNameOrNickname(nss_cert.get());
155 real_spki_by_name_cache_[cert_name] =
156 chromeos::platform_keys::GetSubjectPublicKeyInfo(
157 identity->certificate());
158 new_required_cert_names.insert(cert_name);
159
160 certificates.push_back(std::move(nss_cert));
161 }
162 need_policy_update_ = (required_cert_names_ != new_required_cert_names);
163 for (auto cert_name : required_cert_names_) {
164 if (!new_required_cert_names.count(cert_name)) {
165 real_spki_by_dummy_spki_cache_.erase(
166 dummy_spki_by_name_cache_[cert_name]);
167 dummy_spki_by_name_cache_.erase(cert_name);
168 }
169 }
170 required_cert_names_ = new_required_cert_names;
171 return certificates;
172 }
173
Update(std::map<std::string,std::string> dummy_spki_by_name)174 void ArcSmartCardManagerBridge::CertificateCache::Update(
175 std::map<std::string, std::string> dummy_spki_by_name) {
176 if (required_cert_names_.size() != dummy_spki_by_name.size())
177 return;
178 for (const auto& cert : dummy_spki_by_name) {
179 const std::string& name = cert.first;
180 if (!required_cert_names_.count(name)) {
181 VLOG(1) << "ArcSmartCardManagerBridge::CertificateCache::Update error: "
182 << "An attempt to add a non-required key " << name;
183 continue;
184 }
185
186 std::string dummy_spki = cert.second;
187 if (dummy_spki.empty() && dummy_spki_by_name_cache_.count(name))
188 dummy_spki = dummy_spki_by_name_cache_[name];
189 if (!dummy_spki.empty()) {
190 dummy_spki_by_name_cache_[name] = dummy_spki;
191 real_spki_by_dummy_spki_cache_[dummy_spki] =
192 real_spki_by_name_cache_[name];
193 }
194 }
195 }
196
197 std::string
GetRealSpkiForDummySpki(const std::string & dummy_spki)198 ArcSmartCardManagerBridge::CertificateCache::GetRealSpkiForDummySpki(
199 const std::string& dummy_spki) {
200 if (real_spki_by_dummy_spki_cache_.count(dummy_spki))
201 return real_spki_by_dummy_spki_cache_[dummy_spki];
202 return "";
203 }
204
205 } // namespace arc
206