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