1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/cros/cryptohome_library.h"
6
7 #include "base/command_line.h"
8 #include "base/hash_tables.h"
9 #include "base/message_loop.h"
10 #include "chrome/browser/chromeos/cros/cros_library.h"
11 #include "chrome/common/chrome_switches.h"
12 #include "content/browser/browser_thread.h"
13
14 namespace chromeos {
15
16 // This class handles the interaction with the ChromeOS cryptohome library APIs.
17 class CryptohomeLibraryImpl : public CryptohomeLibrary {
18 public:
CryptohomeLibraryImpl()19 CryptohomeLibraryImpl() {
20 if (CrosLibrary::Get()->EnsureLoaded())
21 Init();
22 }
~CryptohomeLibraryImpl()23 virtual ~CryptohomeLibraryImpl() {}
24
CheckKey(const std::string & user_email,const std::string & passhash)25 bool CheckKey(const std::string& user_email, const std::string& passhash) {
26 return chromeos::CryptohomeCheckKey(user_email.c_str(), passhash.c_str());
27 }
28
AsyncCheckKey(const std::string & user_email,const std::string & passhash,Delegate * d)29 bool AsyncCheckKey(const std::string& user_email,
30 const std::string& passhash,
31 Delegate* d) {
32 return CacheCallback(
33 chromeos::CryptohomeAsyncCheckKey(user_email.c_str(), passhash.c_str()),
34 d,
35 "Couldn't initiate async check of user's key.");
36 }
37
MigrateKey(const std::string & user_email,const std::string & old_hash,const std::string & new_hash)38 bool MigrateKey(const std::string& user_email,
39 const std::string& old_hash,
40 const std::string& new_hash) {
41 return chromeos::CryptohomeMigrateKey(user_email.c_str(),
42 old_hash.c_str(),
43 new_hash.c_str());
44 }
45
AsyncMigrateKey(const std::string & user_email,const std::string & old_hash,const std::string & new_hash,Delegate * d)46 bool AsyncMigrateKey(const std::string& user_email,
47 const std::string& old_hash,
48 const std::string& new_hash,
49 Delegate* d) {
50 return CacheCallback(
51 chromeos::CryptohomeAsyncMigrateKey(user_email.c_str(),
52 old_hash.c_str(),
53 new_hash.c_str()),
54 d,
55 "Couldn't initiate aync migration of user's key");
56 }
57
Mount(const std::string & user_email,const std::string & passhash,int * error_code)58 bool Mount(const std::string& user_email,
59 const std::string& passhash,
60 int* error_code) {
61 return chromeos::CryptohomeMountAllowFail(user_email.c_str(),
62 passhash.c_str(),
63 error_code);
64 }
65
AsyncMount(const std::string & user_email,const std::string & passhash,const bool create_if_missing,Delegate * d)66 bool AsyncMount(const std::string& user_email,
67 const std::string& passhash,
68 const bool create_if_missing,
69 Delegate* d) {
70 return CacheCallback(
71 chromeos::CryptohomeAsyncMountSafe(user_email.c_str(),
72 passhash.c_str(),
73 create_if_missing,
74 false,
75 NULL),
76 d,
77 "Couldn't initiate async mount of cryptohome.");
78 }
79
MountForBwsi(int * error_code)80 bool MountForBwsi(int* error_code) {
81 return chromeos::CryptohomeMountGuest(error_code);
82 }
83
AsyncMountForBwsi(Delegate * d)84 bool AsyncMountForBwsi(Delegate* d) {
85 return CacheCallback(chromeos::CryptohomeAsyncMountGuest(),
86 d,
87 "Couldn't initiate async mount of cryptohome.");
88 }
89
Unmount()90 bool Unmount() {
91 return chromeos::CryptohomeUnmount();
92 }
93
Remove(const std::string & user_email)94 bool Remove(const std::string& user_email) {
95 return chromeos::CryptohomeRemove(user_email.c_str());
96 }
97
AsyncRemove(const std::string & user_email,Delegate * d)98 bool AsyncRemove(const std::string& user_email, Delegate* d) {
99 return CacheCallback(
100 chromeos::CryptohomeAsyncRemove(user_email.c_str()),
101 d,
102 "Couldn't initiate async removal of cryptohome.");
103 }
104
IsMounted()105 bool IsMounted() {
106 return chromeos::CryptohomeIsMounted();
107 }
108
GetSystemSalt()109 CryptohomeBlob GetSystemSalt() {
110 CryptohomeBlob system_salt;
111 char* salt_buf;
112 int salt_len;
113 bool result = chromeos::CryptohomeGetSystemSaltSafe(&salt_buf, &salt_len);
114 if (result) {
115 system_salt.resize(salt_len);
116 if ((int)system_salt.size() == salt_len) {
117 memcpy(&system_salt[0], static_cast<const void*>(salt_buf),
118 salt_len);
119 } else {
120 system_salt.clear();
121 }
122 }
123 return system_salt;
124 }
125
AsyncDoAutomaticFreeDiskSpaceControl(Delegate * d)126 bool AsyncDoAutomaticFreeDiskSpaceControl(Delegate* d) {
127 return CacheCallback(
128 chromeos::CryptohomeAsyncDoAutomaticFreeDiskSpaceControl(),
129 d,
130 "Couldn't do automatic free disk space control.");
131 }
132
TpmIsReady()133 bool TpmIsReady() {
134 return chromeos::CryptohomeTpmIsReady();
135 }
136
TpmIsEnabled()137 bool TpmIsEnabled() {
138 return chromeos::CryptohomeTpmIsEnabled();
139 }
140
TpmIsOwned()141 bool TpmIsOwned() {
142 return chromeos::CryptohomeTpmIsOwned();
143 }
144
TpmIsBeingOwned()145 bool TpmIsBeingOwned() {
146 return chromeos::CryptohomeTpmIsBeingOwned();
147 }
148
TpmGetPassword(std::string * password)149 bool TpmGetPassword(std::string* password) {
150 char *password_buf;
151 bool result = chromeos::CryptohomeTpmGetPasswordSafe(&password_buf);
152 *password = password_buf;
153 chromeos::CryptohomeFreeString(password_buf);
154 return result;
155 }
156
TpmCanAttemptOwnership()157 void TpmCanAttemptOwnership() {
158 chromeos::CryptohomeTpmCanAttemptOwnership();
159 }
160
TpmClearStoredPassword()161 void TpmClearStoredPassword() {
162 chromeos::CryptohomeTpmClearStoredPassword();
163 }
164
InstallAttributesGet(const std::string & name,std::string * value)165 bool InstallAttributesGet(const std::string& name, std::string* value) {
166 char* local_value;
167 bool done =
168 chromeos::CryptohomeInstallAttributesGet(name.c_str(), &local_value);
169 if (done) {
170 *value = local_value;
171 chromeos::CryptohomeFreeString(local_value);
172 }
173 return done;
174 }
175
InstallAttributesSet(const std::string & name,const std::string & value)176 bool InstallAttributesSet(const std::string& name, const std::string& value) {
177 return chromeos::CryptohomeInstallAttributesSet(name.c_str(),
178 value.c_str());
179 }
180
InstallAttributesCount()181 int InstallAttributesCount() {
182 return chromeos::CryptohomeInstallAttributesCount();
183 }
184
InstallAttributesFinalize()185 bool InstallAttributesFinalize() {
186 return chromeos::CryptohomeInstallAttributesFinalize();
187 }
188
InstallAttributesIsReady()189 bool InstallAttributesIsReady() {
190 return chromeos::CryptohomeInstallAttributesIsReady();
191 }
192
InstallAttributesIsSecure()193 bool InstallAttributesIsSecure() {
194 return chromeos::CryptohomeInstallAttributesIsSecure();
195 }
196
InstallAttributesIsInvalid()197 bool InstallAttributesIsInvalid() {
198 return chromeos::CryptohomeInstallAttributesIsInvalid();
199 }
200
InstallAttributesIsFirstInstall()201 bool InstallAttributesIsFirstInstall() {
202 return chromeos::CryptohomeInstallAttributesIsFirstInstall();
203 }
204
Pkcs11GetTpmTokenInfo(std::string * label,std::string * user_pin)205 void Pkcs11GetTpmTokenInfo(std::string* label, std::string* user_pin) {
206 chromeos::CryptohomePkcs11GetTpmTokenInfo(label, user_pin);
207 }
208
Pkcs11IsTpmTokenReady()209 bool Pkcs11IsTpmTokenReady() {
210 return chromeos::CryptohomePkcs11IsTpmTokenReady();
211 }
212
213 private:
Handler(const chromeos::CryptohomeAsyncCallStatus & event,void * cryptohome_library)214 static void Handler(const chromeos::CryptohomeAsyncCallStatus& event,
215 void* cryptohome_library) {
216 CryptohomeLibraryImpl* library =
217 reinterpret_cast<CryptohomeLibraryImpl*>(cryptohome_library);
218 library->Dispatch(event);
219 }
220
Init()221 void Init() {
222 cryptohome_connection_ = chromeos::CryptohomeMonitorSession(&Handler, this);
223 }
224
Dispatch(const chromeos::CryptohomeAsyncCallStatus & event)225 void Dispatch(const chromeos::CryptohomeAsyncCallStatus& event) {
226 const CallbackMap::iterator callback = callback_map_.find(event.async_id);
227 if (callback == callback_map_.end()) {
228 LOG(ERROR) << "Received signal for unknown async_id " << event.async_id;
229 return;
230 }
231 if (callback->second)
232 callback->second->OnComplete(event.return_status, event.return_code);
233 callback_map_.erase(callback);
234 }
235
CacheCallback(int async_id,Delegate * d,const char * error)236 bool CacheCallback(int async_id, Delegate* d, const char* error) {
237 if (async_id == 0) {
238 LOG(ERROR) << error;
239 return false;
240 }
241 VLOG(1) << "Adding handler for " << async_id;
242 callback_map_[async_id] = d;
243 return true;
244 }
245
246 typedef base::hash_map<int, Delegate*> CallbackMap;
247 mutable CallbackMap callback_map_;
248
249 void* cryptohome_connection_;
250
251 DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryImpl);
252 };
253
254 class CryptohomeLibraryStubImpl : public CryptohomeLibrary {
255 public:
CryptohomeLibraryStubImpl()256 CryptohomeLibraryStubImpl()
257 : locked_(false) {}
~CryptohomeLibraryStubImpl()258 virtual ~CryptohomeLibraryStubImpl() {}
259
CheckKey(const std::string & user_email,const std::string & passhash)260 bool CheckKey(const std::string& user_email, const std::string& passhash) {
261 return true;
262 }
263
AsyncCheckKey(const std::string & user_email,const std::string & passhash,Delegate * callback)264 bool AsyncCheckKey(const std::string& user_email,
265 const std::string& passhash,
266 Delegate* callback) {
267 BrowserThread::PostTask(
268 BrowserThread::UI, FROM_HERE,
269 NewRunnableFunction(&DoStubCallback, callback));
270 return true;
271 }
272
MigrateKey(const std::string & user_email,const std::string & old_hash,const std::string & new_hash)273 bool MigrateKey(const std::string& user_email,
274 const std::string& old_hash,
275 const std::string& new_hash) {
276 return true;
277 }
278
AsyncMigrateKey(const std::string & user_email,const std::string & old_hash,const std::string & new_hash,Delegate * callback)279 bool AsyncMigrateKey(const std::string& user_email,
280 const std::string& old_hash,
281 const std::string& new_hash,
282 Delegate* callback) {
283 BrowserThread::PostTask(
284 BrowserThread::UI, FROM_HERE,
285 NewRunnableFunction(&DoStubCallback, callback));
286 return true;
287 }
288
Mount(const std::string & user_email,const std::string & passhash,int * error_code)289 bool Mount(const std::string& user_email,
290 const std::string& passhash,
291 int* error_code) {
292 // For testing password change.
293 if (user_email ==
294 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
295 switches::kLoginUserWithNewPassword)) {
296 *error_code = kCryptohomeMountErrorKeyFailure;
297 return false;
298 }
299
300 return true;
301 }
302
AsyncMount(const std::string & user_email,const std::string & passhash,const bool create_if_missing,Delegate * callback)303 bool AsyncMount(const std::string& user_email,
304 const std::string& passhash,
305 const bool create_if_missing,
306 Delegate* callback) {
307 BrowserThread::PostTask(
308 BrowserThread::UI, FROM_HERE,
309 NewRunnableFunction(&DoStubCallback, callback));
310 return true;
311 }
312
MountForBwsi(int * error_code)313 bool MountForBwsi(int* error_code) {
314 return true;
315 }
316
AsyncMountForBwsi(Delegate * callback)317 bool AsyncMountForBwsi(Delegate* callback) {
318 BrowserThread::PostTask(
319 BrowserThread::UI, FROM_HERE,
320 NewRunnableFunction(&DoStubCallback, callback));
321 return true;
322 }
323
Unmount()324 bool Unmount() {
325 return true;
326 }
327
Remove(const std::string & user_email)328 bool Remove(const std::string& user_email) {
329 return true;
330 }
331
AsyncRemove(const std::string & user_email,Delegate * callback)332 bool AsyncRemove(const std::string& user_email, Delegate* callback) {
333 BrowserThread::PostTask(
334 BrowserThread::UI, FROM_HERE,
335 NewRunnableFunction(&DoStubCallback, callback));
336 return true;
337 }
338
IsMounted()339 bool IsMounted() {
340 return true;
341 }
342
GetSystemSalt()343 CryptohomeBlob GetSystemSalt() {
344 CryptohomeBlob salt = CryptohomeBlob();
345 salt.push_back(0);
346 salt.push_back(0);
347 return salt;
348 }
349
AsyncDoAutomaticFreeDiskSpaceControl(Delegate * callback)350 bool AsyncDoAutomaticFreeDiskSpaceControl(Delegate* callback) {
351 BrowserThread::PostTask(
352 BrowserThread::UI, FROM_HERE,
353 NewRunnableFunction(&DoStubCallback, callback));
354 return true;
355 }
356
357 // Tpm begin ready after 20-th call.
TpmIsReady()358 bool TpmIsReady() {
359 static int counter = 0;
360 return ++counter > 20;
361 }
362
TpmIsEnabled()363 bool TpmIsEnabled() {
364 return true;
365 }
366
TpmIsOwned()367 bool TpmIsOwned() {
368 return true;
369 }
370
TpmIsBeingOwned()371 bool TpmIsBeingOwned() {
372 return true;
373 }
374
TpmGetPassword(std::string * password)375 bool TpmGetPassword(std::string* password) {
376 *password = "Stub-TPM-password";
377 return true;
378 }
379
TpmCanAttemptOwnership()380 void TpmCanAttemptOwnership() {}
381
TpmClearStoredPassword()382 void TpmClearStoredPassword() {}
383
InstallAttributesGet(const std::string & name,std::string * value)384 bool InstallAttributesGet(const std::string& name, std::string* value) {
385 if (install_attrs_.find(name) != install_attrs_.end()) {
386 *value = install_attrs_[name];
387 return true;
388 }
389 return false;
390 }
391
InstallAttributesSet(const std::string & name,const std::string & value)392 bool InstallAttributesSet(const std::string& name, const std::string& value) {
393 install_attrs_[name] = value;
394 return true;
395 }
396
InstallAttributesCount()397 int InstallAttributesCount() {
398 return install_attrs_.size();
399 }
400
InstallAttributesFinalize()401 bool InstallAttributesFinalize() {
402 locked_ = true;
403 return true;
404 }
405
InstallAttributesIsReady()406 bool InstallAttributesIsReady() {
407 return true;
408 }
409
InstallAttributesIsSecure()410 bool InstallAttributesIsSecure() {
411 return false;
412 }
413
InstallAttributesIsInvalid()414 bool InstallAttributesIsInvalid() {
415 return false;
416 }
417
InstallAttributesIsFirstInstall()418 bool InstallAttributesIsFirstInstall() {
419 return !locked_;
420 }
421
Pkcs11GetTpmTokenInfo(std::string * label,std::string * user_pin)422 void Pkcs11GetTpmTokenInfo(std::string* label,
423 std::string* user_pin) {
424 *label = "Stub TPM Token";
425 *user_pin = "012345";
426 }
427
Pkcs11IsTpmTokenReady()428 bool Pkcs11IsTpmTokenReady() { return true; }
429
430 private:
DoStubCallback(Delegate * callback)431 static void DoStubCallback(Delegate* callback) {
432 if (callback)
433 callback->OnComplete(true, kCryptohomeMountErrorNone);
434 }
435
436 std::map<std::string, std::string> install_attrs_;
437 bool locked_;
438 DISALLOW_COPY_AND_ASSIGN(CryptohomeLibraryStubImpl);
439 };
440
CryptohomeLibrary()441 CryptohomeLibrary::CryptohomeLibrary() {}
~CryptohomeLibrary()442 CryptohomeLibrary::~CryptohomeLibrary() {}
443
444 // static
GetImpl(bool stub)445 CryptohomeLibrary* CryptohomeLibrary::GetImpl(bool stub) {
446 if (stub)
447 return new CryptohomeLibraryStubImpl();
448 else
449 return new CryptohomeLibraryImpl();
450 }
451
452 } // namespace chromeos
453