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

Side by Side Diff: net/cert/nss_cert_database_chromeos.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: certdb: handle GetCertTrust and IsUntrusted, failed attempt to handle SetCertTrust Created 7 years, 1 month 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
« no previous file with comments | « net/cert/nss_cert_database_chromeos.h ('k') | net/cert/nss_profile_filter_chromeos.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "net/cert/nss_cert_database_chromeos.h"
6
7 #include <map>
8
9 #include <cert.h>
10 #include <pk11pub.h>
11
12 #include "base/bind.h"
13 #include "base/lazy_instance.h"
14 #include "base/stl_util.h"
15 #include "crypto/nss_util.h"
16 #include "crypto/nss_util_internal.h"
17 #include "net/base/crypto_module.h"
18 #include "net/cert/x509_certificate.h"
19 #include "net/cert/x509_util_nss.h"
20
21 namespace net {
22
23 namespace {
24
25 scoped_refptr<const X509Certificate> FindCertInSlot(const X509Certificate* cert,
26 PK11SlotInfo* slot) {
27 CERTCertificate* slot_cert_handle = PK11_FindCertFromDERCert(
28 slot, cert->os_cert_handle(), NULL);
29 if (slot_cert_handle) {
30 scoped_refptr<X509Certificate> slot_cert(
31 X509Certificate::CreateFromHandle(slot_cert_handle,
32 X509Certificate::OSCertHandles()));
33 CERT_DestroyCertificate(slot_cert_handle);
34 return slot_cert;
35 }
36 return NULL;
37 }
38
39 } // namespace
40
41 class NSSCertDatabaseChromeOS::Manager {
42 public:
43 ~Manager() {
44 STLDeleteValues(&user_db_map_);
45 }
46
47 NSSCertDatabase* GetPrimaryDB() {
48 LOG(WARNING)
49 << "Using primary NSSCertDatabase. Consider using GetForUser instead.";
50 return primary_db_;
51 }
52
53 void GetForUser(const std::string& username_hash,
54 const base::Callback<void(NSSCertDatabase*)>& callback) {
55 UserDBMap::iterator it = user_db_map_.find(username_hash);
56 if (it != user_db_map_.end()) {
57 // DB already exists for this user.
58 it->second->OnReady(callback);
59 return;
60 }
61
62 crypto::ScopedPK11Slot public_slot(
63 crypto::GetPublicSlotForChromeOSUser(username_hash));
64 if (!public_slot) {
65 // Invalid user, or someone called us before InitializeNSSForChromeOSUser
66 // got called for the user.
67 callback.Run(NULL);
68 return;
69 }
70
71 NSSCertDatabaseChromeOS* db = NULL;
72 if (primary_db_owner_) {
73 crypto::ScopedPK11Slot primary_public_slot(primary_db_->GetPublicSlot());
74 if (public_slot.get() == primary_public_slot.get()) {
75 VLOG(1) << "Got username for primary: " << username_hash;
76 // We now know what username corrosponds to the primary user. Put the
77 // primary_db_ into the user_db_map_, which will now own it.
78 db = primary_db_owner_.release();
79 }
80 }
81
82 if (!db) {
83 // Create DB for new user.
84 VLOG(1) << "Create DB for: " << username_hash;
85 db = new NSSCertDatabaseChromeOS(public_slot.Pass());
86 crypto::OnPrivateSlotReadyForChromeOSUser(
87 username_hash,
88 base::Bind(&NSSCertDatabaseChromeOS::SetPrivateSlot,
89 base::Unretained(db)));
90 }
91
92 user_db_map_[username_hash] = db;
93 db->OnReady(callback);
94 }
95 private:
96 friend struct base::DefaultLazyInstanceTraits<Manager>;
97
98 Manager()
99 : primary_db_(new NSSCertDatabaseChromeOS(
100 crypto::ScopedPK11Slot(crypto::GetPublicNSSKeySlot()))) {
101 primary_db_owner_.reset(primary_db_);
102 crypto::OnTPMReady(base::Bind(&Manager::SetPrimaryPrivateSlot,
103 base::Unretained(primary_db_)));
104 }
105
106 static void SetPrimaryPrivateSlot(NSSCertDatabaseChromeOS* db) {
107 db->SetPrivateSlot(crypto::ScopedPK11Slot(crypto::GetPrivateNSSKeySlot()));
108 }
109
110 NSSCertDatabaseChromeOS* primary_db_;
111 scoped_ptr<NSSCertDatabaseChromeOS> primary_db_owner_;
112 typedef std::map<std::string, NSSCertDatabaseChromeOS*> UserDBMap;
113 UserDBMap user_db_map_;
114 };
115
116 namespace {
117 base::LazyInstance<NSSCertDatabaseChromeOS::Manager>::Leaky
118 g_nss_cert_database_chromeos_manager = LAZY_INSTANCE_INITIALIZER;
119 } // namespace
120
121 // On ChromeOS NSSCertDatabase::GetInstance is defined to return the primary
122 // user's NSSCertDatabaseChromeOS object.
123 // static
124 NSSCertDatabase* NSSCertDatabase::GetInstance() {
125 return g_nss_cert_database_chromeos_manager.Get().GetPrimaryDB();
126 }
127
128 // static
129 void NSSCertDatabaseChromeOS::GetForUser(
130 const std::string& username_hash,
131 const base::Callback<void(NSSCertDatabase*)>& callback) {
132 g_nss_cert_database_chromeos_manager.Get().GetForUser(username_hash,
133 callback);
134 }
135
136 NSSCertDatabaseChromeOS::NSSCertDatabaseChromeOS(
137 crypto::ScopedPK11Slot public_slot)
138 : ready_(false), public_slot_(public_slot.Pass()) {
139 VLOG(1) << __func__ << " pub:" << PK11_GetModuleID(public_slot_.get()) << ":"
140 << PK11_GetSlotID(public_slot_.get());
141 }
142
143 NSSCertDatabaseChromeOS::~NSSCertDatabaseChromeOS() {}
144
145 void NSSCertDatabaseChromeOS::ListCerts(CertificateList* certs) {
146 if (!ready_) {
147 LOG(WARNING) << __func__ << " called before initialization complete";
148 certs->clear();
149 return;
150 }
151 NSSCertDatabase::ListCerts(certs);
152
153 size_t pre_size = certs->size();
154 certs->erase(
155 std::remove_if(certs->begin(), certs->end(),
156 NSSProfileFilterChromeOS::Predicate(profile_filter_)),
157 certs->end());
158 VLOG(1) << "filtered " << pre_size - certs->size() << " of " << pre_size
159 << " certs";
160 }
161
162 crypto::ScopedPK11Slot NSSCertDatabaseChromeOS::GetPublicSlot() const {
163 return crypto::ScopedPK11Slot(
164 public_slot_ ? PK11_ReferenceSlot(public_slot_.get()) : NULL);
165 }
166
167 crypto::ScopedPK11Slot NSSCertDatabaseChromeOS::GetPrivateSlot() const {
168 return crypto::ScopedPK11Slot(
169 private_slot_ ? PK11_ReferenceSlot(private_slot_.get()) : NULL);
170 }
171
172 void NSSCertDatabaseChromeOS::ListModules(CryptoModuleList* modules,
173 bool need_rw) const {
174 if (!ready_) {
175 LOG(WARNING) << __func__ << " called before initialization complete";
176 modules->clear();
177 return;
178 }
179 NSSCertDatabase::ListModules(modules, need_rw);
180
181 size_t pre_size = modules->size();
182 modules->erase(
183 std::remove_if(modules->begin(), modules->end(),
184 NSSProfileFilterChromeOS::Predicate(profile_filter_)),
185 modules->end());
186 VLOG(1) << "filtered " << pre_size - modules->size() << " of " << pre_size
187 << " modules";
188 }
189
190 NSSCertDatabase::TrustBits NSSCertDatabaseChromeOS::GetCertTrust(
191 const X509Certificate* cert,
192 CertType type) const {
193 return NSSCertDatabase::GetCertTrust(ResolveCert(cert, false), type);
194 }
195
196 bool NSSCertDatabaseChromeOS::IsUntrusted(const X509Certificate* cert) const {
197 return NSSCertDatabase::IsUntrusted(ResolveCert(cert, false));
198 }
199
200 #if 0
201 bool NSSCertDatabaseChromeOS::SetCertTrust(const X509Certificate* cert,
202 CertType type,
203 TrustBits trust_bits) {
204 // XXX handle case of cert not existing in any of this profile's rw slots
205 if (!FindCertInSlot(cert, public_slot_.get())) {
206 // Copy cert to our slot so we can set trust . . .
207 // XXX this doesn't actually help.
208 SECStatus srv = PK11_ImportCert(
209 public_slot_.get(),
210 cert->os_cert_handle(),
211 CK_INVALID_HANDLE,
212 x509_util::GetUniqueNicknameForSlot(cert->GetDefaultNickname(type),
213 &cert->os_cert_handle()->derSubject,
214 public_slot_.get()).c_str(),
215 PR_FALSE /* includeTrust (unused) */);
216 if (srv != SECSuccess) {
217 LOG(ERROR) << "copying cert to our slot failed with error "
218 << PORT_GetError();
219 return false;
220 }
221 VLOG(1) << "copied cert to our slot";
222 }
223 //
224 // XXX this doesn't work: if cert is in multiple rw slots nss will just set
225 // the trust on the "first" one - we could return false instead of setting
226 // trust in wrong slot? (but how do we know which slot nss would have felt
227 // like setting the trust in? is it always the lowest numbered slotid?)
228 return NSSCertDatabase::SetCertTrust(
229 ResolveCert(cert, true), type, trust_bits);
230 }
231 #endif
232
233 void NSSCertDatabaseChromeOS::SetPrivateSlot(
234 crypto::ScopedPK11Slot private_slot) {
235 DCHECK(!ready_);
236 if (!private_slot)
237 LOG(WARNING) << "initializing with NULL private_slot.";
238 private_slot_ = private_slot.Pass();
239 profile_filter_.Init(GetPublicSlot(), GetPrivateSlot());
240 ready_ = true;
241
242 for (ReadyCallbackList::iterator i = ready_callback_list_.begin();
243 i != ready_callback_list_.end();
244 ++i) {
245 (*i).Run(this);
246 }
247 ready_callback_list_.clear();
248 }
249
250 void NSSCertDatabaseChromeOS::OnReady(
251 const base::Callback<void(NSSCertDatabase*)>& callback) {
252 if (ready_)
253 callback.Run(this);
254 else
255 ready_callback_list_.push_back(callback);
256 }
257
258 scoped_refptr<const X509Certificate> NSSCertDatabaseChromeOS::ResolveCert(
259 const X509Certificate* cert, bool need_rw) const {
260 // If we have a copy in our slot, use that.
261 scoped_refptr<const X509Certificate> pub_slot_cert(
262 FindCertInSlot(cert, public_slot_.get()));
263 if (pub_slot_cert) {
264 VLOG(1) << "found pub slot cert";
265 return pub_slot_cert;
266 }
267
268 CryptoModuleList module_list;
269 ListModules(&module_list, need_rw);
270 for (CryptoModuleList::iterator i = module_list.begin();
271 i != module_list.end();
272 ++i) {
273 if ((*i)->os_module_handle() == public_slot_.get())
274 continue; // We already checked this slot above.
275 scoped_refptr<const X509Certificate> slot_cert(
276 FindCertInSlot(cert, (*i)->os_module_handle()));
277 if (slot_cert) {
278 VLOG(1) << "found cert in other slot: "
279 << PK11_GetModuleID((*i)->os_module_handle()) << ":"
280 << PK11_GetSlotID((*i)->os_module_handle());
281 return slot_cert;
282 }
283 }
284
285 // Otherwise, use whatever NSS decides as the default.
286 // XXX should we return NULL here? NOTREACHED?
287 LOG(WARNING) << "using default slot cert";
288 return cert;
289 }
290
291 } // namespace net
OLDNEW
« no previous file with comments | « net/cert/nss_cert_database_chromeos.h ('k') | net/cert/nss_profile_filter_chromeos.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698