Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chromeos / dbus / fake_cryptohome_client.cc
1 // Copyright 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 "chromeos/dbus/fake_cryptohome_client.h"
6
7 #include "base/bind.h"
8 #include "base/file_util.h"
9 #include "base/location.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/path_service.h"
12 #include "base/threading/worker_pool.h"
13 #include "chromeos/chromeos_paths.h"
14 #include "chromeos/dbus/cryptohome/key.pb.h"
15 #include "chromeos/dbus/cryptohome/rpc.pb.h"
16 #include "crypto/nss_util.h"
17 #include "third_party/cros_system_api/dbus/service_constants.h"
18 #include "third_party/protobuf/src/google/protobuf/io/coded_stream.h"
19 #include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream.h"
20 #include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl_lite.h"
21
22 namespace {
23
24 // Helper to asynchronously write a file in the WorkerPool.
25 void PersistFile(const base::FilePath& path, const std::string& content) {
26   base::WriteFile(path, content.data(), content.size());
27 }
28
29 }  // namespace
30
31 namespace chromeos {
32
33 FakeCryptohomeClient::FakeCryptohomeClient()
34     : service_is_available_(true),
35       async_call_id_(1),
36       tpm_is_ready_counter_(0),
37       unmount_result_(true),
38       system_salt_(GetStubSystemSalt()),
39       weak_ptr_factory_(this) {
40   base::FilePath cache_path;
41   locked_ = PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES, &cache_path) &&
42             base::PathExists(cache_path);
43 }
44
45 FakeCryptohomeClient::~FakeCryptohomeClient() {}
46
47 void FakeCryptohomeClient::Init(dbus::Bus* bus) {
48 }
49
50 void FakeCryptohomeClient::SetAsyncCallStatusHandlers(
51     const AsyncCallStatusHandler& handler,
52     const AsyncCallStatusWithDataHandler& data_handler) {
53   async_call_status_handler_ = handler;
54   async_call_status_data_handler_ = data_handler;
55 }
56
57 void FakeCryptohomeClient::ResetAsyncCallStatusHandlers() {
58   async_call_status_handler_.Reset();
59   async_call_status_data_handler_.Reset();
60 }
61
62 void FakeCryptohomeClient::WaitForServiceToBeAvailable(
63     const WaitForServiceToBeAvailableCallback& callback) {
64   if (service_is_available_) {
65     base::MessageLoop::current()->PostTask(FROM_HERE,
66                                            base::Bind(callback, true));
67   } else {
68     pending_wait_for_service_to_be_available_callbacks_.push_back(callback);
69   }
70 }
71
72 void FakeCryptohomeClient::IsMounted(
73     const BoolDBusMethodCallback& callback) {
74   base::MessageLoop::current()->PostTask(
75       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
76 }
77
78 bool FakeCryptohomeClient::Unmount(bool* success) {
79   *success = unmount_result_;
80   return true;
81 }
82
83 void FakeCryptohomeClient::AsyncCheckKey(
84     const std::string& username,
85     const std::string& key,
86     const AsyncMethodCallback& callback) {
87   ReturnAsyncMethodResult(callback, false);
88 }
89
90 void FakeCryptohomeClient::AsyncMigrateKey(
91     const std::string& username,
92     const std::string& from_key,
93     const std::string& to_key,
94     const AsyncMethodCallback& callback) {
95   ReturnAsyncMethodResult(callback, false);
96 }
97
98 void FakeCryptohomeClient::AsyncRemove(
99     const std::string& username,
100     const AsyncMethodCallback& callback) {
101   ReturnAsyncMethodResult(callback, false);
102 }
103
104 void FakeCryptohomeClient::GetSystemSalt(
105     const GetSystemSaltCallback& callback) {
106   base::MessageLoop::current()->PostTask(
107       FROM_HERE,
108       base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, system_salt_));
109 }
110
111 void FakeCryptohomeClient::GetSanitizedUsername(
112     const std::string& username,
113     const StringDBusMethodCallback& callback) {
114   // Even for stub implementation we have to return different values so that
115   // multi-profiles would work.
116   std::string sanitized_username = GetStubSanitizedUsername(username);
117   base::MessageLoop::current()->PostTask(
118       FROM_HERE,
119       base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, sanitized_username));
120 }
121
122 std::string FakeCryptohomeClient::BlockingGetSanitizedUsername(
123     const std::string& username) {
124   return GetStubSanitizedUsername(username);
125 }
126
127 void FakeCryptohomeClient::AsyncMount(const std::string& username,
128                                           const std::string& key,
129                                           int flags,
130                                           const AsyncMethodCallback& callback) {
131   ReturnAsyncMethodResult(callback, false);
132 }
133
134 void FakeCryptohomeClient::AsyncAddKey(
135     const std::string& username,
136     const std::string& key,
137     const std::string& new_key,
138     const AsyncMethodCallback& callback) {
139   ReturnAsyncMethodResult(callback, false);
140 }
141
142 void FakeCryptohomeClient::AsyncMountGuest(
143     const AsyncMethodCallback& callback) {
144   ReturnAsyncMethodResult(callback, false);
145 }
146
147 void FakeCryptohomeClient::AsyncMountPublic(
148     const std::string& public_mount_id,
149     int flags,
150     const AsyncMethodCallback& callback) {
151   ReturnAsyncMethodResult(callback, false);
152 }
153
154 void FakeCryptohomeClient::TpmIsReady(
155     const BoolDBusMethodCallback& callback) {
156   base::MessageLoop::current()->PostTask(
157       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
158 }
159
160 void FakeCryptohomeClient::TpmIsEnabled(
161     const BoolDBusMethodCallback& callback) {
162   base::MessageLoop::current()->PostTask(
163       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
164 }
165
166 bool FakeCryptohomeClient::CallTpmIsEnabledAndBlock(bool* enabled) {
167   *enabled = true;
168   return true;
169 }
170
171 void FakeCryptohomeClient::TpmGetPassword(
172     const StringDBusMethodCallback& callback) {
173   const char kStubTpmPassword[] = "Stub-TPM-password";
174   base::MessageLoop::current()->PostTask(
175       FROM_HERE,
176       base::Bind(callback, DBUS_METHOD_CALL_SUCCESS,
177                  std::string(kStubTpmPassword)));
178 }
179
180 void FakeCryptohomeClient::TpmIsOwned(
181     const BoolDBusMethodCallback& callback) {
182   base::MessageLoop::current()->PostTask(
183       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
184 }
185
186 bool FakeCryptohomeClient::CallTpmIsOwnedAndBlock(bool* owned) {
187   *owned = true;
188   return true;
189 }
190
191 void FakeCryptohomeClient::TpmIsBeingOwned(
192     const BoolDBusMethodCallback& callback) {
193   base::MessageLoop::current()->PostTask(
194       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
195 }
196
197 bool FakeCryptohomeClient::CallTpmIsBeingOwnedAndBlock(bool* owning) {
198   *owning = true;
199   return true;
200 }
201
202 void FakeCryptohomeClient::TpmCanAttemptOwnership(
203     const VoidDBusMethodCallback& callback) {
204   base::MessageLoop::current()->PostTask(
205       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS));
206 }
207
208 void FakeCryptohomeClient::TpmClearStoredPassword(
209     const VoidDBusMethodCallback& callback) {
210   base::MessageLoop::current()->PostTask(
211       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS));
212 }
213
214 bool FakeCryptohomeClient::CallTpmClearStoredPasswordAndBlock() {
215   return true;
216 }
217
218 void FakeCryptohomeClient::Pkcs11IsTpmTokenReady(
219     const BoolDBusMethodCallback& callback) {
220   base::MessageLoop::current()->PostTask(
221       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
222 }
223
224 void FakeCryptohomeClient::Pkcs11GetTpmTokenInfo(
225     const Pkcs11GetTpmTokenInfoCallback& callback) {
226   const char kStubUserPin[] = "012345";
227   const int kStubSlot = 0;
228   base::MessageLoop::current()->PostTask(
229       FROM_HERE,
230       base::Bind(callback,
231                  DBUS_METHOD_CALL_SUCCESS,
232                  std::string(crypto::kTestTPMTokenName),
233                  std::string(kStubUserPin),
234                  kStubSlot));
235 }
236
237 void FakeCryptohomeClient::Pkcs11GetTpmTokenInfoForUser(
238     const std::string& username,
239     const Pkcs11GetTpmTokenInfoCallback& callback) {
240   Pkcs11GetTpmTokenInfo(callback);
241 }
242
243 bool FakeCryptohomeClient::InstallAttributesGet(const std::string& name,
244                                                     std::vector<uint8>* value,
245                                                     bool* successful) {
246   if (install_attrs_.find(name) != install_attrs_.end()) {
247     *value = install_attrs_[name];
248     *successful = true;
249   } else {
250     value->clear();
251     *successful = false;
252   }
253   return true;
254 }
255
256 bool FakeCryptohomeClient::InstallAttributesSet(
257     const std::string& name,
258     const std::vector<uint8>& value,
259     bool* successful) {
260   install_attrs_[name] = value;
261   *successful = true;
262   return true;
263 }
264
265 bool FakeCryptohomeClient::InstallAttributesFinalize(bool* successful) {
266   locked_ = true;
267   *successful = true;
268
269   // Persist the install attributes so that they can be reloaded if the
270   // browser is restarted. This is used for ease of development when device
271   // enrollment is required.
272   // The cryptohome::SerializedInstallAttributes protobuf lives in
273   // chrome/browser/chromeos, so it can't be used directly here; use the
274   // low-level protobuf API instead to just write the name-value pairs.
275   // The cache file is read by EnterpriseInstallAttributes::ReadCacheFile.
276   base::FilePath cache_path;
277   if (!PathService::Get(chromeos::FILE_INSTALL_ATTRIBUTES, &cache_path))
278     return false;
279
280   std::string result;
281   {
282     // |result| can be used only after the StringOutputStream goes out of
283     // scope.
284     google::protobuf::io::StringOutputStream result_stream(&result);
285     google::protobuf::io::CodedOutputStream result_output(&result_stream);
286
287     // These tags encode a variable-length value on the wire, which can be
288     // used to encode strings, bytes and messages. We only needs constants
289     // for tag numbers 1 and 2 (see install_attributes.proto).
290     const int kVarLengthTag1 = (1 << 3) | 0x2;
291     const int kVarLengthTag2 = (2 << 3) | 0x2;
292
293     typedef std::map<std::string, std::vector<uint8> >::const_iterator Iter;
294     for (Iter it = install_attrs_.begin(); it != install_attrs_.end(); ++it) {
295       std::string attr;
296       {
297         google::protobuf::io::StringOutputStream attr_stream(&attr);
298         google::protobuf::io::CodedOutputStream attr_output(&attr_stream);
299
300         attr_output.WriteVarint32(kVarLengthTag1);
301         attr_output.WriteVarint32(it->first.size());
302         attr_output.WriteString(it->first);
303         attr_output.WriteVarint32(kVarLengthTag2);
304         attr_output.WriteVarint32(it->second.size());
305         attr_output.WriteRaw(it->second.data(), it->second.size());
306       }
307
308       // Two CodedOutputStreams are needed because inner messages must be
309       // prefixed by their total length, which can't be easily computed before
310       // writing their tags and values.
311       result_output.WriteVarint32(kVarLengthTag2);
312       result_output.WriteVarint32(attr.size());
313       result_output.WriteRaw(attr.data(), attr.size());
314     }
315   }
316
317   base::WorkerPool::PostTask(
318       FROM_HERE, base::Bind(&PersistFile, cache_path, result), false);
319
320   return true;
321 }
322
323 void FakeCryptohomeClient::InstallAttributesIsReady(
324     const BoolDBusMethodCallback& callback) {
325   base::MessageLoop::current()->PostTask(
326       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
327 }
328
329 bool FakeCryptohomeClient::InstallAttributesIsInvalid(bool* is_invalid) {
330   *is_invalid = false;
331   return true;
332 }
333
334 bool FakeCryptohomeClient::InstallAttributesIsFirstInstall(
335     bool* is_first_install) {
336   *is_first_install = !locked_;
337   return true;
338 }
339
340 void FakeCryptohomeClient::TpmAttestationIsPrepared(
341     const BoolDBusMethodCallback& callback) {
342   base::MessageLoop::current()->PostTask(
343       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
344 }
345
346 void FakeCryptohomeClient::TpmAttestationIsEnrolled(
347     const BoolDBusMethodCallback& callback) {
348   base::MessageLoop::current()->PostTask(
349       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, true));
350 }
351
352 void FakeCryptohomeClient::AsyncTpmAttestationCreateEnrollRequest(
353     chromeos::attestation::PrivacyCAType pca_type,
354     const AsyncMethodCallback& callback) {
355   ReturnAsyncMethodResult(callback, true);
356 }
357
358 void FakeCryptohomeClient::AsyncTpmAttestationEnroll(
359     chromeos::attestation::PrivacyCAType pca_type,
360     const std::string& pca_response,
361     const AsyncMethodCallback& callback) {
362   ReturnAsyncMethodResult(callback, false);
363 }
364
365 void FakeCryptohomeClient::AsyncTpmAttestationCreateCertRequest(
366     chromeos::attestation::PrivacyCAType pca_type,
367     attestation::AttestationCertificateProfile certificate_profile,
368     const std::string& user_id,
369     const std::string& request_origin,
370     const AsyncMethodCallback& callback) {
371   ReturnAsyncMethodResult(callback, true);
372 }
373
374 void FakeCryptohomeClient::AsyncTpmAttestationFinishCertRequest(
375     const std::string& pca_response,
376     attestation::AttestationKeyType key_type,
377     const std::string& user_id,
378     const std::string& key_name,
379     const AsyncMethodCallback& callback) {
380   ReturnAsyncMethodResult(callback, true);
381 }
382
383 void FakeCryptohomeClient::TpmAttestationDoesKeyExist(
384     attestation::AttestationKeyType key_type,
385     const std::string& user_id,
386     const std::string& key_name,
387     const BoolDBusMethodCallback& callback) {
388   base::MessageLoop::current()->PostTask(
389       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
390 }
391
392 void FakeCryptohomeClient::TpmAttestationGetCertificate(
393     attestation::AttestationKeyType key_type,
394     const std::string& user_id,
395     const std::string& key_name,
396     const DataMethodCallback& callback) {
397   base::MessageLoop::current()->PostTask(
398       FROM_HERE,
399       base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
400 }
401
402 void FakeCryptohomeClient::TpmAttestationGetPublicKey(
403     attestation::AttestationKeyType key_type,
404     const std::string& user_id,
405     const std::string& key_name,
406     const DataMethodCallback& callback) {
407   base::MessageLoop::current()->PostTask(
408       FROM_HERE,
409       base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
410 }
411
412 void FakeCryptohomeClient::TpmAttestationRegisterKey(
413     attestation::AttestationKeyType key_type,
414     const std::string& user_id,
415     const std::string& key_name,
416     const AsyncMethodCallback& callback) {
417   ReturnAsyncMethodResult(callback, true);
418 }
419
420 void FakeCryptohomeClient::TpmAttestationSignEnterpriseChallenge(
421     attestation::AttestationKeyType key_type,
422     const std::string& user_id,
423     const std::string& key_name,
424     const std::string& domain,
425     const std::string& device_id,
426     attestation::AttestationChallengeOptions options,
427     const std::string& challenge,
428     const AsyncMethodCallback& callback) {
429   ReturnAsyncMethodResult(callback, true);
430 }
431
432 void FakeCryptohomeClient::TpmAttestationSignSimpleChallenge(
433     attestation::AttestationKeyType key_type,
434     const std::string& user_id,
435     const std::string& key_name,
436     const std::string& challenge,
437     const AsyncMethodCallback& callback) {
438   ReturnAsyncMethodResult(callback, true);
439 }
440
441 void FakeCryptohomeClient::TpmAttestationGetKeyPayload(
442     attestation::AttestationKeyType key_type,
443     const std::string& user_id,
444     const std::string& key_name,
445     const DataMethodCallback& callback) {
446   base::MessageLoop::current()->PostTask(
447       FROM_HERE,
448       base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false, std::string()));
449 }
450
451 void FakeCryptohomeClient::TpmAttestationSetKeyPayload(
452     attestation::AttestationKeyType key_type,
453     const std::string& user_id,
454     const std::string& key_name,
455     const std::string& payload,
456     const BoolDBusMethodCallback& callback) {
457   base::MessageLoop::current()->PostTask(
458       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
459 }
460
461 void FakeCryptohomeClient::TpmAttestationDeleteKeys(
462     attestation::AttestationKeyType key_type,
463     const std::string& user_id,
464     const std::string& key_prefix,
465     const BoolDBusMethodCallback& callback) {
466   base::MessageLoop::current()->PostTask(
467       FROM_HERE, base::Bind(callback, DBUS_METHOD_CALL_SUCCESS, false));
468 }
469
470 void FakeCryptohomeClient::CheckKeyEx(
471     const cryptohome::AccountIdentifier& id,
472     const cryptohome::AuthorizationRequest& auth,
473     const cryptohome::CheckKeyRequest& request,
474     const ProtobufMethodCallback& callback) {
475   ReturnProtobufMethodCallback(id.email(), callback);
476 }
477
478 void FakeCryptohomeClient::MountEx(
479     const cryptohome::AccountIdentifier& id,
480     const cryptohome::AuthorizationRequest& auth,
481     const cryptohome::MountRequest& request,
482     const ProtobufMethodCallback& callback) {
483   ReturnProtobufMethodCallback(id.email(), callback);
484 }
485
486 void FakeCryptohomeClient::AddKeyEx(
487     const cryptohome::AccountIdentifier& id,
488     const cryptohome::AuthorizationRequest& auth,
489     const cryptohome::AddKeyRequest& request,
490     const ProtobufMethodCallback& callback) {
491   ReturnProtobufMethodCallback(id.email(), callback);
492 }
493
494 void FakeCryptohomeClient::RemoveKeyEx(
495     const cryptohome::AccountIdentifier& id,
496     const cryptohome::AuthorizationRequest& auth,
497     const cryptohome::RemoveKeyRequest& request,
498     const ProtobufMethodCallback& callback) {
499   ReturnProtobufMethodCallback(id.email(), callback);
500 }
501
502 void FakeCryptohomeClient::UpdateKeyEx(
503     const cryptohome::AccountIdentifier& id,
504     const cryptohome::AuthorizationRequest& auth,
505     const cryptohome::UpdateKeyRequest& request,
506     const ProtobufMethodCallback& callback) {
507   ReturnProtobufMethodCallback(id.email(), callback);
508 }
509
510 void FakeCryptohomeClient::SetServiceIsAvailable(bool is_available) {
511   service_is_available_ = is_available;
512   if (is_available) {
513     std::vector<WaitForServiceToBeAvailableCallback> callbacks;
514     callbacks.swap(pending_wait_for_service_to_be_available_callbacks_);
515     for (size_t i = 0; i < callbacks.size(); ++i)
516       callbacks[i].Run(is_available);
517   }
518 }
519
520 // static
521 std::vector<uint8> FakeCryptohomeClient::GetStubSystemSalt() {
522   const char kStubSystemSalt[] = "stub_system_salt";
523   return std::vector<uint8>(kStubSystemSalt,
524                             kStubSystemSalt + arraysize(kStubSystemSalt) - 1);
525 }
526
527 void FakeCryptohomeClient::ReturnProtobufMethodCallback(
528     const std::string& userid,
529     const ProtobufMethodCallback& callback) {
530   cryptohome::BaseReply reply;
531   reply.set_error(cryptohome::CRYPTOHOME_ERROR_NOT_SET);
532   cryptohome::MountReply* mount =
533       reply.MutableExtension(cryptohome::MountReply::reply);
534   mount->set_sanitized_username(GetStubSanitizedUsername(userid));
535   base::MessageLoop::current()->PostTask(
536       FROM_HERE,
537       base::Bind(callback,
538                  DBUS_METHOD_CALL_SUCCESS,
539                  true,
540                  reply));
541 }
542
543 void FakeCryptohomeClient::ReturnAsyncMethodResult(
544     const AsyncMethodCallback& callback,
545     bool returns_data) {
546   base::MessageLoop::current()->PostTask(
547       FROM_HERE,
548       base::Bind(&FakeCryptohomeClient::ReturnAsyncMethodResultInternal,
549                  weak_ptr_factory_.GetWeakPtr(),
550                  callback,
551                  returns_data));
552 }
553
554 void FakeCryptohomeClient::ReturnAsyncMethodResultInternal(
555     const AsyncMethodCallback& callback,
556     bool returns_data) {
557   callback.Run(async_call_id_);
558   if (!returns_data && !async_call_status_handler_.is_null()) {
559     base::MessageLoop::current()->PostTask(
560         FROM_HERE,
561         base::Bind(async_call_status_handler_,
562                    async_call_id_,
563                    true,
564                    cryptohome::MOUNT_ERROR_NONE));
565   } else if (returns_data && !async_call_status_data_handler_.is_null()) {
566     base::MessageLoop::current()->PostTask(
567         FROM_HERE,
568         base::Bind(async_call_status_data_handler_,
569                    async_call_id_,
570                    true,
571                    std::string()));
572   }
573   ++async_call_id_;
574 }
575
576 }  // namespace chromeos