1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker
5*635a8641SAndroid Build Coastguard Worker #include "crypto/nss_util.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <nss.h>
8*635a8641SAndroid Build Coastguard Worker #include <pk11pub.h>
9*635a8641SAndroid Build Coastguard Worker #include <plarena.h>
10*635a8641SAndroid Build Coastguard Worker #include <prerror.h>
11*635a8641SAndroid Build Coastguard Worker #include <prinit.h>
12*635a8641SAndroid Build Coastguard Worker #include <prtime.h>
13*635a8641SAndroid Build Coastguard Worker #include <secmod.h>
14*635a8641SAndroid Build Coastguard Worker
15*635a8641SAndroid Build Coastguard Worker #include <map>
16*635a8641SAndroid Build Coastguard Worker #include <memory>
17*635a8641SAndroid Build Coastguard Worker #include <utility>
18*635a8641SAndroid Build Coastguard Worker #include <vector>
19*635a8641SAndroid Build Coastguard Worker
20*635a8641SAndroid Build Coastguard Worker #include "base/base_paths.h"
21*635a8641SAndroid Build Coastguard Worker #include "base/bind.h"
22*635a8641SAndroid Build Coastguard Worker #include "base/debug/alias.h"
23*635a8641SAndroid Build Coastguard Worker #include "base/debug/stack_trace.h"
24*635a8641SAndroid Build Coastguard Worker #include "base/files/file_path.h"
25*635a8641SAndroid Build Coastguard Worker #include "base/files/file_util.h"
26*635a8641SAndroid Build Coastguard Worker #include "base/lazy_instance.h"
27*635a8641SAndroid Build Coastguard Worker #include "base/location.h"
28*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
29*635a8641SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
30*635a8641SAndroid Build Coastguard Worker #include "base/path_service.h"
31*635a8641SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
32*635a8641SAndroid Build Coastguard Worker #include "base/task_scheduler/post_task.h"
33*635a8641SAndroid Build Coastguard Worker #include "base/threading/scoped_blocking_call.h"
34*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_checker.h"
35*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
36*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_task_runner_handle.h"
37*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
38*635a8641SAndroid Build Coastguard Worker #include "crypto/nss_crypto_module_delegate.h"
39*635a8641SAndroid Build Coastguard Worker #include "crypto/nss_util_internal.h"
40*635a8641SAndroid Build Coastguard Worker
41*635a8641SAndroid Build Coastguard Worker #if defined(OS_CHROMEOS)
42*635a8641SAndroid Build Coastguard Worker #include <dlfcn.h>
43*635a8641SAndroid Build Coastguard Worker #endif
44*635a8641SAndroid Build Coastguard Worker
45*635a8641SAndroid Build Coastguard Worker namespace crypto {
46*635a8641SAndroid Build Coastguard Worker
47*635a8641SAndroid Build Coastguard Worker namespace {
48*635a8641SAndroid Build Coastguard Worker
49*635a8641SAndroid Build Coastguard Worker #if defined(OS_CHROMEOS)
50*635a8641SAndroid Build Coastguard Worker const char kUserNSSDatabaseName[] = "UserNSSDB";
51*635a8641SAndroid Build Coastguard Worker
52*635a8641SAndroid Build Coastguard Worker // Constants for loading the Chrome OS TPM-backed PKCS #11 library.
53*635a8641SAndroid Build Coastguard Worker const char kChapsModuleName[] = "Chaps";
54*635a8641SAndroid Build Coastguard Worker const char kChapsPath[] = "libchaps.so";
55*635a8641SAndroid Build Coastguard Worker
56*635a8641SAndroid Build Coastguard Worker // Fake certificate authority database used for testing.
57*635a8641SAndroid Build Coastguard Worker static const base::FilePath::CharType kReadOnlyCertDB[] =
58*635a8641SAndroid Build Coastguard Worker FILE_PATH_LITERAL("/etc/fake_root_ca/nssdb");
59*635a8641SAndroid Build Coastguard Worker #endif // defined(OS_CHROMEOS)
60*635a8641SAndroid Build Coastguard Worker
GetNSSErrorMessage()61*635a8641SAndroid Build Coastguard Worker std::string GetNSSErrorMessage() {
62*635a8641SAndroid Build Coastguard Worker std::string result;
63*635a8641SAndroid Build Coastguard Worker if (PR_GetErrorTextLength()) {
64*635a8641SAndroid Build Coastguard Worker std::unique_ptr<char[]> error_text(new char[PR_GetErrorTextLength() + 1]);
65*635a8641SAndroid Build Coastguard Worker PRInt32 copied = PR_GetErrorText(error_text.get());
66*635a8641SAndroid Build Coastguard Worker result = std::string(error_text.get(), copied);
67*635a8641SAndroid Build Coastguard Worker } else {
68*635a8641SAndroid Build Coastguard Worker result = base::StringPrintf("NSS error code: %d", PR_GetError());
69*635a8641SAndroid Build Coastguard Worker }
70*635a8641SAndroid Build Coastguard Worker return result;
71*635a8641SAndroid Build Coastguard Worker }
72*635a8641SAndroid Build Coastguard Worker
73*635a8641SAndroid Build Coastguard Worker #if !defined(OS_CHROMEOS)
GetDefaultConfigDirectory()74*635a8641SAndroid Build Coastguard Worker base::FilePath GetDefaultConfigDirectory() {
75*635a8641SAndroid Build Coastguard Worker base::FilePath dir;
76*635a8641SAndroid Build Coastguard Worker base::PathService::Get(base::DIR_HOME, &dir);
77*635a8641SAndroid Build Coastguard Worker if (dir.empty()) {
78*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to get home directory.";
79*635a8641SAndroid Build Coastguard Worker return dir;
80*635a8641SAndroid Build Coastguard Worker }
81*635a8641SAndroid Build Coastguard Worker dir = dir.AppendASCII(".pki").AppendASCII("nssdb");
82*635a8641SAndroid Build Coastguard Worker if (!base::CreateDirectory(dir)) {
83*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to create " << dir.value() << " directory.";
84*635a8641SAndroid Build Coastguard Worker dir.clear();
85*635a8641SAndroid Build Coastguard Worker }
86*635a8641SAndroid Build Coastguard Worker DVLOG(2) << "DefaultConfigDirectory: " << dir.value();
87*635a8641SAndroid Build Coastguard Worker return dir;
88*635a8641SAndroid Build Coastguard Worker }
89*635a8641SAndroid Build Coastguard Worker #endif // !defined(OS_CHROMEOS)
90*635a8641SAndroid Build Coastguard Worker
91*635a8641SAndroid Build Coastguard Worker // On non-Chrome OS platforms, return the default config directory. On Chrome OS
92*635a8641SAndroid Build Coastguard Worker // test images, return a read-only directory with fake root CA certs (which are
93*635a8641SAndroid Build Coastguard Worker // used by the local Google Accounts server mock we use when testing our login
94*635a8641SAndroid Build Coastguard Worker // code). On Chrome OS non-test images (where the read-only directory doesn't
95*635a8641SAndroid Build Coastguard Worker // exist), return an empty path.
GetInitialConfigDirectory()96*635a8641SAndroid Build Coastguard Worker base::FilePath GetInitialConfigDirectory() {
97*635a8641SAndroid Build Coastguard Worker #if defined(OS_CHROMEOS)
98*635a8641SAndroid Build Coastguard Worker base::FilePath database_dir = base::FilePath(kReadOnlyCertDB);
99*635a8641SAndroid Build Coastguard Worker if (!base::PathExists(database_dir))
100*635a8641SAndroid Build Coastguard Worker database_dir.clear();
101*635a8641SAndroid Build Coastguard Worker return database_dir;
102*635a8641SAndroid Build Coastguard Worker #else
103*635a8641SAndroid Build Coastguard Worker return GetDefaultConfigDirectory();
104*635a8641SAndroid Build Coastguard Worker #endif // defined(OS_CHROMEOS)
105*635a8641SAndroid Build Coastguard Worker }
106*635a8641SAndroid Build Coastguard Worker
107*635a8641SAndroid Build Coastguard Worker // This callback for NSS forwards all requests to a caller-specified
108*635a8641SAndroid Build Coastguard Worker // CryptoModuleBlockingPasswordDelegate object.
PKCS11PasswordFunc(PK11SlotInfo * slot,PRBool retry,void * arg)109*635a8641SAndroid Build Coastguard Worker char* PKCS11PasswordFunc(PK11SlotInfo* slot, PRBool retry, void* arg) {
110*635a8641SAndroid Build Coastguard Worker crypto::CryptoModuleBlockingPasswordDelegate* delegate =
111*635a8641SAndroid Build Coastguard Worker reinterpret_cast<crypto::CryptoModuleBlockingPasswordDelegate*>(arg);
112*635a8641SAndroid Build Coastguard Worker if (delegate) {
113*635a8641SAndroid Build Coastguard Worker bool cancelled = false;
114*635a8641SAndroid Build Coastguard Worker std::string password = delegate->RequestPassword(PK11_GetTokenName(slot),
115*635a8641SAndroid Build Coastguard Worker retry != PR_FALSE,
116*635a8641SAndroid Build Coastguard Worker &cancelled);
117*635a8641SAndroid Build Coastguard Worker if (cancelled)
118*635a8641SAndroid Build Coastguard Worker return nullptr;
119*635a8641SAndroid Build Coastguard Worker char* result = PORT_Strdup(password.c_str());
120*635a8641SAndroid Build Coastguard Worker password.replace(0, password.size(), password.size(), 0);
121*635a8641SAndroid Build Coastguard Worker return result;
122*635a8641SAndroid Build Coastguard Worker }
123*635a8641SAndroid Build Coastguard Worker DLOG(ERROR) << "PK11 password requested with nullptr arg";
124*635a8641SAndroid Build Coastguard Worker return nullptr;
125*635a8641SAndroid Build Coastguard Worker }
126*635a8641SAndroid Build Coastguard Worker
127*635a8641SAndroid Build Coastguard Worker // A singleton to initialize/deinitialize NSPR.
128*635a8641SAndroid Build Coastguard Worker // Separate from the NSS singleton because we initialize NSPR on the UI thread.
129*635a8641SAndroid Build Coastguard Worker // Now that we're leaking the singleton, we could merge back with the NSS
130*635a8641SAndroid Build Coastguard Worker // singleton.
131*635a8641SAndroid Build Coastguard Worker class NSPRInitSingleton {
132*635a8641SAndroid Build Coastguard Worker private:
133*635a8641SAndroid Build Coastguard Worker friend struct base::LazyInstanceTraitsBase<NSPRInitSingleton>;
134*635a8641SAndroid Build Coastguard Worker
NSPRInitSingleton()135*635a8641SAndroid Build Coastguard Worker NSPRInitSingleton() {
136*635a8641SAndroid Build Coastguard Worker PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
137*635a8641SAndroid Build Coastguard Worker }
138*635a8641SAndroid Build Coastguard Worker
139*635a8641SAndroid Build Coastguard Worker // NOTE(willchan): We don't actually cleanup on destruction since we leak NSS
140*635a8641SAndroid Build Coastguard Worker // to prevent non-joinable threads from using NSS after it's already been
141*635a8641SAndroid Build Coastguard Worker // shut down.
142*635a8641SAndroid Build Coastguard Worker ~NSPRInitSingleton() = delete;
143*635a8641SAndroid Build Coastguard Worker };
144*635a8641SAndroid Build Coastguard Worker
145*635a8641SAndroid Build Coastguard Worker base::LazyInstance<NSPRInitSingleton>::Leaky
146*635a8641SAndroid Build Coastguard Worker g_nspr_singleton = LAZY_INSTANCE_INITIALIZER;
147*635a8641SAndroid Build Coastguard Worker
148*635a8641SAndroid Build Coastguard Worker // Force a crash with error info on NSS_NoDB_Init failure.
CrashOnNSSInitFailure()149*635a8641SAndroid Build Coastguard Worker void CrashOnNSSInitFailure() {
150*635a8641SAndroid Build Coastguard Worker int nss_error = PR_GetError();
151*635a8641SAndroid Build Coastguard Worker int os_error = PR_GetOSError();
152*635a8641SAndroid Build Coastguard Worker base::debug::Alias(&nss_error);
153*635a8641SAndroid Build Coastguard Worker base::debug::Alias(&os_error);
154*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Error initializing NSS without a persistent database: "
155*635a8641SAndroid Build Coastguard Worker << GetNSSErrorMessage();
156*635a8641SAndroid Build Coastguard Worker LOG(FATAL) << "nss_error=" << nss_error << ", os_error=" << os_error;
157*635a8641SAndroid Build Coastguard Worker }
158*635a8641SAndroid Build Coastguard Worker
159*635a8641SAndroid Build Coastguard Worker #if defined(OS_CHROMEOS)
160*635a8641SAndroid Build Coastguard Worker class ChromeOSUserData {
161*635a8641SAndroid Build Coastguard Worker public:
ChromeOSUserData(ScopedPK11Slot public_slot)162*635a8641SAndroid Build Coastguard Worker explicit ChromeOSUserData(ScopedPK11Slot public_slot)
163*635a8641SAndroid Build Coastguard Worker : public_slot_(std::move(public_slot)),
164*635a8641SAndroid Build Coastguard Worker private_slot_initialization_started_(false) {}
~ChromeOSUserData()165*635a8641SAndroid Build Coastguard Worker ~ChromeOSUserData() {
166*635a8641SAndroid Build Coastguard Worker if (public_slot_) {
167*635a8641SAndroid Build Coastguard Worker SECStatus status = SECMOD_CloseUserDB(public_slot_.get());
168*635a8641SAndroid Build Coastguard Worker if (status != SECSuccess)
169*635a8641SAndroid Build Coastguard Worker PLOG(ERROR) << "SECMOD_CloseUserDB failed: " << PORT_GetError();
170*635a8641SAndroid Build Coastguard Worker }
171*635a8641SAndroid Build Coastguard Worker }
172*635a8641SAndroid Build Coastguard Worker
GetPublicSlot()173*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot GetPublicSlot() {
174*635a8641SAndroid Build Coastguard Worker return ScopedPK11Slot(public_slot_ ? PK11_ReferenceSlot(public_slot_.get())
175*635a8641SAndroid Build Coastguard Worker : nullptr);
176*635a8641SAndroid Build Coastguard Worker }
177*635a8641SAndroid Build Coastguard Worker
GetPrivateSlot(base::OnceCallback<void (ScopedPK11Slot)> callback)178*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot GetPrivateSlot(
179*635a8641SAndroid Build Coastguard Worker base::OnceCallback<void(ScopedPK11Slot)> callback) {
180*635a8641SAndroid Build Coastguard Worker if (private_slot_)
181*635a8641SAndroid Build Coastguard Worker return ScopedPK11Slot(PK11_ReferenceSlot(private_slot_.get()));
182*635a8641SAndroid Build Coastguard Worker if (!callback.is_null())
183*635a8641SAndroid Build Coastguard Worker tpm_ready_callback_list_.push_back(std::move(callback));
184*635a8641SAndroid Build Coastguard Worker return ScopedPK11Slot();
185*635a8641SAndroid Build Coastguard Worker }
186*635a8641SAndroid Build Coastguard Worker
SetPrivateSlot(ScopedPK11Slot private_slot)187*635a8641SAndroid Build Coastguard Worker void SetPrivateSlot(ScopedPK11Slot private_slot) {
188*635a8641SAndroid Build Coastguard Worker DCHECK(!private_slot_);
189*635a8641SAndroid Build Coastguard Worker private_slot_ = std::move(private_slot);
190*635a8641SAndroid Build Coastguard Worker
191*635a8641SAndroid Build Coastguard Worker SlotReadyCallbackList callback_list;
192*635a8641SAndroid Build Coastguard Worker callback_list.swap(tpm_ready_callback_list_);
193*635a8641SAndroid Build Coastguard Worker for (SlotReadyCallbackList::iterator i = callback_list.begin();
194*635a8641SAndroid Build Coastguard Worker i != callback_list.end();
195*635a8641SAndroid Build Coastguard Worker ++i) {
196*635a8641SAndroid Build Coastguard Worker std::move(*i).Run(
197*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot(PK11_ReferenceSlot(private_slot_.get())));
198*635a8641SAndroid Build Coastguard Worker }
199*635a8641SAndroid Build Coastguard Worker }
200*635a8641SAndroid Build Coastguard Worker
private_slot_initialization_started() const201*635a8641SAndroid Build Coastguard Worker bool private_slot_initialization_started() const {
202*635a8641SAndroid Build Coastguard Worker return private_slot_initialization_started_;
203*635a8641SAndroid Build Coastguard Worker }
204*635a8641SAndroid Build Coastguard Worker
set_private_slot_initialization_started()205*635a8641SAndroid Build Coastguard Worker void set_private_slot_initialization_started() {
206*635a8641SAndroid Build Coastguard Worker private_slot_initialization_started_ = true;
207*635a8641SAndroid Build Coastguard Worker }
208*635a8641SAndroid Build Coastguard Worker
209*635a8641SAndroid Build Coastguard Worker private:
210*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot public_slot_;
211*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot private_slot_;
212*635a8641SAndroid Build Coastguard Worker
213*635a8641SAndroid Build Coastguard Worker bool private_slot_initialization_started_;
214*635a8641SAndroid Build Coastguard Worker
215*635a8641SAndroid Build Coastguard Worker typedef std::vector<base::OnceCallback<void(ScopedPK11Slot)>>
216*635a8641SAndroid Build Coastguard Worker SlotReadyCallbackList;
217*635a8641SAndroid Build Coastguard Worker SlotReadyCallbackList tpm_ready_callback_list_;
218*635a8641SAndroid Build Coastguard Worker };
219*635a8641SAndroid Build Coastguard Worker
220*635a8641SAndroid Build Coastguard Worker class ScopedChapsLoadFixup {
221*635a8641SAndroid Build Coastguard Worker public:
222*635a8641SAndroid Build Coastguard Worker ScopedChapsLoadFixup();
223*635a8641SAndroid Build Coastguard Worker ~ScopedChapsLoadFixup();
224*635a8641SAndroid Build Coastguard Worker
225*635a8641SAndroid Build Coastguard Worker private:
226*635a8641SAndroid Build Coastguard Worker #if defined(COMPONENT_BUILD)
227*635a8641SAndroid Build Coastguard Worker void* chaps_handle_;
228*635a8641SAndroid Build Coastguard Worker #endif
229*635a8641SAndroid Build Coastguard Worker };
230*635a8641SAndroid Build Coastguard Worker
231*635a8641SAndroid Build Coastguard Worker #if defined(COMPONENT_BUILD)
232*635a8641SAndroid Build Coastguard Worker
ScopedChapsLoadFixup()233*635a8641SAndroid Build Coastguard Worker ScopedChapsLoadFixup::ScopedChapsLoadFixup() {
234*635a8641SAndroid Build Coastguard Worker // HACK: libchaps links the system protobuf and there are symbol conflicts
235*635a8641SAndroid Build Coastguard Worker // with the bundled copy. Load chaps with RTLD_DEEPBIND to workaround.
236*635a8641SAndroid Build Coastguard Worker chaps_handle_ = dlopen(kChapsPath, RTLD_LOCAL | RTLD_NOW | RTLD_DEEPBIND);
237*635a8641SAndroid Build Coastguard Worker }
238*635a8641SAndroid Build Coastguard Worker
~ScopedChapsLoadFixup()239*635a8641SAndroid Build Coastguard Worker ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {
240*635a8641SAndroid Build Coastguard Worker // LoadModule() will have taken a 2nd reference.
241*635a8641SAndroid Build Coastguard Worker if (chaps_handle_)
242*635a8641SAndroid Build Coastguard Worker dlclose(chaps_handle_);
243*635a8641SAndroid Build Coastguard Worker }
244*635a8641SAndroid Build Coastguard Worker
245*635a8641SAndroid Build Coastguard Worker #else
246*635a8641SAndroid Build Coastguard Worker
ScopedChapsLoadFixup()247*635a8641SAndroid Build Coastguard Worker ScopedChapsLoadFixup::ScopedChapsLoadFixup() {}
~ScopedChapsLoadFixup()248*635a8641SAndroid Build Coastguard Worker ScopedChapsLoadFixup::~ScopedChapsLoadFixup() {}
249*635a8641SAndroid Build Coastguard Worker
250*635a8641SAndroid Build Coastguard Worker #endif // defined(COMPONENT_BUILD)
251*635a8641SAndroid Build Coastguard Worker #endif // defined(OS_CHROMEOS)
252*635a8641SAndroid Build Coastguard Worker
253*635a8641SAndroid Build Coastguard Worker class NSSInitSingleton {
254*635a8641SAndroid Build Coastguard Worker public:
255*635a8641SAndroid Build Coastguard Worker #if defined(OS_CHROMEOS)
256*635a8641SAndroid Build Coastguard Worker // Used with PostTaskAndReply to pass handles to worker thread and back.
257*635a8641SAndroid Build Coastguard Worker struct TPMModuleAndSlot {
TPMModuleAndSlotcrypto::__anon1d0ef6600111::NSSInitSingleton::TPMModuleAndSlot258*635a8641SAndroid Build Coastguard Worker explicit TPMModuleAndSlot(SECMODModule* init_chaps_module)
259*635a8641SAndroid Build Coastguard Worker : chaps_module(init_chaps_module) {}
260*635a8641SAndroid Build Coastguard Worker SECMODModule* chaps_module;
261*635a8641SAndroid Build Coastguard Worker crypto::ScopedPK11Slot tpm_slot;
262*635a8641SAndroid Build Coastguard Worker };
263*635a8641SAndroid Build Coastguard Worker
OpenPersistentNSSDBForPath(const std::string & db_name,const base::FilePath & path)264*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot OpenPersistentNSSDBForPath(const std::string& db_name,
265*635a8641SAndroid Build Coastguard Worker const base::FilePath& path) {
266*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
267*635a8641SAndroid Build Coastguard Worker // NSS is allowed to do IO on the current thread since dispatching
268*635a8641SAndroid Build Coastguard Worker // to a dedicated thread would still have the affect of blocking
269*635a8641SAndroid Build Coastguard Worker // the current thread, due to NSS's internal locking requirements
270*635a8641SAndroid Build Coastguard Worker base::ThreadRestrictions::ScopedAllowIO allow_io;
271*635a8641SAndroid Build Coastguard Worker
272*635a8641SAndroid Build Coastguard Worker base::FilePath nssdb_path = path.AppendASCII(".pki").AppendASCII("nssdb");
273*635a8641SAndroid Build Coastguard Worker if (!base::CreateDirectory(nssdb_path)) {
274*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Failed to create " << nssdb_path.value() << " directory.";
275*635a8641SAndroid Build Coastguard Worker return ScopedPK11Slot();
276*635a8641SAndroid Build Coastguard Worker }
277*635a8641SAndroid Build Coastguard Worker return OpenSoftwareNSSDB(nssdb_path, db_name);
278*635a8641SAndroid Build Coastguard Worker }
279*635a8641SAndroid Build Coastguard Worker
EnableTPMTokenForNSS()280*635a8641SAndroid Build Coastguard Worker void EnableTPMTokenForNSS() {
281*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
282*635a8641SAndroid Build Coastguard Worker
283*635a8641SAndroid Build Coastguard Worker // If this gets set, then we'll use the TPM for certs with
284*635a8641SAndroid Build Coastguard Worker // private keys, otherwise we'll fall back to the software
285*635a8641SAndroid Build Coastguard Worker // implementation.
286*635a8641SAndroid Build Coastguard Worker tpm_token_enabled_for_nss_ = true;
287*635a8641SAndroid Build Coastguard Worker }
288*635a8641SAndroid Build Coastguard Worker
IsTPMTokenEnabledForNSS()289*635a8641SAndroid Build Coastguard Worker bool IsTPMTokenEnabledForNSS() {
290*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
291*635a8641SAndroid Build Coastguard Worker return tpm_token_enabled_for_nss_;
292*635a8641SAndroid Build Coastguard Worker }
293*635a8641SAndroid Build Coastguard Worker
InitializeTPMTokenAndSystemSlot(int system_slot_id,base::OnceCallback<void (bool)> callback)294*635a8641SAndroid Build Coastguard Worker void InitializeTPMTokenAndSystemSlot(
295*635a8641SAndroid Build Coastguard Worker int system_slot_id,
296*635a8641SAndroid Build Coastguard Worker base::OnceCallback<void(bool)> callback) {
297*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
298*635a8641SAndroid Build Coastguard Worker // Should not be called while there is already an initialization in
299*635a8641SAndroid Build Coastguard Worker // progress.
300*635a8641SAndroid Build Coastguard Worker DCHECK(!initializing_tpm_token_);
301*635a8641SAndroid Build Coastguard Worker // If EnableTPMTokenForNSS hasn't been called, return false.
302*635a8641SAndroid Build Coastguard Worker if (!tpm_token_enabled_for_nss_) {
303*635a8641SAndroid Build Coastguard Worker base::ThreadTaskRunnerHandle::Get()->PostTask(
304*635a8641SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(std::move(callback), false));
305*635a8641SAndroid Build Coastguard Worker return;
306*635a8641SAndroid Build Coastguard Worker }
307*635a8641SAndroid Build Coastguard Worker
308*635a8641SAndroid Build Coastguard Worker // If everything is already initialized, then return true.
309*635a8641SAndroid Build Coastguard Worker // Note that only |tpm_slot_| is checked, since |chaps_module_| could be
310*635a8641SAndroid Build Coastguard Worker // nullptr in tests while |tpm_slot_| has been set to the test DB.
311*635a8641SAndroid Build Coastguard Worker if (tpm_slot_) {
312*635a8641SAndroid Build Coastguard Worker base::ThreadTaskRunnerHandle::Get()->PostTask(
313*635a8641SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(std::move(callback), true));
314*635a8641SAndroid Build Coastguard Worker return;
315*635a8641SAndroid Build Coastguard Worker }
316*635a8641SAndroid Build Coastguard Worker
317*635a8641SAndroid Build Coastguard Worker // Note that a reference is not taken to chaps_module_. This is safe since
318*635a8641SAndroid Build Coastguard Worker // NSSInitSingleton is Leaky, so the reference it holds is never released.
319*635a8641SAndroid Build Coastguard Worker std::unique_ptr<TPMModuleAndSlot> tpm_args(
320*635a8641SAndroid Build Coastguard Worker new TPMModuleAndSlot(chaps_module_));
321*635a8641SAndroid Build Coastguard Worker TPMModuleAndSlot* tpm_args_ptr = tpm_args.get();
322*635a8641SAndroid Build Coastguard Worker base::PostTaskWithTraitsAndReply(
323*635a8641SAndroid Build Coastguard Worker FROM_HERE,
324*635a8641SAndroid Build Coastguard Worker {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
325*635a8641SAndroid Build Coastguard Worker base::BindOnce(&NSSInitSingleton::InitializeTPMTokenInThreadPool,
326*635a8641SAndroid Build Coastguard Worker system_slot_id, tpm_args_ptr),
327*635a8641SAndroid Build Coastguard Worker base::BindOnce(&NSSInitSingleton::OnInitializedTPMTokenAndSystemSlot,
328*635a8641SAndroid Build Coastguard Worker base::Unretained(this), // NSSInitSingleton is leaky
329*635a8641SAndroid Build Coastguard Worker std::move(callback), std::move(tpm_args)));
330*635a8641SAndroid Build Coastguard Worker initializing_tpm_token_ = true;
331*635a8641SAndroid Build Coastguard Worker }
332*635a8641SAndroid Build Coastguard Worker
InitializeTPMTokenInThreadPool(CK_SLOT_ID token_slot_id,TPMModuleAndSlot * tpm_args)333*635a8641SAndroid Build Coastguard Worker static void InitializeTPMTokenInThreadPool(CK_SLOT_ID token_slot_id,
334*635a8641SAndroid Build Coastguard Worker TPMModuleAndSlot* tpm_args) {
335*635a8641SAndroid Build Coastguard Worker // NSS functions may reenter //net via extension hooks. If the reentered
336*635a8641SAndroid Build Coastguard Worker // code needs to synchronously wait for a task to run but the thread pool in
337*635a8641SAndroid Build Coastguard Worker // which that task must run doesn't have enough threads to schedule it, a
338*635a8641SAndroid Build Coastguard Worker // deadlock occurs. To prevent that, the base::ScopedBlockingCall below
339*635a8641SAndroid Build Coastguard Worker // increments the thread pool capacity for the duration of the TPM
340*635a8641SAndroid Build Coastguard Worker // initialization.
341*635a8641SAndroid Build Coastguard Worker base::ScopedBlockingCall scoped_blocking_call(
342*635a8641SAndroid Build Coastguard Worker base::BlockingType::WILL_BLOCK);
343*635a8641SAndroid Build Coastguard Worker
344*635a8641SAndroid Build Coastguard Worker if (!tpm_args->chaps_module) {
345*635a8641SAndroid Build Coastguard Worker ScopedChapsLoadFixup chaps_loader;
346*635a8641SAndroid Build Coastguard Worker
347*635a8641SAndroid Build Coastguard Worker DVLOG(3) << "Loading chaps...";
348*635a8641SAndroid Build Coastguard Worker tpm_args->chaps_module = LoadModule(
349*635a8641SAndroid Build Coastguard Worker kChapsModuleName,
350*635a8641SAndroid Build Coastguard Worker kChapsPath,
351*635a8641SAndroid Build Coastguard Worker // For more details on these parameters, see:
352*635a8641SAndroid Build Coastguard Worker // https://developer.mozilla.org/en/PKCS11_Module_Specs
353*635a8641SAndroid Build Coastguard Worker // slotFlags=[PublicCerts] -- Certificates and public keys can be
354*635a8641SAndroid Build Coastguard Worker // read from this slot without requiring a call to C_Login.
355*635a8641SAndroid Build Coastguard Worker // askpw=only -- Only authenticate to the token when necessary.
356*635a8641SAndroid Build Coastguard Worker "NSS=\"slotParams=(0={slotFlags=[PublicCerts] askpw=only})\"");
357*635a8641SAndroid Build Coastguard Worker }
358*635a8641SAndroid Build Coastguard Worker if (tpm_args->chaps_module) {
359*635a8641SAndroid Build Coastguard Worker tpm_args->tpm_slot =
360*635a8641SAndroid Build Coastguard Worker GetTPMSlotForIdInThreadPool(tpm_args->chaps_module, token_slot_id);
361*635a8641SAndroid Build Coastguard Worker }
362*635a8641SAndroid Build Coastguard Worker }
363*635a8641SAndroid Build Coastguard Worker
OnInitializedTPMTokenAndSystemSlot(base::OnceCallback<void (bool)> callback,std::unique_ptr<TPMModuleAndSlot> tpm_args)364*635a8641SAndroid Build Coastguard Worker void OnInitializedTPMTokenAndSystemSlot(
365*635a8641SAndroid Build Coastguard Worker base::OnceCallback<void(bool)> callback,
366*635a8641SAndroid Build Coastguard Worker std::unique_ptr<TPMModuleAndSlot> tpm_args) {
367*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
368*635a8641SAndroid Build Coastguard Worker DVLOG(2) << "Loaded chaps: " << !!tpm_args->chaps_module
369*635a8641SAndroid Build Coastguard Worker << ", got tpm slot: " << !!tpm_args->tpm_slot;
370*635a8641SAndroid Build Coastguard Worker
371*635a8641SAndroid Build Coastguard Worker chaps_module_ = tpm_args->chaps_module;
372*635a8641SAndroid Build Coastguard Worker tpm_slot_ = std::move(tpm_args->tpm_slot);
373*635a8641SAndroid Build Coastguard Worker if (!chaps_module_ && test_system_slot_) {
374*635a8641SAndroid Build Coastguard Worker // chromeos_unittests try to test the TPM initialization process. If we
375*635a8641SAndroid Build Coastguard Worker // have a test DB open, pretend that it is the TPM slot.
376*635a8641SAndroid Build Coastguard Worker tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get()));
377*635a8641SAndroid Build Coastguard Worker }
378*635a8641SAndroid Build Coastguard Worker initializing_tpm_token_ = false;
379*635a8641SAndroid Build Coastguard Worker
380*635a8641SAndroid Build Coastguard Worker if (tpm_slot_)
381*635a8641SAndroid Build Coastguard Worker RunAndClearTPMReadyCallbackList();
382*635a8641SAndroid Build Coastguard Worker
383*635a8641SAndroid Build Coastguard Worker std::move(callback).Run(!!tpm_slot_);
384*635a8641SAndroid Build Coastguard Worker }
385*635a8641SAndroid Build Coastguard Worker
RunAndClearTPMReadyCallbackList()386*635a8641SAndroid Build Coastguard Worker void RunAndClearTPMReadyCallbackList() {
387*635a8641SAndroid Build Coastguard Worker TPMReadyCallbackList callback_list;
388*635a8641SAndroid Build Coastguard Worker callback_list.swap(tpm_ready_callback_list_);
389*635a8641SAndroid Build Coastguard Worker for (TPMReadyCallbackList::iterator i = callback_list.begin();
390*635a8641SAndroid Build Coastguard Worker i != callback_list.end();
391*635a8641SAndroid Build Coastguard Worker ++i) {
392*635a8641SAndroid Build Coastguard Worker std::move(*i).Run();
393*635a8641SAndroid Build Coastguard Worker }
394*635a8641SAndroid Build Coastguard Worker }
395*635a8641SAndroid Build Coastguard Worker
IsTPMTokenReady(base::OnceClosure callback)396*635a8641SAndroid Build Coastguard Worker bool IsTPMTokenReady(base::OnceClosure callback) {
397*635a8641SAndroid Build Coastguard Worker if (!callback.is_null()) {
398*635a8641SAndroid Build Coastguard Worker // Cannot DCHECK in the general case yet, but since the callback is
399*635a8641SAndroid Build Coastguard Worker // a new addition to the API, DCHECK to make sure at least the new uses
400*635a8641SAndroid Build Coastguard Worker // don't regress.
401*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
402*635a8641SAndroid Build Coastguard Worker } else if (!thread_checker_.CalledOnValidThread()) {
403*635a8641SAndroid Build Coastguard Worker // TODO(mattm): Change to DCHECK when callers have been fixed.
404*635a8641SAndroid Build Coastguard Worker DVLOG(1) << "Called on wrong thread.\n"
405*635a8641SAndroid Build Coastguard Worker << base::debug::StackTrace().ToString();
406*635a8641SAndroid Build Coastguard Worker }
407*635a8641SAndroid Build Coastguard Worker
408*635a8641SAndroid Build Coastguard Worker if (tpm_slot_)
409*635a8641SAndroid Build Coastguard Worker return true;
410*635a8641SAndroid Build Coastguard Worker
411*635a8641SAndroid Build Coastguard Worker if (!callback.is_null())
412*635a8641SAndroid Build Coastguard Worker tpm_ready_callback_list_.push_back(std::move(callback));
413*635a8641SAndroid Build Coastguard Worker
414*635a8641SAndroid Build Coastguard Worker return false;
415*635a8641SAndroid Build Coastguard Worker }
416*635a8641SAndroid Build Coastguard Worker
417*635a8641SAndroid Build Coastguard Worker // Note that CK_SLOT_ID is an unsigned long, but cryptohome gives us the slot
418*635a8641SAndroid Build Coastguard Worker // id as an int. This should be safe since this is only used with chaps, which
419*635a8641SAndroid Build Coastguard Worker // we also control.
GetTPMSlotForIdInThreadPool(SECMODModule * chaps_module,CK_SLOT_ID slot_id)420*635a8641SAndroid Build Coastguard Worker static crypto::ScopedPK11Slot GetTPMSlotForIdInThreadPool(
421*635a8641SAndroid Build Coastguard Worker SECMODModule* chaps_module,
422*635a8641SAndroid Build Coastguard Worker CK_SLOT_ID slot_id) {
423*635a8641SAndroid Build Coastguard Worker DCHECK(chaps_module);
424*635a8641SAndroid Build Coastguard Worker
425*635a8641SAndroid Build Coastguard Worker DVLOG(3) << "Poking chaps module.";
426*635a8641SAndroid Build Coastguard Worker SECStatus rv = SECMOD_UpdateSlotList(chaps_module);
427*635a8641SAndroid Build Coastguard Worker if (rv != SECSuccess)
428*635a8641SAndroid Build Coastguard Worker PLOG(ERROR) << "SECMOD_UpdateSlotList failed: " << PORT_GetError();
429*635a8641SAndroid Build Coastguard Worker
430*635a8641SAndroid Build Coastguard Worker PK11SlotInfo* slot = SECMOD_LookupSlot(chaps_module->moduleID, slot_id);
431*635a8641SAndroid Build Coastguard Worker if (!slot)
432*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "TPM slot " << slot_id << " not found.";
433*635a8641SAndroid Build Coastguard Worker return crypto::ScopedPK11Slot(slot);
434*635a8641SAndroid Build Coastguard Worker }
435*635a8641SAndroid Build Coastguard Worker
InitializeNSSForChromeOSUser(const std::string & username_hash,const base::FilePath & path)436*635a8641SAndroid Build Coastguard Worker bool InitializeNSSForChromeOSUser(const std::string& username_hash,
437*635a8641SAndroid Build Coastguard Worker const base::FilePath& path) {
438*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
439*635a8641SAndroid Build Coastguard Worker if (chromeos_user_map_.find(username_hash) != chromeos_user_map_.end()) {
440*635a8641SAndroid Build Coastguard Worker // This user already exists in our mapping.
441*635a8641SAndroid Build Coastguard Worker DVLOG(2) << username_hash << " already initialized.";
442*635a8641SAndroid Build Coastguard Worker return false;
443*635a8641SAndroid Build Coastguard Worker }
444*635a8641SAndroid Build Coastguard Worker
445*635a8641SAndroid Build Coastguard Worker DVLOG(2) << "Opening NSS DB " << path.value();
446*635a8641SAndroid Build Coastguard Worker std::string db_name = base::StringPrintf(
447*635a8641SAndroid Build Coastguard Worker "%s %s", kUserNSSDatabaseName, username_hash.c_str());
448*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot public_slot(OpenPersistentNSSDBForPath(db_name, path));
449*635a8641SAndroid Build Coastguard Worker chromeos_user_map_[username_hash] =
450*635a8641SAndroid Build Coastguard Worker std::make_unique<ChromeOSUserData>(std::move(public_slot));
451*635a8641SAndroid Build Coastguard Worker return true;
452*635a8641SAndroid Build Coastguard Worker }
453*635a8641SAndroid Build Coastguard Worker
ShouldInitializeTPMForChromeOSUser(const std::string & username_hash)454*635a8641SAndroid Build Coastguard Worker bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) {
455*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
456*635a8641SAndroid Build Coastguard Worker DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
457*635a8641SAndroid Build Coastguard Worker
458*635a8641SAndroid Build Coastguard Worker return !chromeos_user_map_[username_hash]
459*635a8641SAndroid Build Coastguard Worker ->private_slot_initialization_started();
460*635a8641SAndroid Build Coastguard Worker }
461*635a8641SAndroid Build Coastguard Worker
WillInitializeTPMForChromeOSUser(const std::string & username_hash)462*635a8641SAndroid Build Coastguard Worker void WillInitializeTPMForChromeOSUser(const std::string& username_hash) {
463*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
464*635a8641SAndroid Build Coastguard Worker DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
465*635a8641SAndroid Build Coastguard Worker
466*635a8641SAndroid Build Coastguard Worker chromeos_user_map_[username_hash]
467*635a8641SAndroid Build Coastguard Worker ->set_private_slot_initialization_started();
468*635a8641SAndroid Build Coastguard Worker }
469*635a8641SAndroid Build Coastguard Worker
InitializeTPMForChromeOSUser(const std::string & username_hash,CK_SLOT_ID slot_id)470*635a8641SAndroid Build Coastguard Worker void InitializeTPMForChromeOSUser(const std::string& username_hash,
471*635a8641SAndroid Build Coastguard Worker CK_SLOT_ID slot_id) {
472*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
473*635a8641SAndroid Build Coastguard Worker DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
474*635a8641SAndroid Build Coastguard Worker DCHECK(chromeos_user_map_[username_hash]->
475*635a8641SAndroid Build Coastguard Worker private_slot_initialization_started());
476*635a8641SAndroid Build Coastguard Worker
477*635a8641SAndroid Build Coastguard Worker if (!chaps_module_)
478*635a8641SAndroid Build Coastguard Worker return;
479*635a8641SAndroid Build Coastguard Worker
480*635a8641SAndroid Build Coastguard Worker // Note that a reference is not taken to chaps_module_. This is safe since
481*635a8641SAndroid Build Coastguard Worker // NSSInitSingleton is Leaky, so the reference it holds is never released.
482*635a8641SAndroid Build Coastguard Worker std::unique_ptr<TPMModuleAndSlot> tpm_args(
483*635a8641SAndroid Build Coastguard Worker new TPMModuleAndSlot(chaps_module_));
484*635a8641SAndroid Build Coastguard Worker TPMModuleAndSlot* tpm_args_ptr = tpm_args.get();
485*635a8641SAndroid Build Coastguard Worker base::PostTaskWithTraitsAndReply(
486*635a8641SAndroid Build Coastguard Worker FROM_HERE,
487*635a8641SAndroid Build Coastguard Worker {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
488*635a8641SAndroid Build Coastguard Worker base::BindOnce(&NSSInitSingleton::InitializeTPMTokenInThreadPool,
489*635a8641SAndroid Build Coastguard Worker slot_id, tpm_args_ptr),
490*635a8641SAndroid Build Coastguard Worker base::BindOnce(&NSSInitSingleton::OnInitializedTPMForChromeOSUser,
491*635a8641SAndroid Build Coastguard Worker base::Unretained(this), // NSSInitSingleton is leaky
492*635a8641SAndroid Build Coastguard Worker username_hash, std::move(tpm_args)));
493*635a8641SAndroid Build Coastguard Worker }
494*635a8641SAndroid Build Coastguard Worker
OnInitializedTPMForChromeOSUser(const std::string & username_hash,std::unique_ptr<TPMModuleAndSlot> tpm_args)495*635a8641SAndroid Build Coastguard Worker void OnInitializedTPMForChromeOSUser(
496*635a8641SAndroid Build Coastguard Worker const std::string& username_hash,
497*635a8641SAndroid Build Coastguard Worker std::unique_ptr<TPMModuleAndSlot> tpm_args) {
498*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
499*635a8641SAndroid Build Coastguard Worker DVLOG(2) << "Got tpm slot for " << username_hash << " "
500*635a8641SAndroid Build Coastguard Worker << !!tpm_args->tpm_slot;
501*635a8641SAndroid Build Coastguard Worker chromeos_user_map_[username_hash]->SetPrivateSlot(
502*635a8641SAndroid Build Coastguard Worker std::move(tpm_args->tpm_slot));
503*635a8641SAndroid Build Coastguard Worker }
504*635a8641SAndroid Build Coastguard Worker
InitializePrivateSoftwareSlotForChromeOSUser(const std::string & username_hash)505*635a8641SAndroid Build Coastguard Worker void InitializePrivateSoftwareSlotForChromeOSUser(
506*635a8641SAndroid Build Coastguard Worker const std::string& username_hash) {
507*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
508*635a8641SAndroid Build Coastguard Worker VLOG(1) << "using software private slot for " << username_hash;
509*635a8641SAndroid Build Coastguard Worker DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
510*635a8641SAndroid Build Coastguard Worker DCHECK(chromeos_user_map_[username_hash]->
511*635a8641SAndroid Build Coastguard Worker private_slot_initialization_started());
512*635a8641SAndroid Build Coastguard Worker
513*635a8641SAndroid Build Coastguard Worker if (prepared_test_private_slot_) {
514*635a8641SAndroid Build Coastguard Worker chromeos_user_map_[username_hash]->SetPrivateSlot(
515*635a8641SAndroid Build Coastguard Worker std::move(prepared_test_private_slot_));
516*635a8641SAndroid Build Coastguard Worker return;
517*635a8641SAndroid Build Coastguard Worker }
518*635a8641SAndroid Build Coastguard Worker
519*635a8641SAndroid Build Coastguard Worker chromeos_user_map_[username_hash]->SetPrivateSlot(
520*635a8641SAndroid Build Coastguard Worker chromeos_user_map_[username_hash]->GetPublicSlot());
521*635a8641SAndroid Build Coastguard Worker }
522*635a8641SAndroid Build Coastguard Worker
GetPublicSlotForChromeOSUser(const std::string & username_hash)523*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot GetPublicSlotForChromeOSUser(
524*635a8641SAndroid Build Coastguard Worker const std::string& username_hash) {
525*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
526*635a8641SAndroid Build Coastguard Worker
527*635a8641SAndroid Build Coastguard Worker if (username_hash.empty()) {
528*635a8641SAndroid Build Coastguard Worker DVLOG(2) << "empty username_hash";
529*635a8641SAndroid Build Coastguard Worker return ScopedPK11Slot();
530*635a8641SAndroid Build Coastguard Worker }
531*635a8641SAndroid Build Coastguard Worker
532*635a8641SAndroid Build Coastguard Worker if (chromeos_user_map_.find(username_hash) == chromeos_user_map_.end()) {
533*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << username_hash << " not initialized.";
534*635a8641SAndroid Build Coastguard Worker return ScopedPK11Slot();
535*635a8641SAndroid Build Coastguard Worker }
536*635a8641SAndroid Build Coastguard Worker return chromeos_user_map_[username_hash]->GetPublicSlot();
537*635a8641SAndroid Build Coastguard Worker }
538*635a8641SAndroid Build Coastguard Worker
GetPrivateSlotForChromeOSUser(const std::string & username_hash,base::OnceCallback<void (ScopedPK11Slot)> callback)539*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot GetPrivateSlotForChromeOSUser(
540*635a8641SAndroid Build Coastguard Worker const std::string& username_hash,
541*635a8641SAndroid Build Coastguard Worker base::OnceCallback<void(ScopedPK11Slot)> callback) {
542*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
543*635a8641SAndroid Build Coastguard Worker
544*635a8641SAndroid Build Coastguard Worker if (username_hash.empty()) {
545*635a8641SAndroid Build Coastguard Worker DVLOG(2) << "empty username_hash";
546*635a8641SAndroid Build Coastguard Worker if (!callback.is_null()) {
547*635a8641SAndroid Build Coastguard Worker base::ThreadTaskRunnerHandle::Get()->PostTask(
548*635a8641SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(std::move(callback), ScopedPK11Slot()));
549*635a8641SAndroid Build Coastguard Worker }
550*635a8641SAndroid Build Coastguard Worker return ScopedPK11Slot();
551*635a8641SAndroid Build Coastguard Worker }
552*635a8641SAndroid Build Coastguard Worker
553*635a8641SAndroid Build Coastguard Worker DCHECK(chromeos_user_map_.find(username_hash) != chromeos_user_map_.end());
554*635a8641SAndroid Build Coastguard Worker
555*635a8641SAndroid Build Coastguard Worker return chromeos_user_map_[username_hash]->GetPrivateSlot(
556*635a8641SAndroid Build Coastguard Worker std::move(callback));
557*635a8641SAndroid Build Coastguard Worker }
558*635a8641SAndroid Build Coastguard Worker
CloseChromeOSUserForTesting(const std::string & username_hash)559*635a8641SAndroid Build Coastguard Worker void CloseChromeOSUserForTesting(const std::string& username_hash) {
560*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
561*635a8641SAndroid Build Coastguard Worker auto i = chromeos_user_map_.find(username_hash);
562*635a8641SAndroid Build Coastguard Worker DCHECK(i != chromeos_user_map_.end());
563*635a8641SAndroid Build Coastguard Worker chromeos_user_map_.erase(i);
564*635a8641SAndroid Build Coastguard Worker }
565*635a8641SAndroid Build Coastguard Worker
SetSystemKeySlotForTesting(ScopedPK11Slot slot)566*635a8641SAndroid Build Coastguard Worker void SetSystemKeySlotForTesting(ScopedPK11Slot slot) {
567*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
568*635a8641SAndroid Build Coastguard Worker
569*635a8641SAndroid Build Coastguard Worker // Ensure that a previous value of test_system_slot_ is not overwritten.
570*635a8641SAndroid Build Coastguard Worker // Unsetting, i.e. setting a nullptr, however is allowed.
571*635a8641SAndroid Build Coastguard Worker DCHECK(!slot || !test_system_slot_);
572*635a8641SAndroid Build Coastguard Worker test_system_slot_ = std::move(slot);
573*635a8641SAndroid Build Coastguard Worker if (test_system_slot_) {
574*635a8641SAndroid Build Coastguard Worker tpm_slot_.reset(PK11_ReferenceSlot(test_system_slot_.get()));
575*635a8641SAndroid Build Coastguard Worker RunAndClearTPMReadyCallbackList();
576*635a8641SAndroid Build Coastguard Worker } else {
577*635a8641SAndroid Build Coastguard Worker tpm_slot_.reset();
578*635a8641SAndroid Build Coastguard Worker }
579*635a8641SAndroid Build Coastguard Worker }
580*635a8641SAndroid Build Coastguard Worker
SetPrivateSoftwareSlotForChromeOSUserForTesting(ScopedPK11Slot slot)581*635a8641SAndroid Build Coastguard Worker void SetPrivateSoftwareSlotForChromeOSUserForTesting(ScopedPK11Slot slot) {
582*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
583*635a8641SAndroid Build Coastguard Worker
584*635a8641SAndroid Build Coastguard Worker // Ensure that a previous value of prepared_test_private_slot_ is not
585*635a8641SAndroid Build Coastguard Worker // overwritten. Unsetting, i.e. setting a nullptr, however is allowed.
586*635a8641SAndroid Build Coastguard Worker DCHECK(!slot || !prepared_test_private_slot_);
587*635a8641SAndroid Build Coastguard Worker prepared_test_private_slot_ = std::move(slot);
588*635a8641SAndroid Build Coastguard Worker }
589*635a8641SAndroid Build Coastguard Worker #endif // defined(OS_CHROMEOS)
590*635a8641SAndroid Build Coastguard Worker
591*635a8641SAndroid Build Coastguard Worker #if !defined(OS_CHROMEOS)
GetPersistentNSSKeySlot()592*635a8641SAndroid Build Coastguard Worker PK11SlotInfo* GetPersistentNSSKeySlot() {
593*635a8641SAndroid Build Coastguard Worker // TODO(mattm): Change to DCHECK when callers have been fixed.
594*635a8641SAndroid Build Coastguard Worker if (!thread_checker_.CalledOnValidThread()) {
595*635a8641SAndroid Build Coastguard Worker DVLOG(1) << "Called on wrong thread.\n"
596*635a8641SAndroid Build Coastguard Worker << base::debug::StackTrace().ToString();
597*635a8641SAndroid Build Coastguard Worker }
598*635a8641SAndroid Build Coastguard Worker
599*635a8641SAndroid Build Coastguard Worker return PK11_GetInternalKeySlot();
600*635a8641SAndroid Build Coastguard Worker }
601*635a8641SAndroid Build Coastguard Worker #endif
602*635a8641SAndroid Build Coastguard Worker
603*635a8641SAndroid Build Coastguard Worker #if defined(OS_CHROMEOS)
GetSystemNSSKeySlotCallback(base::OnceCallback<void (ScopedPK11Slot)> callback)604*635a8641SAndroid Build Coastguard Worker void GetSystemNSSKeySlotCallback(
605*635a8641SAndroid Build Coastguard Worker base::OnceCallback<void(ScopedPK11Slot)> callback) {
606*635a8641SAndroid Build Coastguard Worker std::move(callback).Run(
607*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get())));
608*635a8641SAndroid Build Coastguard Worker }
609*635a8641SAndroid Build Coastguard Worker
GetSystemNSSKeySlot(base::OnceCallback<void (ScopedPK11Slot)> callback)610*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot GetSystemNSSKeySlot(
611*635a8641SAndroid Build Coastguard Worker base::OnceCallback<void(ScopedPK11Slot)> callback) {
612*635a8641SAndroid Build Coastguard Worker DCHECK(thread_checker_.CalledOnValidThread());
613*635a8641SAndroid Build Coastguard Worker // TODO(mattm): chromeos::TPMTokenloader always calls
614*635a8641SAndroid Build Coastguard Worker // InitializeTPMTokenAndSystemSlot with slot 0. If the system slot is
615*635a8641SAndroid Build Coastguard Worker // disabled, tpm_slot_ will be the first user's slot instead. Can that be
616*635a8641SAndroid Build Coastguard Worker // detected and return nullptr instead?
617*635a8641SAndroid Build Coastguard Worker
618*635a8641SAndroid Build Coastguard Worker base::OnceClosure wrapped_callback;
619*635a8641SAndroid Build Coastguard Worker if (!callback.is_null()) {
620*635a8641SAndroid Build Coastguard Worker wrapped_callback = base::BindOnce(
621*635a8641SAndroid Build Coastguard Worker &NSSInitSingleton::GetSystemNSSKeySlotCallback,
622*635a8641SAndroid Build Coastguard Worker base::Unretained(this) /* singleton is leaky */, std::move(callback));
623*635a8641SAndroid Build Coastguard Worker }
624*635a8641SAndroid Build Coastguard Worker if (IsTPMTokenReady(std::move(wrapped_callback)))
625*635a8641SAndroid Build Coastguard Worker return ScopedPK11Slot(PK11_ReferenceSlot(tpm_slot_.get()));
626*635a8641SAndroid Build Coastguard Worker return ScopedPK11Slot();
627*635a8641SAndroid Build Coastguard Worker }
628*635a8641SAndroid Build Coastguard Worker #endif
629*635a8641SAndroid Build Coastguard Worker
630*635a8641SAndroid Build Coastguard Worker private:
631*635a8641SAndroid Build Coastguard Worker friend struct base::LazyInstanceTraitsBase<NSSInitSingleton>;
632*635a8641SAndroid Build Coastguard Worker
NSSInitSingleton()633*635a8641SAndroid Build Coastguard Worker NSSInitSingleton()
634*635a8641SAndroid Build Coastguard Worker : tpm_token_enabled_for_nss_(false),
635*635a8641SAndroid Build Coastguard Worker initializing_tpm_token_(false),
636*635a8641SAndroid Build Coastguard Worker chaps_module_(nullptr),
637*635a8641SAndroid Build Coastguard Worker root_(nullptr) {
638*635a8641SAndroid Build Coastguard Worker // Initializing NSS causes us to do blocking IO.
639*635a8641SAndroid Build Coastguard Worker // Temporarily allow it until we fix
640*635a8641SAndroid Build Coastguard Worker // http://code.google.com/p/chromium/issues/detail?id=59847
641*635a8641SAndroid Build Coastguard Worker base::ThreadRestrictions::ScopedAllowIO allow_io;
642*635a8641SAndroid Build Coastguard Worker
643*635a8641SAndroid Build Coastguard Worker // It's safe to construct on any thread, since LazyInstance will prevent any
644*635a8641SAndroid Build Coastguard Worker // other threads from accessing until the constructor is done.
645*635a8641SAndroid Build Coastguard Worker thread_checker_.DetachFromThread();
646*635a8641SAndroid Build Coastguard Worker
647*635a8641SAndroid Build Coastguard Worker EnsureNSPRInit();
648*635a8641SAndroid Build Coastguard Worker
649*635a8641SAndroid Build Coastguard Worker // We *must* have NSS >= 3.26 at compile time.
650*635a8641SAndroid Build Coastguard Worker static_assert((NSS_VMAJOR == 3 && NSS_VMINOR >= 26) || (NSS_VMAJOR > 3),
651*635a8641SAndroid Build Coastguard Worker "nss version check failed");
652*635a8641SAndroid Build Coastguard Worker // Also check the run-time NSS version.
653*635a8641SAndroid Build Coastguard Worker // NSS_VersionCheck is a >= check, not strict equality.
654*635a8641SAndroid Build Coastguard Worker if (!NSS_VersionCheck("3.26")) {
655*635a8641SAndroid Build Coastguard Worker LOG(FATAL) << "NSS_VersionCheck(\"3.26\") failed. NSS >= 3.26 is "
656*635a8641SAndroid Build Coastguard Worker "required. Please upgrade to the latest NSS, and if you "
657*635a8641SAndroid Build Coastguard Worker "still get this error, contact your distribution "
658*635a8641SAndroid Build Coastguard Worker "maintainer.";
659*635a8641SAndroid Build Coastguard Worker }
660*635a8641SAndroid Build Coastguard Worker
661*635a8641SAndroid Build Coastguard Worker SECStatus status = SECFailure;
662*635a8641SAndroid Build Coastguard Worker base::FilePath database_dir = GetInitialConfigDirectory();
663*635a8641SAndroid Build Coastguard Worker if (!database_dir.empty()) {
664*635a8641SAndroid Build Coastguard Worker // Initialize with a persistent database (likely, ~/.pki/nssdb).
665*635a8641SAndroid Build Coastguard Worker // Use "sql:" which can be shared by multiple processes safely.
666*635a8641SAndroid Build Coastguard Worker std::string nss_config_dir =
667*635a8641SAndroid Build Coastguard Worker base::StringPrintf("sql:%s", database_dir.value().c_str());
668*635a8641SAndroid Build Coastguard Worker #if defined(OS_CHROMEOS)
669*635a8641SAndroid Build Coastguard Worker status = NSS_Init(nss_config_dir.c_str());
670*635a8641SAndroid Build Coastguard Worker #else
671*635a8641SAndroid Build Coastguard Worker status = NSS_InitReadWrite(nss_config_dir.c_str());
672*635a8641SAndroid Build Coastguard Worker #endif
673*635a8641SAndroid Build Coastguard Worker if (status != SECSuccess) {
674*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Error initializing NSS with a persistent "
675*635a8641SAndroid Build Coastguard Worker "database (" << nss_config_dir
676*635a8641SAndroid Build Coastguard Worker << "): " << GetNSSErrorMessage();
677*635a8641SAndroid Build Coastguard Worker }
678*635a8641SAndroid Build Coastguard Worker }
679*635a8641SAndroid Build Coastguard Worker if (status != SECSuccess) {
680*635a8641SAndroid Build Coastguard Worker VLOG(1) << "Initializing NSS without a persistent database.";
681*635a8641SAndroid Build Coastguard Worker status = NSS_NoDB_Init(nullptr);
682*635a8641SAndroid Build Coastguard Worker if (status != SECSuccess) {
683*635a8641SAndroid Build Coastguard Worker CrashOnNSSInitFailure();
684*635a8641SAndroid Build Coastguard Worker return;
685*635a8641SAndroid Build Coastguard Worker }
686*635a8641SAndroid Build Coastguard Worker }
687*635a8641SAndroid Build Coastguard Worker
688*635a8641SAndroid Build Coastguard Worker PK11_SetPasswordFunc(PKCS11PasswordFunc);
689*635a8641SAndroid Build Coastguard Worker
690*635a8641SAndroid Build Coastguard Worker // If we haven't initialized the password for the NSS databases,
691*635a8641SAndroid Build Coastguard Worker // initialize an empty-string password so that we don't need to
692*635a8641SAndroid Build Coastguard Worker // log in.
693*635a8641SAndroid Build Coastguard Worker PK11SlotInfo* slot = PK11_GetInternalKeySlot();
694*635a8641SAndroid Build Coastguard Worker if (slot) {
695*635a8641SAndroid Build Coastguard Worker // PK11_InitPin may write to the keyDB, but no other thread can use NSS
696*635a8641SAndroid Build Coastguard Worker // yet, so we don't need to lock.
697*635a8641SAndroid Build Coastguard Worker if (PK11_NeedUserInit(slot))
698*635a8641SAndroid Build Coastguard Worker PK11_InitPin(slot, nullptr, nullptr);
699*635a8641SAndroid Build Coastguard Worker PK11_FreeSlot(slot);
700*635a8641SAndroid Build Coastguard Worker }
701*635a8641SAndroid Build Coastguard Worker
702*635a8641SAndroid Build Coastguard Worker root_ = InitDefaultRootCerts();
703*635a8641SAndroid Build Coastguard Worker
704*635a8641SAndroid Build Coastguard Worker // Disable MD5 certificate signatures. (They are disabled by default in
705*635a8641SAndroid Build Coastguard Worker // NSS 3.14.)
706*635a8641SAndroid Build Coastguard Worker NSS_SetAlgorithmPolicy(SEC_OID_MD5, 0, NSS_USE_ALG_IN_CERT_SIGNATURE);
707*635a8641SAndroid Build Coastguard Worker NSS_SetAlgorithmPolicy(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
708*635a8641SAndroid Build Coastguard Worker 0, NSS_USE_ALG_IN_CERT_SIGNATURE);
709*635a8641SAndroid Build Coastguard Worker }
710*635a8641SAndroid Build Coastguard Worker
711*635a8641SAndroid Build Coastguard Worker // NOTE(willchan): We don't actually cleanup on destruction since we leak NSS
712*635a8641SAndroid Build Coastguard Worker // to prevent non-joinable threads from using NSS after it's already been
713*635a8641SAndroid Build Coastguard Worker // shut down.
714*635a8641SAndroid Build Coastguard Worker ~NSSInitSingleton() = delete;
715*635a8641SAndroid Build Coastguard Worker
716*635a8641SAndroid Build Coastguard Worker // Load nss's built-in root certs.
InitDefaultRootCerts()717*635a8641SAndroid Build Coastguard Worker SECMODModule* InitDefaultRootCerts() {
718*635a8641SAndroid Build Coastguard Worker SECMODModule* root = LoadModule("Root Certs", "libnssckbi.so", nullptr);
719*635a8641SAndroid Build Coastguard Worker if (root)
720*635a8641SAndroid Build Coastguard Worker return root;
721*635a8641SAndroid Build Coastguard Worker
722*635a8641SAndroid Build Coastguard Worker // Aw, snap. Can't find/load root cert shared library.
723*635a8641SAndroid Build Coastguard Worker // This will make it hard to talk to anybody via https.
724*635a8641SAndroid Build Coastguard Worker // TODO(mattm): Re-add the NOTREACHED here when crbug.com/310972 is fixed.
725*635a8641SAndroid Build Coastguard Worker return nullptr;
726*635a8641SAndroid Build Coastguard Worker }
727*635a8641SAndroid Build Coastguard Worker
728*635a8641SAndroid Build Coastguard Worker // Load the given module for this NSS session.
LoadModule(const char * name,const char * library_path,const char * params)729*635a8641SAndroid Build Coastguard Worker static SECMODModule* LoadModule(const char* name,
730*635a8641SAndroid Build Coastguard Worker const char* library_path,
731*635a8641SAndroid Build Coastguard Worker const char* params) {
732*635a8641SAndroid Build Coastguard Worker std::string modparams = base::StringPrintf(
733*635a8641SAndroid Build Coastguard Worker "name=\"%s\" library=\"%s\" %s",
734*635a8641SAndroid Build Coastguard Worker name, library_path, params ? params : "");
735*635a8641SAndroid Build Coastguard Worker
736*635a8641SAndroid Build Coastguard Worker // Shouldn't need to const_cast here, but SECMOD doesn't properly
737*635a8641SAndroid Build Coastguard Worker // declare input string arguments as const. Bug
738*635a8641SAndroid Build Coastguard Worker // https://bugzilla.mozilla.org/show_bug.cgi?id=642546 was filed
739*635a8641SAndroid Build Coastguard Worker // on NSS codebase to address this.
740*635a8641SAndroid Build Coastguard Worker SECMODModule* module = SECMOD_LoadUserModule(
741*635a8641SAndroid Build Coastguard Worker const_cast<char*>(modparams.c_str()), nullptr, PR_FALSE);
742*635a8641SAndroid Build Coastguard Worker if (!module) {
743*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Error loading " << name << " module into NSS: "
744*635a8641SAndroid Build Coastguard Worker << GetNSSErrorMessage();
745*635a8641SAndroid Build Coastguard Worker return nullptr;
746*635a8641SAndroid Build Coastguard Worker }
747*635a8641SAndroid Build Coastguard Worker if (!module->loaded) {
748*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "After loading " << name << ", loaded==false: "
749*635a8641SAndroid Build Coastguard Worker << GetNSSErrorMessage();
750*635a8641SAndroid Build Coastguard Worker SECMOD_DestroyModule(module);
751*635a8641SAndroid Build Coastguard Worker return nullptr;
752*635a8641SAndroid Build Coastguard Worker }
753*635a8641SAndroid Build Coastguard Worker return module;
754*635a8641SAndroid Build Coastguard Worker }
755*635a8641SAndroid Build Coastguard Worker
756*635a8641SAndroid Build Coastguard Worker bool tpm_token_enabled_for_nss_;
757*635a8641SAndroid Build Coastguard Worker bool initializing_tpm_token_;
758*635a8641SAndroid Build Coastguard Worker typedef std::vector<base::OnceClosure> TPMReadyCallbackList;
759*635a8641SAndroid Build Coastguard Worker TPMReadyCallbackList tpm_ready_callback_list_;
760*635a8641SAndroid Build Coastguard Worker SECMODModule* chaps_module_;
761*635a8641SAndroid Build Coastguard Worker crypto::ScopedPK11Slot tpm_slot_;
762*635a8641SAndroid Build Coastguard Worker SECMODModule* root_;
763*635a8641SAndroid Build Coastguard Worker #if defined(OS_CHROMEOS)
764*635a8641SAndroid Build Coastguard Worker std::map<std::string, std::unique_ptr<ChromeOSUserData>> chromeos_user_map_;
765*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot test_system_slot_;
766*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot prepared_test_private_slot_;
767*635a8641SAndroid Build Coastguard Worker #endif
768*635a8641SAndroid Build Coastguard Worker
769*635a8641SAndroid Build Coastguard Worker base::ThreadChecker thread_checker_;
770*635a8641SAndroid Build Coastguard Worker };
771*635a8641SAndroid Build Coastguard Worker
772*635a8641SAndroid Build Coastguard Worker base::LazyInstance<NSSInitSingleton>::Leaky
773*635a8641SAndroid Build Coastguard Worker g_nss_singleton = LAZY_INSTANCE_INITIALIZER;
774*635a8641SAndroid Build Coastguard Worker } // namespace
775*635a8641SAndroid Build Coastguard Worker
OpenSoftwareNSSDB(const base::FilePath & path,const std::string & description)776*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot OpenSoftwareNSSDB(const base::FilePath& path,
777*635a8641SAndroid Build Coastguard Worker const std::string& description) {
778*635a8641SAndroid Build Coastguard Worker const std::string modspec =
779*635a8641SAndroid Build Coastguard Worker base::StringPrintf("configDir='sql:%s' tokenDescription='%s'",
780*635a8641SAndroid Build Coastguard Worker path.value().c_str(),
781*635a8641SAndroid Build Coastguard Worker description.c_str());
782*635a8641SAndroid Build Coastguard Worker PK11SlotInfo* db_slot = SECMOD_OpenUserDB(modspec.c_str());
783*635a8641SAndroid Build Coastguard Worker if (db_slot) {
784*635a8641SAndroid Build Coastguard Worker if (PK11_NeedUserInit(db_slot))
785*635a8641SAndroid Build Coastguard Worker PK11_InitPin(db_slot, nullptr, nullptr);
786*635a8641SAndroid Build Coastguard Worker } else {
787*635a8641SAndroid Build Coastguard Worker LOG(ERROR) << "Error opening persistent database (" << modspec
788*635a8641SAndroid Build Coastguard Worker << "): " << GetNSSErrorMessage();
789*635a8641SAndroid Build Coastguard Worker }
790*635a8641SAndroid Build Coastguard Worker return ScopedPK11Slot(db_slot);
791*635a8641SAndroid Build Coastguard Worker }
792*635a8641SAndroid Build Coastguard Worker
EnsureNSPRInit()793*635a8641SAndroid Build Coastguard Worker void EnsureNSPRInit() {
794*635a8641SAndroid Build Coastguard Worker g_nspr_singleton.Get();
795*635a8641SAndroid Build Coastguard Worker }
796*635a8641SAndroid Build Coastguard Worker
EnsureNSSInit()797*635a8641SAndroid Build Coastguard Worker void EnsureNSSInit() {
798*635a8641SAndroid Build Coastguard Worker g_nss_singleton.Get();
799*635a8641SAndroid Build Coastguard Worker }
800*635a8641SAndroid Build Coastguard Worker
CheckNSSVersion(const char * version)801*635a8641SAndroid Build Coastguard Worker bool CheckNSSVersion(const char* version) {
802*635a8641SAndroid Build Coastguard Worker return !!NSS_VersionCheck(version);
803*635a8641SAndroid Build Coastguard Worker }
804*635a8641SAndroid Build Coastguard Worker
AutoSECMODListReadLock()805*635a8641SAndroid Build Coastguard Worker AutoSECMODListReadLock::AutoSECMODListReadLock()
806*635a8641SAndroid Build Coastguard Worker : lock_(SECMOD_GetDefaultModuleListLock()) {
807*635a8641SAndroid Build Coastguard Worker SECMOD_GetReadLock(lock_);
808*635a8641SAndroid Build Coastguard Worker }
809*635a8641SAndroid Build Coastguard Worker
~AutoSECMODListReadLock()810*635a8641SAndroid Build Coastguard Worker AutoSECMODListReadLock::~AutoSECMODListReadLock() {
811*635a8641SAndroid Build Coastguard Worker SECMOD_ReleaseReadLock(lock_);
812*635a8641SAndroid Build Coastguard Worker }
813*635a8641SAndroid Build Coastguard Worker
814*635a8641SAndroid Build Coastguard Worker #if defined(OS_CHROMEOS)
GetSystemNSSKeySlot(base::OnceCallback<void (ScopedPK11Slot)> callback)815*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot GetSystemNSSKeySlot(
816*635a8641SAndroid Build Coastguard Worker base::OnceCallback<void(ScopedPK11Slot)> callback) {
817*635a8641SAndroid Build Coastguard Worker return g_nss_singleton.Get().GetSystemNSSKeySlot(std::move(callback));
818*635a8641SAndroid Build Coastguard Worker }
819*635a8641SAndroid Build Coastguard Worker
SetSystemKeySlotForTesting(ScopedPK11Slot slot)820*635a8641SAndroid Build Coastguard Worker void SetSystemKeySlotForTesting(ScopedPK11Slot slot) {
821*635a8641SAndroid Build Coastguard Worker g_nss_singleton.Get().SetSystemKeySlotForTesting(std::move(slot));
822*635a8641SAndroid Build Coastguard Worker }
823*635a8641SAndroid Build Coastguard Worker
EnableTPMTokenForNSS()824*635a8641SAndroid Build Coastguard Worker void EnableTPMTokenForNSS() {
825*635a8641SAndroid Build Coastguard Worker g_nss_singleton.Get().EnableTPMTokenForNSS();
826*635a8641SAndroid Build Coastguard Worker }
827*635a8641SAndroid Build Coastguard Worker
IsTPMTokenEnabledForNSS()828*635a8641SAndroid Build Coastguard Worker bool IsTPMTokenEnabledForNSS() {
829*635a8641SAndroid Build Coastguard Worker return g_nss_singleton.Get().IsTPMTokenEnabledForNSS();
830*635a8641SAndroid Build Coastguard Worker }
831*635a8641SAndroid Build Coastguard Worker
IsTPMTokenReady(base::OnceClosure callback)832*635a8641SAndroid Build Coastguard Worker bool IsTPMTokenReady(base::OnceClosure callback) {
833*635a8641SAndroid Build Coastguard Worker return g_nss_singleton.Get().IsTPMTokenReady(std::move(callback));
834*635a8641SAndroid Build Coastguard Worker }
835*635a8641SAndroid Build Coastguard Worker
InitializeTPMTokenAndSystemSlot(int token_slot_id,base::OnceCallback<void (bool)> callback)836*635a8641SAndroid Build Coastguard Worker void InitializeTPMTokenAndSystemSlot(int token_slot_id,
837*635a8641SAndroid Build Coastguard Worker base::OnceCallback<void(bool)> callback) {
838*635a8641SAndroid Build Coastguard Worker g_nss_singleton.Get().InitializeTPMTokenAndSystemSlot(token_slot_id,
839*635a8641SAndroid Build Coastguard Worker std::move(callback));
840*635a8641SAndroid Build Coastguard Worker }
841*635a8641SAndroid Build Coastguard Worker
InitializeNSSForChromeOSUser(const std::string & username_hash,const base::FilePath & path)842*635a8641SAndroid Build Coastguard Worker bool InitializeNSSForChromeOSUser(const std::string& username_hash,
843*635a8641SAndroid Build Coastguard Worker const base::FilePath& path) {
844*635a8641SAndroid Build Coastguard Worker return g_nss_singleton.Get().InitializeNSSForChromeOSUser(username_hash,
845*635a8641SAndroid Build Coastguard Worker path);
846*635a8641SAndroid Build Coastguard Worker }
847*635a8641SAndroid Build Coastguard Worker
ShouldInitializeTPMForChromeOSUser(const std::string & username_hash)848*635a8641SAndroid Build Coastguard Worker bool ShouldInitializeTPMForChromeOSUser(const std::string& username_hash) {
849*635a8641SAndroid Build Coastguard Worker return g_nss_singleton.Get().ShouldInitializeTPMForChromeOSUser(
850*635a8641SAndroid Build Coastguard Worker username_hash);
851*635a8641SAndroid Build Coastguard Worker }
852*635a8641SAndroid Build Coastguard Worker
WillInitializeTPMForChromeOSUser(const std::string & username_hash)853*635a8641SAndroid Build Coastguard Worker void WillInitializeTPMForChromeOSUser(const std::string& username_hash) {
854*635a8641SAndroid Build Coastguard Worker g_nss_singleton.Get().WillInitializeTPMForChromeOSUser(username_hash);
855*635a8641SAndroid Build Coastguard Worker }
856*635a8641SAndroid Build Coastguard Worker
InitializeTPMForChromeOSUser(const std::string & username_hash,CK_SLOT_ID slot_id)857*635a8641SAndroid Build Coastguard Worker void InitializeTPMForChromeOSUser(
858*635a8641SAndroid Build Coastguard Worker const std::string& username_hash,
859*635a8641SAndroid Build Coastguard Worker CK_SLOT_ID slot_id) {
860*635a8641SAndroid Build Coastguard Worker g_nss_singleton.Get().InitializeTPMForChromeOSUser(username_hash, slot_id);
861*635a8641SAndroid Build Coastguard Worker }
862*635a8641SAndroid Build Coastguard Worker
InitializePrivateSoftwareSlotForChromeOSUser(const std::string & username_hash)863*635a8641SAndroid Build Coastguard Worker void InitializePrivateSoftwareSlotForChromeOSUser(
864*635a8641SAndroid Build Coastguard Worker const std::string& username_hash) {
865*635a8641SAndroid Build Coastguard Worker g_nss_singleton.Get().InitializePrivateSoftwareSlotForChromeOSUser(
866*635a8641SAndroid Build Coastguard Worker username_hash);
867*635a8641SAndroid Build Coastguard Worker }
868*635a8641SAndroid Build Coastguard Worker
GetPublicSlotForChromeOSUser(const std::string & username_hash)869*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot GetPublicSlotForChromeOSUser(const std::string& username_hash) {
870*635a8641SAndroid Build Coastguard Worker return g_nss_singleton.Get().GetPublicSlotForChromeOSUser(username_hash);
871*635a8641SAndroid Build Coastguard Worker }
872*635a8641SAndroid Build Coastguard Worker
GetPrivateSlotForChromeOSUser(const std::string & username_hash,base::OnceCallback<void (ScopedPK11Slot)> callback)873*635a8641SAndroid Build Coastguard Worker ScopedPK11Slot GetPrivateSlotForChromeOSUser(
874*635a8641SAndroid Build Coastguard Worker const std::string& username_hash,
875*635a8641SAndroid Build Coastguard Worker base::OnceCallback<void(ScopedPK11Slot)> callback) {
876*635a8641SAndroid Build Coastguard Worker return g_nss_singleton.Get().GetPrivateSlotForChromeOSUser(
877*635a8641SAndroid Build Coastguard Worker username_hash, std::move(callback));
878*635a8641SAndroid Build Coastguard Worker }
879*635a8641SAndroid Build Coastguard Worker
CloseChromeOSUserForTesting(const std::string & username_hash)880*635a8641SAndroid Build Coastguard Worker void CloseChromeOSUserForTesting(const std::string& username_hash) {
881*635a8641SAndroid Build Coastguard Worker g_nss_singleton.Get().CloseChromeOSUserForTesting(username_hash);
882*635a8641SAndroid Build Coastguard Worker }
883*635a8641SAndroid Build Coastguard Worker
SetPrivateSoftwareSlotForChromeOSUserForTesting(ScopedPK11Slot slot)884*635a8641SAndroid Build Coastguard Worker void SetPrivateSoftwareSlotForChromeOSUserForTesting(ScopedPK11Slot slot) {
885*635a8641SAndroid Build Coastguard Worker g_nss_singleton.Get().SetPrivateSoftwareSlotForChromeOSUserForTesting(
886*635a8641SAndroid Build Coastguard Worker std::move(slot));
887*635a8641SAndroid Build Coastguard Worker }
888*635a8641SAndroid Build Coastguard Worker #endif // defined(OS_CHROMEOS)
889*635a8641SAndroid Build Coastguard Worker
PRTimeToBaseTime(PRTime prtime)890*635a8641SAndroid Build Coastguard Worker base::Time PRTimeToBaseTime(PRTime prtime) {
891*635a8641SAndroid Build Coastguard Worker return base::Time::FromInternalValue(
892*635a8641SAndroid Build Coastguard Worker prtime + base::Time::UnixEpoch().ToInternalValue());
893*635a8641SAndroid Build Coastguard Worker }
894*635a8641SAndroid Build Coastguard Worker
BaseTimeToPRTime(base::Time time)895*635a8641SAndroid Build Coastguard Worker PRTime BaseTimeToPRTime(base::Time time) {
896*635a8641SAndroid Build Coastguard Worker return time.ToInternalValue() - base::Time::UnixEpoch().ToInternalValue();
897*635a8641SAndroid Build Coastguard Worker }
898*635a8641SAndroid Build Coastguard Worker
899*635a8641SAndroid Build Coastguard Worker #if !defined(OS_CHROMEOS)
GetPersistentNSSKeySlot()900*635a8641SAndroid Build Coastguard Worker PK11SlotInfo* GetPersistentNSSKeySlot() {
901*635a8641SAndroid Build Coastguard Worker return g_nss_singleton.Get().GetPersistentNSSKeySlot();
902*635a8641SAndroid Build Coastguard Worker }
903*635a8641SAndroid Build Coastguard Worker #endif
904*635a8641SAndroid Build Coastguard Worker
905*635a8641SAndroid Build Coastguard Worker } // namespace crypto
906