Elly Jones | eca6ef1 | 2012-03-07 14:37:08 -0500 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | // |
| 5 | // InstallAttributes - class for managing install-time system attributes. |
| 6 | |
| 7 | #ifndef CRYPTOHOME_INSTALL_ATTRIBUTES_H_ |
| 8 | #define CRYPTOHOME_INSTALL_ATTRIBUTES_H_ |
| 9 | |
Gwendal Grignou | c7acaa9 | 2016-06-24 15:34:06 -0700 | [diff] [blame] | 10 | #include <memory> |
Alex Vakulenko | b4b694a | 2014-07-18 17:21:35 -0700 | [diff] [blame] | 11 | #include <string> |
| 12 | |
Gwendal Grignou | dcdc1a4 | 2016-06-30 09:41:01 -0700 | [diff] [blame] | 13 | #include <base/files/file_path.h> |
Ben Chan | 4ac108c | 2014-09-02 23:26:04 -0700 | [diff] [blame] | 14 | #include <base/macros.h> |
Darren Krahn | 1f9b3e4 | 2013-12-18 17:33:54 -0800 | [diff] [blame] | 15 | #include <base/observer_list.h> |
Qijiang Fan | 41a483a | 2020-05-07 13:12:37 +0900 | [diff] [blame] | 16 | #include <base/observer_list_types.h> |
Elly Jones | eca6ef1 | 2012-03-07 14:37:08 -0500 | [diff] [blame] | 17 | #include <base/values.h> |
Alex Vakulenko | e769653 | 2015-10-16 16:27:29 -0700 | [diff] [blame] | 18 | #include <brillo/secure_blob.h> |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 19 | |
Alex Vakulenko | b4b694a | 2014-07-18 17:21:35 -0700 | [diff] [blame] | 20 | #include "cryptohome/crypto.h" |
Greg Kerr | f9b0fc1 | 2020-08-13 22:29:10 +0000 | [diff] [blame] | 21 | #include "cryptohome/install_attributes.pb.h" |
Alex Vakulenko | b4b694a | 2014-07-18 17:21:35 -0700 | [diff] [blame] | 22 | #include "cryptohome/lockbox.h" |
| 23 | #include "cryptohome/platform.h" |
| 24 | #include "cryptohome/tpm.h" |
Alex Vakulenko | b4b694a | 2014-07-18 17:21:35 -0700 | [diff] [blame] | 25 | |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 26 | namespace cryptohome { |
| 27 | |
| 28 | // InstallAttributes - manages secure, install-time attributes |
| 29 | // |
| 30 | // Provides setting and getting of tamper-evident install-time |
| 31 | // attributes. Upon finalization, the underlying tamper-evident |
| 32 | // store will "lock" the attributes such that they become read-only |
| 33 | // until the next install. |
| 34 | // |
| 35 | // InstallAttributes is not thread-safe and should not be accessed in parallel. |
| 36 | class InstallAttributes { |
| 37 | public: |
Mattias Nissler | bb0191f | 2018-12-11 16:07:05 +0100 | [diff] [blame] | 38 | enum class Status { |
| 39 | kUnknown, // Not initialized yet. |
| 40 | kTpmNotOwned, // TPM not owned yet. |
| 41 | kFirstInstall, // Allows writing. |
| 42 | kValid, // Validated successfully. |
| 43 | kInvalid, // Not valid, e.g. clobbered, absent. |
John L Chen | cbf32cf | 2019-05-29 18:34:42 +0800 | [diff] [blame] | 44 | COUNT, // This is unused, just for counting the number of elements. |
| 45 | // Note that COUNT should always be the last element. |
Mattias Nissler | bb0191f | 2018-12-11 16:07:05 +0100 | [diff] [blame] | 46 | }; |
| 47 | |
Qijiang Fan | 41a483a | 2020-05-07 13:12:37 +0900 | [diff] [blame] | 48 | class Observer : public base::CheckedObserver { |
Darren Krahn | 1f9b3e4 | 2013-12-18 17:33:54 -0800 | [diff] [blame] | 49 | public: |
| 50 | virtual void OnFinalized() = 0; |
| 51 | }; |
| 52 | |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 53 | // Creates an instance of install attributes that will use the |tpm|. If |tpm| |
| 54 | // is NULL, InstallAttributes will proceed insecurely (unless it is set with |
Nam T. Nguyen | 0e6fbb6 | 2014-03-18 09:51:43 -0700 | [diff] [blame] | 55 | // SetTpm at a later time). |
Elly Jones | eca6ef1 | 2012-03-07 14:37:08 -0500 | [diff] [blame] | 56 | explicit InstallAttributes(Tpm* tpm); |
Qijiang Fan | 6bc59e1 | 2020-11-11 02:51:06 +0900 | [diff] [blame] | 57 | InstallAttributes(const InstallAttributes&) = delete; |
| 58 | InstallAttributes& operator=(const InstallAttributes&) = delete; |
| 59 | |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 60 | virtual ~InstallAttributes(); |
| 61 | |
John L Chen | cbf32cf | 2019-05-29 18:34:42 +0800 | [diff] [blame] | 62 | virtual Status status() const { return status_; } |
Mattias Nissler | bb0191f | 2018-12-11 16:07:05 +0100 | [diff] [blame] | 63 | |
| 64 | // Sets status (for testing). |
| 65 | void set_status_for_testing(Status status) { status_ = status; } |
| 66 | |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 67 | // Updates the TPM used by Lockbox or disables the use of the TPM. |
| 68 | // This does NOT take ownership of the pointer. |
| 69 | virtual void SetTpm(Tpm* tpm); |
| 70 | |
| 71 | // Prepares the class for use including instantiating a new environment |
Ching-Kang Yen | db834d2 | 2021-03-08 01:18:40 +0800 | [diff] [blame] | 72 | // if needed. If initialization completes, |tpm| will be used to remove |
Nam T. Nguyen | 0e6fbb6 | 2014-03-18 09:51:43 -0700 | [diff] [blame] | 73 | // this instance's dependency on the TPM ownership. |
Ching-Kang Yen | db834d2 | 2021-03-08 01:18:40 +0800 | [diff] [blame] | 74 | virtual bool Init(Tpm* tpm); |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 75 | |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 76 | // Populates |value| based on the content referenced by |name|. |
| 77 | // |
| 78 | // Parameters |
| 79 | // - name: addressable name of the entry to retrieve |
| 80 | // - value: pointer to a Blob to populate with the value, if found. |
| 81 | // Returns true if |name| exists in the store and |value| will be populated. |
| 82 | // Returns false if the |name| does not exist. |
Alex Vakulenko | e769653 | 2015-10-16 16:27:29 -0700 | [diff] [blame] | 83 | virtual bool Get(const std::string& name, brillo::Blob* value) const; |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 84 | |
| 85 | // Populates |name| and |value| based on the content referenced by |index|. |
| 86 | // |
| 87 | // Parameters |
| 88 | // - index: 0-addressable index of the desired entry. |
| 89 | // - name: addressable name of the entry to retrieve |
| 90 | // - value: pointer to a Blob to populate with the value, if found. |
| 91 | // Returns true if |index| exists in the store. |
| 92 | // Returns false if the |index| does not exist. |
| 93 | virtual bool GetByIndex(int index, |
| 94 | std::string* name, |
Alex Vakulenko | e769653 | 2015-10-16 16:27:29 -0700 | [diff] [blame] | 95 | brillo::Blob* value) const; |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 96 | |
| 97 | // Appends |name| and |value| as an attribute pair to the internal store. |
| 98 | // |
| 99 | // Parameters |
| 100 | // - name: attribute name to associate |value| with in the store |
| 101 | // - value: Blob of data to store with |name|. |
| 102 | // Returns true if the association can be stored, and false if it can't. |
| 103 | // If the given |name| already exists, it will be replaced. |
Alex Vakulenko | e769653 | 2015-10-16 16:27:29 -0700 | [diff] [blame] | 104 | virtual bool Set(const std::string& name, const brillo::Blob& value); |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 105 | |
| 106 | // Finalizes the install-time attributes making them tamper-evident. |
| 107 | virtual bool Finalize(); |
| 108 | |
| 109 | // Returns the number of entries in the Lockbox. |
| 110 | virtual int Count() const; |
| 111 | |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 112 | // Return InstallAttributes version. |
| 113 | // This is populated from the default value in install_attributes.proto and |
| 114 | // should be incremented there when behavior vesioning is needed. |
| 115 | virtual uint64_t version() const { return version_; } |
| 116 | |
| 117 | // Allows overriding the version, often for testing. |
| 118 | virtual void set_version(uint64_t version) { version_ = version; } |
| 119 | |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 120 | // Returns true if the attribute storage is securely stored. It does not |
| 121 | // indicate if the store has been finalized, just if the system TPM/Lockbox |
| 122 | // is being used. |
| 123 | virtual bool is_secure() const { return is_secure_; } |
| 124 | |
| 125 | virtual void set_is_secure(bool is_secure) { is_secure_ = is_secure; } |
| 126 | |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 127 | // Allows replacement of the underlying lockbox. |
| 128 | // This does NOT take ownership of the pointer. |
| 129 | virtual void set_lockbox(Lockbox* lockbox) { lockbox_ = lockbox; } |
| 130 | |
| 131 | virtual Lockbox* lockbox() { return lockbox_; } |
| 132 | |
| 133 | // Replaces the platform implementation. |
| 134 | // Does NOT take ownership of the pointer. |
| 135 | virtual void set_platform(Platform* platform) { platform_ = platform; } |
| 136 | |
| 137 | virtual Platform* platform() { return platform_; } |
| 138 | |
Elly Jones | eca6ef1 | 2012-03-07 14:37:08 -0500 | [diff] [blame] | 139 | // Returns a description of the system's install attributes as a Value. |
| 140 | // |
hscham | 6d748eb | 2020-10-09 14:46:06 +0900 | [diff] [blame] | 141 | // The Value is of type Dictionary, with keys "initialized", "version", |
Elly Jones | eca6ef1 | 2012-03-07 14:37:08 -0500 | [diff] [blame] | 142 | // "lockbox_index", "secure", "invalid", "first_install" and "size". |
hscham | 6d748eb | 2020-10-09 14:46:06 +0900 | [diff] [blame] | 143 | virtual base::Value GetStatus(); |
Elly Jones | eca6ef1 | 2012-03-07 14:37:08 -0500 | [diff] [blame] | 144 | |
Tom Hughes | 6711cdc | 2020-09-14 08:34:01 -0700 | [diff] [blame] | 145 | void AddObserver(Observer* obs) { observer_list_.AddObserver(obs); } |
Darren Krahn | 1f9b3e4 | 2013-12-18 17:33:54 -0800 | [diff] [blame] | 146 | |
Tom Hughes | 6711cdc | 2020-09-14 08:34:01 -0700 | [diff] [blame] | 147 | void RemoveObserver(Observer* obs) { observer_list_.RemoveObserver(obs); } |
Darren Krahn | 1f9b3e4 | 2013-12-18 17:33:54 -0800 | [diff] [blame] | 148 | |
| 149 | void NotifyFinalized() { |
Eric Caruso | 388ba9a | 2018-01-12 14:53:36 -0800 | [diff] [blame] | 150 | for (Observer& observer : observer_list_) |
| 151 | observer.OnFinalized(); |
Darren Krahn | 1f9b3e4 | 2013-12-18 17:33:54 -0800 | [diff] [blame] | 152 | } |
| 153 | |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 154 | // Provides the TPM NVRAM index to be used by the underlying Lockbox instance. |
| 155 | static const uint32_t kLockboxIndex; |
| 156 | // Provides the default location for the attributes data file. |
Gwendal Grignou | dcdc1a4 | 2016-06-30 09:41:01 -0700 | [diff] [blame] | 157 | static const char kDefaultDataFile[]; |
Thiemo Nagel | ea7dbf3 | 2014-10-16 20:12:54 +0200 | [diff] [blame] | 158 | // File permissions of attributes data file (modulo umask). |
| 159 | static const mode_t kDataFilePermissions; |
Mattias Nissler | 0fae369 | 2013-01-23 16:20:47 +0100 | [diff] [blame] | 160 | // Provides the default location for the cache file. |
Gwendal Grignou | dcdc1a4 | 2016-06-30 09:41:01 -0700 | [diff] [blame] | 161 | static const char kDefaultCacheFile[]; |
Thiemo Nagel | ea7dbf3 | 2014-10-16 20:12:54 +0200 | [diff] [blame] | 162 | // File permissions of cache file (modulo umask). |
| 163 | static const mode_t kCacheFilePermissions; |
Elly Jones | eca6ef1 | 2012-03-07 14:37:08 -0500 | [diff] [blame] | 164 | |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 165 | protected: |
| 166 | // Helper to find a given entry index using its name. |
| 167 | virtual int FindIndexByName(const std::string& name) const; |
| 168 | // Convert the current attributes to a byte stream and write it |
| 169 | // to |out_bytes|. |
Alex Vakulenko | e769653 | 2015-10-16 16:27:29 -0700 | [diff] [blame] | 170 | virtual bool SerializeAttributes(brillo::Blob* out_bytes); |
Mattias Nissler | eb2d207 | 2018-12-05 16:08:35 +0100 | [diff] [blame] | 171 | // Remove the data file on disk if it exists. |
| 172 | bool ClearData(); |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 173 | |
| 174 | private: |
Mattias Nissler | bb0191f | 2018-12-11 16:07:05 +0100 | [diff] [blame] | 175 | Status status_ = Status::kUnknown; |
Tom Hughes | 6711cdc | 2020-09-14 08:34:01 -0700 | [diff] [blame] | 176 | bool is_secure_ = false; // Indicates if there is hardware protection (TPM). |
| 177 | base::FilePath data_file_; // Location data is persisted to. |
| 178 | base::FilePath cache_file_; // World-readable data cache file. |
| 179 | uint64_t version_ = 0; // Default implementation version. |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 180 | // Default implementations of dependencies |
Gwendal Grignou | c7acaa9 | 2016-06-24 15:34:06 -0700 | [diff] [blame] | 181 | std::unique_ptr<SerializedInstallAttributes> default_attributes_; |
| 182 | std::unique_ptr<Lockbox> default_lockbox_; |
| 183 | std::unique_ptr<Platform> default_platform_; |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 184 | // Overridable dependency pointer which allow for easy injection. |
Mattias Nissler | eb2d207 | 2018-12-05 16:08:35 +0100 | [diff] [blame] | 185 | SerializedInstallAttributes* attributes_ = nullptr; |
| 186 | Lockbox* lockbox_ = nullptr; |
| 187 | Platform* platform_ = nullptr; |
Alex Vakulenko | 5e5accd | 2015-06-15 12:53:22 -0700 | [diff] [blame] | 188 | base::ObserverList<Observer> observer_list_; |
Will Drewry | dcd0994 | 2011-04-15 09:31:33 -0500 | [diff] [blame] | 189 | }; |
| 190 | |
| 191 | } // namespace cryptohome |
| 192 | |
| 193 | #endif // CRYPTOHOME_INSTALL_ATTRIBUTES_H_ |