Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Side by Side Diff: chrome/browser/net/nss_slot_factory.cc

Issue 18121007: *WIP* Store NSS slots per profile. Move keygen to chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: cert manager basics working Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 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/net/nss_slot_factory.h"
6
7 #include <map>
8
9 #include "base/bind.h"
10 #include "base/file_util.h"
11 #include "base/files/file_path.h"
12 #include "base/lazy_instance.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/memory/weak_ptr.h"
16 #include "base/stl_util.h"
17 #include "chrome/browser/profiles/profile_io_data.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/resource_context.h"
20 #include "crypto/nss_util.h"
21 #include "crypto/nss_util_internal.h"
22 #include "net/cert/nss_cert_database.h"
23
24 #if defined(OS_CHROMEOS)
25 #include "chromeos/dbus/cryptohome_client.h"
26 #include "chromeos/dbus/dbus_thread_manager.h"
27 #include "chrome/browser/chromeos/net/nss_cert_database_cros.h"
28 #endif
29
30 using content::BrowserThread;
31
32 namespace {
33
34 #if defined(OS_CHROMEOS)
35 void OnPkcs11GetTpmTokenInfoOnUIThread(
36 const base::Callback<void(int)>& callback,
37 chromeos::DBusMethodCallStatus call_status,
38 const std::string& label,
39 const std::string& user_pin,
40 int slot) {
41 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
42 LOG(WARNING) << __func__ << " " << label << " " << slot;
43 BrowserThread::PostTask(
44 BrowserThread::IO, FROM_HERE, base::Bind(callback, slot));
45 }
46
47 void GetTpmInfoForUserOnUIThread(const std::string& user_name,
48 const base::Callback<void(int)>& callback) {
49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
50 LOG(WARNING) << __func__ << " " << user_name;
51 chromeos::DBusThreadManager::Get()
52 ->GetCryptohomeClient()
53 ->Pkcs11GetTpmTokenInfoForUser(
54 user_name,
55 base::Bind(&OnPkcs11GetTpmTokenInfoOnUIThread, callback));
56 }
57
58 // NSSSlotService initializes and holds the public and private key slots for a
59 // given profile.
60 class NSSSlotService {
61 public:
62 NSSSlotService(const base::FilePath& user_dir,
63 const std::string& user_name);
64 virtual ~NSSSlotService();
65
66 crypto::ScopedPK11Slot GetPublicNSSKeySlot();
67 crypto::ScopedPK11Slot GetPrivateNSSKeySlot();
68 void OnPrivateNSSKeySlotForResourceContextReady(
69 const base::Callback<void(crypto::ScopedPK11Slot)>& callback);
70 void OnNSSCertDatabaseForResourceContextReady(
71 const base::Callback<void(net::NSSCertDatabase*)>& callback);
72
73 private:
74 void OnGotTpmSlot(int slot);
75 void StartTpmSlotInitializion();
76
77 base::FilePath user_dir_;
78 std::string user_name_;
79 crypto::ScopedPK11Slot public_slot_;
80 crypto::ScopedPK11Slot private_slot_;
81 scoped_ptr<chromeos::NSSCertDatabaseCros> cert_db_;
82
83 std::vector<base::Callback<void(crypto::ScopedPK11Slot)> >
84 tpm_ready_callback_list_;
85 std::vector<base::Callback<void(net::NSSCertDatabase*)> >
86 cert_db_ready_callback_list_;
87 base::WeakPtrFactory<NSSSlotService> weak_ptr_factory_;
88
89 DISALLOW_COPY_AND_ASSIGN(NSSSlotService);
90 };
91
92 // XXX
93 // If the profile directory is /home/chronos/u-xxxxxx, the nss db will be at
94 // /home/chronos/u-xxxxxx/.pki/nssdb. You can get the profile directory for a
95 // given username if you need it by calling libchromeos' GetUserPath().
96 //
97 NSSSlotService::NSSSlotService(const base::FilePath& user_dir,
98 const std::string& user_name)
99 : user_dir_(user_dir),
100 user_name_(user_name),
101 weak_ptr_factory_(this) {
102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
103 // XXX should we do something to check that we aren't reopening the same
104 // database used by the default public slot?
105 public_slot_.reset(crypto::OpenPersistentNSSDBForPath(user_dir_));
106 LOG(WARNING) << "pub: " << public_slot_.get();
107 if (crypto::IsTPMTokenEnabledForNSS()) {
108 if (crypto::IsTPMTokenReady()) {
109 StartTpmSlotInitializion();
110 } else {
111 LOG(WARNING) << "waiting for tpm ready ...";
112 crypto::OnTPMReady(base::Bind(&NSSSlotService::StartTpmSlotInitializion,
113 weak_ptr_factory_.GetWeakPtr()));
114 }
115 } else {
116 LOG(WARNING) << "using software private slot";
117 private_slot_ = GetPublicNSSKeySlot();
118 }
119 crypto::DumpNSSSlotInfos();
120 }
121
122 NSSSlotService::~NSSSlotService() {
123 LOG(WARNING) << __func__;
124 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
125 // Don't close when NSS is < 3.15.1, because it would require an additional
126 // sleep for 1 second after closing the database, due to
127 // http://bugzil.la/875601.
128 if (NSS_VersionCheck("3.15.1")) {
129 if (public_slot_) {
130 LOG(WARNING) << "closing nssdb";
131 SECStatus status = SECMOD_CloseUserDB(public_slot_.get());
132 if (status != SECSuccess)
133 PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
134 }
135 }
136 }
137
138 crypto::ScopedPK11Slot NSSSlotService::GetPublicNSSKeySlot() {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
140 return crypto::ScopedPK11Slot(
141 public_slot_ ? PK11_ReferenceSlot(public_slot_.get()) : NULL);
142 }
143
144 crypto::ScopedPK11Slot NSSSlotService::GetPrivateNSSKeySlot() {
145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
146 return crypto::ScopedPK11Slot(
147 private_slot_ ? PK11_ReferenceSlot(private_slot_.get()) : NULL);
148 }
149
150 void NSSSlotService::OnPrivateNSSKeySlotForResourceContextReady(
151 const base::Callback<void(crypto::ScopedPK11Slot)>& callback) {
152 VLOG(1) << __func__;
153 if (private_slot_)
154 callback.Run(GetPrivateNSSKeySlot());
155 else
156 tpm_ready_callback_list_.push_back(callback);
157 }
158
159 void NSSSlotService::OnNSSCertDatabaseForResourceContextReady(
160 const base::Callback<void(net::NSSCertDatabase*)>& callback) {
161 if (cert_db_)
162 callback.Run(cert_db_.get());
163 else
164 cert_db_ready_callback_list_.push_back(callback);
165 }
166
167 void NSSSlotService::OnGotTpmSlot(int slot) {
168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
169 LOG(WARNING) << __func__ << " " << slot;
170 if (slot >= 0) {
171 private_slot_.reset(crypto::GetTPMSlotForId(slot));
172 LOG(WARNING) << " private_slot_ " << private_slot_.get();
173 cert_db_.reset(new chromeos::NSSCertDatabaseCros(GetPublicNSSKeySlot(),
174 GetPrivateNSSKeySlot()));
175
176 for (std::vector<base::Callback<void(crypto::ScopedPK11Slot)> >::iterator
177 i = tpm_ready_callback_list_.begin();
178 i != tpm_ready_callback_list_.end();
179 ++i) {
180 (*i).Run(GetPrivateNSSKeySlot());
181 }
182 tpm_ready_callback_list_.clear();
183
184 for (std::vector<base::Callback<void(net::NSSCertDatabase*)> >::iterator
185 i = cert_db_ready_callback_list_.begin();
186 i != cert_db_ready_callback_list_.end();
187 ++i) {
188 (*i).Run(cert_db_.get());
189 }
190 cert_db_ready_callback_list_.clear();
191 }
192 crypto::DumpNSSSlotInfos();
193 }
194
195 void NSSSlotService::StartTpmSlotInitializion() {
196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
197 LOG(WARNING) << __func__;
198
199 BrowserThread::PostTask(
200 BrowserThread::UI,
201 FROM_HERE,
202 base::Bind(&GetTpmInfoForUserOnUIThread,
203 user_name_,
204 base::Bind(&NSSSlotService::OnGotTpmSlot,
205 weak_ptr_factory_.GetWeakPtr())));
206 }
207
208 class NSSSlotFactory {
209 public:
210 NSSSlotService* GetService(content::ResourceContext* context);
211
212 ~NSSSlotFactory();
213
214 private:
215 friend struct base::DefaultLazyInstanceTraits<NSSSlotFactory>;
216
217 std::map<std::string, NSSSlotService*> service_map_;
218 };
219
220 base::LazyInstance<NSSSlotFactory>::Leaky
221 g_nss_slot_factory = LAZY_INSTANCE_INITIALIZER;
222
223 NSSSlotService* NSSSlotFactory::GetService(content::ResourceContext* context) {
224 ProfileIOData* io_data = ProfileIOData::FromResourceContext(context);
225 std::string user_name = io_data->user_name();
226 if (user_name.empty())
227 return NULL;
228
229 std::map<std::string, NSSSlotService*>::iterator i =
230 service_map_.find(user_name);
231 if (i != service_map_.end())
232 return (*i).second;
233
234 NSSSlotService* service =
235 new NSSSlotService(io_data->profile_path(), io_data->user_name());
236 service_map_[user_name] = service;
237 return service;
238 }
239
240 // XXX this will be run on UI thread due to lazyinstance atexit thingy?
241 // XXX made lazyinstance leaky ... so it won't be run at all, like nss_util
242 NSSSlotFactory::~NSSSlotFactory() {
243 LOG(WARNING) << __func__;
244 STLDeleteValues(&service_map_);
245 }
246 #endif // defined(OS_CHROMEOS)
247
248 void PassTPMToCallback(
249 const base::Callback<void(crypto::ScopedPK11Slot)>& callback) {
250 callback.Run(crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot()));
251 }
252
253 } // namespace
254
255 crypto::ScopedPK11Slot GetPublicNSSKeySlotForResourceContext(
256 content::ResourceContext* context) {
257 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
258 #if defined(OS_CHROMEOS)
259 NSSSlotService* service = g_nss_slot_factory.Get().GetService(context);
260 if (service)
261 return service->GetPublicNSSKeySlot();
262 #endif
263 return crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot());
264 }
265
266 crypto::ScopedPK11Slot GetPrivateNSSKeySlotForResourceContext(
267 content::ResourceContext* context) {
268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
269 #if defined(OS_CHROMEOS)
270 NSSSlotService* service = g_nss_slot_factory.Get().GetService(context);
271 if (service)
272 return service->GetPrivateNSSKeySlot();
273 #endif
274 return crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot());
275 }
276
277 void OnPrivateNSSKeySlotForResourceContextReady(
278 content::ResourceContext* context,
279 const base::Callback<void(crypto::ScopedPK11Slot)>& callback) {
280 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
281 #if defined(OS_CHROMEOS)
282 NSSSlotService* service = g_nss_slot_factory.Get().GetService(context);
283 if (service) {
284 service->OnPrivateNSSKeySlotForResourceContextReady(callback);
285 return;
286 }
287 crypto::OnTPMReady(base::Bind(&PassTPMToCallback, callback));
288 #else
289 PassTPMToCallback(callback);
290 #endif
291 }
292
293 void GetNSSCertDatabaseForResourceContext(
294 content::ResourceContext* context,
295 const base::Callback<void(net::NSSCertDatabase*)>& callback) {
296 #if defined(OS_CHROMEOS)
297 NSSSlotService* service = g_nss_slot_factory.Get().GetService(context);
298 if (service) {
299 service->OnNSSCertDatabaseForResourceContextReady(callback);
300 return;
301 }
302 #else
303 callback.Run(NSSCertDatabase::GetInstance());
304 #endif
305 }
OLDNEW
« no previous file with comments | « chrome/browser/net/nss_slot_factory.h ('k') | chrome/browser/policy/browser_policy_connector.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698