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 #ifndef CHROMEOS_DBUS_CRYPTOHOME_FAKE_CRYPTOHOME_CLIENT_H_
6 #define CHROMEOS_DBUS_CRYPTOHOME_FAKE_CRYPTOHOME_CLIENT_H_
7 
8 #include <stdint.h>
9 
10 #include <map>
11 #include <set>
12 #include <string>
13 #include <utility>
14 #include <vector>
15 
16 #include "base/macros.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/observer_list.h"
19 #include "base/optional.h"
20 #include "base/timer/timer.h"
21 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
22 #include "chromeos/dbus/cryptohome/key.pb.h"
23 #include "chromeos/dbus/cryptohome/rpc.pb.h"
24 
25 namespace chromeos {
26 
COMPONENT_EXPORT(CRYPTOHOME_CLIENT)27 class COMPONENT_EXPORT(CRYPTOHOME_CLIENT) FakeCryptohomeClient
28     : public CryptohomeClient {
29  public:
30   // FakeCryptohomeClient can be embedded in unit tests, but the
31   // InitializeFake/Shutdown pattern should be preferred. Constructing the
32   // instance will set the global instance for the fake and for the base class,
33   // so the static Get() accessor can be used with that pattern.
34   FakeCryptohomeClient();
35   ~FakeCryptohomeClient() override;
36 
37   // Checks that a FakeCryptohome instance was initialized and returns it.
38   static FakeCryptohomeClient* Get();
39 
40   // Expose stub password for tests.
41   static const char kStubTpmPassword[];
42 
43   // CryptohomeClient overrides
44   void AddObserver(Observer* observer) override;
45   void RemoveObserver(Observer* observer) override;
46   void WaitForServiceToBeAvailable(
47       WaitForServiceToBeAvailableCallback callback) override;
48   void IsMounted(DBusMethodCallback<bool> callback) override;
49   void UnmountEx(const cryptohome::UnmountRequest& request,
50                  DBusMethodCallback<cryptohome::BaseReply> callback) override;
51   void MigrateKeyEx(
52       const cryptohome::AccountIdentifier& account,
53       const cryptohome::AuthorizationRequest& auth_request,
54       const cryptohome::MigrateKeyRequest& migrate_request,
55       DBusMethodCallback<cryptohome::BaseReply> callback) override;
56   void RemoveEx(const cryptohome::AccountIdentifier& account,
57                 DBusMethodCallback<cryptohome::BaseReply> callback) override;
58   void RenameCryptohome(
59       const cryptohome::AccountIdentifier& cryptohome_id_from,
60       const cryptohome::AccountIdentifier& cryptohome_id_to,
61       DBusMethodCallback<cryptohome::BaseReply> callback) override;
62   void GetAccountDiskUsage(
63       const cryptohome::AccountIdentifier& account_id,
64       DBusMethodCallback<cryptohome::BaseReply> callback) override;
65   void GetSystemSalt(
66       DBusMethodCallback<std::vector<uint8_t>> callback) override;
67   void GetSanitizedUsername(const cryptohome::AccountIdentifier& cryptohome_id,
68                             DBusMethodCallback<std::string> callback) override;
69   std::string BlockingGetSanitizedUsername(
70       const cryptohome::AccountIdentifier& cryptohome_id) override;
71   void MountGuestEx(
72       const cryptohome::MountGuestRequest& request,
73       DBusMethodCallback<cryptohome::BaseReply> callback) override;
74   void GetRsuDeviceId(
75       DBusMethodCallback<cryptohome::BaseReply> callback) override;
76   void TpmIsReady(DBusMethodCallback<bool> callback) override;
77   void TpmIsEnabled(DBusMethodCallback<bool> callback) override;
78   bool CallTpmIsEnabledAndBlock(bool* enabled) override;
79   void TpmGetPassword(DBusMethodCallback<std::string> callback) override;
80   void TpmIsOwned(DBusMethodCallback<bool> callback) override;
81   bool CallTpmIsOwnedAndBlock(bool* owned) override;
82   void TpmIsBeingOwned(DBusMethodCallback<bool> callback) override;
83   bool CallTpmIsBeingOwnedAndBlock(bool* owning) override;
84   void TpmCanAttemptOwnership(VoidDBusMethodCallback callback) override;
85   void TpmClearStoredPassword(VoidDBusMethodCallback callback) override;
86   bool CallTpmClearStoredPasswordAndBlock() override;
87   void Pkcs11IsTpmTokenReady(DBusMethodCallback<bool> callback) override;
88   void Pkcs11GetTpmTokenInfo(
89       DBusMethodCallback<TpmTokenInfo> callback) override;
90   void Pkcs11GetTpmTokenInfoForUser(
91       const cryptohome::AccountIdentifier& cryptohome_id,
92       DBusMethodCallback<TpmTokenInfo> callback) override;
93   bool InstallAttributesGet(const std::string& name,
94                             std::vector<uint8_t>* value,
95                             bool* successful) override;
96   bool InstallAttributesSet(const std::string& name,
97                             const std::vector<uint8_t>& value,
98                             bool* successful) override;
99   bool InstallAttributesFinalize(bool* successful) override;
100   void InstallAttributesIsReady(DBusMethodCallback<bool> callback) override;
101   bool InstallAttributesIsInvalid(bool* is_invalid) override;
102   bool InstallAttributesIsFirstInstall(bool* is_first_install) override;
103   void TpmGetVersion(DBusMethodCallback<TpmVersionInfo> callback) override;
104   void GetKeyDataEx(
105       const cryptohome::AccountIdentifier& cryptohome_id,
106       const cryptohome::AuthorizationRequest& auth,
107       const cryptohome::GetKeyDataRequest& request,
108       DBusMethodCallback<cryptohome::BaseReply> callback) override;
109   void CheckKeyEx(const cryptohome::AccountIdentifier& cryptohome_id,
110                   const cryptohome::AuthorizationRequest& auth,
111                   const cryptohome::CheckKeyRequest& request,
112                   DBusMethodCallback<cryptohome::BaseReply> callback) override;
113   void MountEx(const cryptohome::AccountIdentifier& cryptohome_id,
114                const cryptohome::AuthorizationRequest& auth,
115                const cryptohome::MountRequest& request,
116                DBusMethodCallback<cryptohome::BaseReply> callback) override;
117   void LockToSingleUserMountUntilReboot(
118       const cryptohome::LockToSingleUserMountUntilRebootRequest& request,
119       DBusMethodCallback<cryptohome::BaseReply> callback) override;
120   void AddKeyEx(const cryptohome::AccountIdentifier& cryptohome_id,
121                 const cryptohome::AuthorizationRequest& auth,
122                 const cryptohome::AddKeyRequest& request,
123                 DBusMethodCallback<cryptohome::BaseReply> callback) override;
124   void AddDataRestoreKey(
125       const cryptohome::AccountIdentifier& cryptohome_id,
126       const cryptohome::AuthorizationRequest& auth,
127       DBusMethodCallback<cryptohome::BaseReply> callback) override;
128   void UpdateKeyEx(const cryptohome::AccountIdentifier& cryptohome_id,
129                    const cryptohome::AuthorizationRequest& auth,
130                    const cryptohome::UpdateKeyRequest& request,
131                    DBusMethodCallback<cryptohome::BaseReply> callback) override;
132   void RemoveKeyEx(const cryptohome::AccountIdentifier& cryptohome_id,
133                    const cryptohome::AuthorizationRequest& auth,
134                    const cryptohome::RemoveKeyRequest& request,
135                    DBusMethodCallback<cryptohome::BaseReply> callback) override;
136   void MassRemoveKeys(
137       const cryptohome::AccountIdentifier& cryptohome_id,
138       const cryptohome::AuthorizationRequest& auth,
139       const cryptohome::MassRemoveKeysRequest& request,
140       DBusMethodCallback<cryptohome::BaseReply> callback) override;
141   void GetBootAttribute(
142       const cryptohome::GetBootAttributeRequest& request,
143       DBusMethodCallback<cryptohome::BaseReply> callback) override;
144   void SetBootAttribute(
145       const cryptohome::SetBootAttributeRequest& request,
146       DBusMethodCallback<cryptohome::BaseReply> callback) override;
147   void FlushAndSignBootAttributes(
148       const cryptohome::FlushAndSignBootAttributesRequest& request,
149       DBusMethodCallback<cryptohome::BaseReply> callback) override;
150   void GetTpmStatus(
151       const cryptohome::GetTpmStatusRequest& request,
152       DBusMethodCallback<cryptohome::BaseReply> callback) override;
153   void MigrateToDircrypto(const cryptohome::AccountIdentifier& cryptohome_id,
154                           const cryptohome::MigrateToDircryptoRequest& request,
155                           VoidDBusMethodCallback callback) override;
156   void RemoveFirmwareManagementParametersFromTpm(
157       const cryptohome::RemoveFirmwareManagementParametersRequest& request,
158       DBusMethodCallback<cryptohome::BaseReply> callback) override;
159   void SetFirmwareManagementParametersInTpm(
160       const cryptohome::SetFirmwareManagementParametersRequest& request,
161       DBusMethodCallback<cryptohome::BaseReply> callback) override;
162   void NeedsDircryptoMigration(
163       const cryptohome::AccountIdentifier& cryptohome_id,
164       DBusMethodCallback<bool> callback) override;
165   void GetSupportedKeyPolicies(
166       const cryptohome::GetSupportedKeyPoliciesRequest& request,
167       DBusMethodCallback<cryptohome::BaseReply> callback) override;
168   void IsQuotaSupported(DBusMethodCallback<bool> callback) override;
169   void GetCurrentSpaceForUid(uid_t android_uid,
170                              DBusMethodCallback<int64_t> callback) override;
171   void GetCurrentSpaceForGid(gid_t android_gid,
172                              DBusMethodCallback<int64_t> callback) override;
173   void CheckHealth(const cryptohome::CheckHealthRequest& request,
174                    DBusMethodCallback<cryptohome::BaseReply> callback) override;
175   void StartFingerprintAuthSession(
176       const cryptohome::AccountIdentifier& id,
177       const cryptohome::StartFingerprintAuthSessionRequest& request,
178       DBusMethodCallback<cryptohome::BaseReply> callback) override;
179   void EndFingerprintAuthSession(
180       const cryptohome::EndFingerprintAuthSessionRequest& request,
181       DBusMethodCallback<cryptohome::BaseReply> callback) override;
182 
183   /////////// Test helpers ////////////
184 
185   // Changes the behavior of WaitForServiceToBeAvailable(). This method runs
186   // pending callbacks if is_available is true.
187   void SetServiceIsAvailable(bool is_available);
188 
189   // Runs pending availability callbacks reporting that the service is
190   // unavailable. Expects service not to be available when called.
191   void ReportServiceIsNotAvailable();
192 
193   // Changes the behavior of TpmIsReady().
194   void set_tpm_is_ready(bool value) { tpm_is_ready_ = value; }
195 
196   // Changes the behavior of TpmIsEnabled().
197   void set_tpm_is_enabled(bool value) { tpm_is_enabled_ = value; }
198 
199   // Sets whether the MountEx() call should fail when the |create| field is not
200   // provided (the error code will be CRYPTOHOME_ERROR_ACCOUNT_NOT_FOUND).
201   // This allows to simulate the behavior during the new user profile creation.
202   void set_mount_create_required(bool mount_create_required) {
203     mount_create_required_ = mount_create_required;
204   }
205 
206   // Sets the unmount result of Unmount() call.
207   void set_unmount_result(bool result) { unmount_result_ = result; }
208 
209   // Sets the system salt which will be returned from GetSystemSalt(). By
210   // default, GetSystemSalt() returns the value generated by
211   // GetStubSystemSalt().
212   void set_system_salt(const std::vector<uint8_t>& system_salt) {
213     system_salt_ = system_salt;
214   }
215 
216   // Returns the stub system salt as raw bytes. (not as a string encoded in the
217   // format used by SystemSaltGetter::ConvertRawSaltToHexString()).
218   static std::vector<uint8_t> GetStubSystemSalt();
219 
220   // Marks |cryptohome_id| as using ecryptfs (|use_ecryptfs|=true) or dircrypto
221   // (|use_ecryptfs|=false).
222   void SetEcryptfsUserHome(const cryptohome::AccountIdentifier& cryptohome_id,
223                            bool use_ecryptfs);
224 
225   // Sets whether dircrypto migration update should be run automatically.
226   // If set to false, the client will not send any dircrypto migration progress
227   // updates on its own - a test that sets this will have to call
228   // NotifyDircryptoMigrationProgress() for the progress to update.
229   void set_run_default_dircrypto_migration(bool value) {
230     run_default_dircrypto_migration_ = value;
231   }
232 
233   // Sets the CryptohomeError value to return.
234   void set_cryptohome_error(cryptohome::CryptohomeErrorCode error) {
235     cryptohome_error_ = error;
236   }
237 
238   void set_supports_low_entropy_credentials(bool supports) {
239     supports_low_entropy_credentials_ = supports;
240   }
241 
242   void set_enable_auth_check(bool enable_auth_check) {
243     enable_auth_check_ = enable_auth_check;
244   }
245 
246   void set_rsu_device_id(const std::string& rsu_device_id) {
247     rsu_device_id_ = rsu_device_id;
248   }
249 
250   // Calls TpmInitStatusUpdated() on Observer instances.
251   void NotifyTpmInitStatusUpdated(bool ready,
252                                   bool owned,
253                                   bool was_owned_this_boot);
254 
255   // Calls DircryptoMigrationProgress() on Observer instances.
256   void NotifyDircryptoMigrationProgress(
257       cryptohome::DircryptoMigrationStatus status,
258       uint64_t current,
259       uint64_t total);
260 
261   // Notifies LowDiskSpace() to Observer instances.
262   void NotifyLowDiskSpace(uint64_t disk_free_bytes);
263 
264   // MountEx getters.
265   const cryptohome::MountRequest& get_last_mount_request() const {
266     return last_mount_request_;
267   }
268   bool to_migrate_from_ecryptfs() const {
269     return last_mount_request_.to_migrate_from_ecryptfs();
270   }
271   bool hidden_mount() const { return last_mount_request_.hidden_mount(); }
272   bool public_mount() const { return last_mount_request_.public_mount(); }
273   const cryptohome::AuthorizationRequest& get_last_mount_authentication()
274       const {
275     return last_mount_auth_request_;
276   }
277   const std::string& get_secret_for_last_mount_authentication() const {
278     return last_mount_auth_request_.key().secret();
279   }
280 
281   // MigrateToDircrypto getters.
282   const cryptohome::AccountIdentifier& get_id_for_disk_migrated_to_dircrypto()
283       const {
284     return id_for_disk_migrated_to_dircrypto_;
285   }
286   bool minimal_migration() const {
287     return last_migrate_to_dircrypto_request_.minimal_migration();
288   }
289 
290   int remove_firmware_management_parameters_from_tpm_call_count() const {
291     return remove_firmware_management_parameters_from_tpm_call_count_;
292   }
293 
294   bool is_device_locked_to_single_user() const {
295     return is_device_locked_to_single_user_;
296   }
297 
298   void set_requires_powerwash(bool requires_powerwash) {
299     requires_powerwash_ = requires_powerwash;
300   }
301 
302  private:
303   void ReturnProtobufMethodCallback(
304       const cryptohome::BaseReply& reply,
305       DBusMethodCallback<cryptohome::BaseReply> callback);
306 
307   // Posts tasks which return fake results to the UI thread.
308   void ReturnAsyncMethodResult(AsyncMethodCallback callback);
309 
310   // Posts tasks which return fake data to the UI thread.
311   void ReturnAsyncMethodData(AsyncMethodCallback callback,
312                              const std::string& data);
313 
314   // This method is used to implement ReturnAsyncMethodResult without data.
315   void ReturnAsyncMethodResultInternal(AsyncMethodCallback callback);
316 
317   // This method is used to implement ReturnAsyncMethodResult with data.
318   void ReturnAsyncMethodDataInternal(AsyncMethodCallback callback,
319                                      const std::string& data);
320 
321   // This method is used to implement MigrateToDircrypto with simulated progress
322   // updates.
323   void OnDircryptoMigrationProgressUpdated();
324 
325   // Notifies AsyncCallStatus() to Observer instances.
326   void NotifyAsyncCallStatus(int async_id, bool return_status, int return_code);
327 
328   // Notifies AsyncCallStatusWithData() to Observer instances.
329   void NotifyAsyncCallStatusWithData(int async_id,
330                                      bool return_status,
331                                      const std::string& data);
332 
333   // Loads install attributes from the stub file.
334   bool LoadInstallAttributes();
335 
336   // Returns true if |cryptohome_id| has been marked as being an ecryptfs user
337   // home using SetEcryptfsUserHome.
338   bool IsEcryptfsUserHome(const cryptohome::AccountIdentifier& cryptohome_id);
339 
340   // Finds a key matching the given label. Wildcard labels are supported.
341   std::map<std::string, cryptohome::Key>::const_iterator FindKey(
342       const std::map<std::string, cryptohome::Key>& keys,
343       const std::string& label);
344 
345   bool service_is_available_ = true;
346   // If set, WaitForServiceToBeAvailable will run the callback, even if service
347   // is not available (instead of adding the callback to pending callback list).
348   bool service_reported_not_available_ = false;
349   base::ObserverList<Observer>::Unchecked observer_list_;
350 
351   int remove_firmware_management_parameters_from_tpm_call_count_ = 0;
352 
353   int async_call_id_ = 1;
354   bool mount_create_required_ = false;
355   bool unmount_result_ = true;
356   std::vector<uint8_t> system_salt_{GetStubSystemSalt()};
357 
358   std::vector<WaitForServiceToBeAvailableCallback>
359       pending_wait_for_service_to_be_available_callbacks_;
360 
361   // A stub store for InstallAttributes, mapping an attribute name to the
362   // associated data blob. Used to implement InstallAttributesSet and -Get.
363   std::map<std::string, std::vector<uint8_t>> install_attrs_;
364   bool locked_;
365 
366   std::map<cryptohome::AccountIdentifier,
367            std::map<std::string, cryptohome::Key>>
368       key_data_map_;
369 
370   // Set of account identifiers whose user homes use ecryptfs. User homes not
371   // mentioned here use dircrypto.
372   std::set<cryptohome::AccountIdentifier> ecryptfs_user_homes_;
373 
374   base::RepeatingTimer dircrypto_migration_progress_timer_;
375   uint64_t dircrypto_migration_progress_ = 0;
376 
377   bool run_default_dircrypto_migration_ = true;
378   bool supports_low_entropy_credentials_ = false;
379   // Controls if CheckKeyEx actually checks the key.
380   bool enable_auth_check_ = false;
381   bool tpm_is_ready_ = true;
382   bool tpm_is_enabled_ = true;
383 
384   // Reply to GetRsuDeviceId().
385   std::string rsu_device_id_;
386 
387   // MountEx fields.
388   cryptohome::CryptohomeErrorCode cryptohome_error_ =
389       cryptohome::CRYPTOHOME_ERROR_NOT_SET;
390   cryptohome::MountRequest last_mount_request_;
391   cryptohome::AuthorizationRequest last_mount_auth_request_;
392 
393   // MigrateToDircrypto fields.
394   cryptohome::AccountIdentifier id_for_disk_migrated_to_dircrypto_;
395   cryptohome::MigrateToDircryptoRequest last_migrate_to_dircrypto_request_;
396 
397   // Used by LockToSingleUserMountUntilReboot.
398   bool is_device_locked_to_single_user_ = false;
399 
400   // Used by GetStateRequiresPowerwash
401   bool requires_powerwash_ = false;
402 
403   base::WeakPtrFactory<FakeCryptohomeClient> weak_ptr_factory_{this};
404 
405   DISALLOW_COPY_AND_ASSIGN(FakeCryptohomeClient);
406 };
407 
408 }  // namespace chromeos
409 
410 #endif  // CHROMEOS_DBUS_CRYPTOHOME_FAKE_CRYPTOHOME_CLIENT_H_
411