1 //
2 // Copyright (C) 2020 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 #include "tpm_gatekeeper.h"
17
18 #include <algorithm>
19 #include <vector>
20
21 #include <android-base/logging.h>
22 #include <tss2/tss2_esys.h>
23 #include <tss2/tss2_mu.h>
24 #include <tss2/tss2_rc.h>
25
26 #ifdef _WIN32
27 #include <sysinfoapi.h>
28 #endif
29
30 #include "host/commands/secure_env/primary_key_builder.h"
31 #include "host/commands/secure_env/tpm_auth.h"
32 #include "host/commands/secure_env/tpm_hmac.h"
33 #include "host/commands/secure_env/tpm_random_source.h"
34
35 namespace cuttlefish {
36
TpmGatekeeper(TpmResourceManager & resource_manager,secure_env::Storage & secure_storage,secure_env::Storage & insecure_storage)37 TpmGatekeeper::TpmGatekeeper(
38 TpmResourceManager& resource_manager,
39 secure_env::Storage& secure_storage,
40 secure_env::Storage& insecure_storage)
41 : resource_manager_(resource_manager)
42 , secure_storage_(secure_storage)
43 , insecure_storage_(insecure_storage) {
44 }
45
46 /*
47 * The reinterpret_cast and kPasswordUnique data is combined together with TPM
48 * internal state to create the actual key used for Gatekeeper operations.
49 */
50
GetAuthTokenKey(const uint8_t ** auth_token_key,uint32_t * length) const51 bool TpmGatekeeper::GetAuthTokenKey(
52 const uint8_t** auth_token_key, uint32_t* length) const {
53 static constexpr char kAuthTokenUnique[] = "TpmGatekeeper auth token key";
54 *auth_token_key = reinterpret_cast<const uint8_t*>(kAuthTokenUnique);
55 *length = sizeof(kAuthTokenUnique);
56 return true;
57 }
58
GetPasswordKey(const uint8_t ** password_key,uint32_t * length)59 void TpmGatekeeper::GetPasswordKey(
60 const uint8_t** password_key, uint32_t* length) {
61 static constexpr char kPasswordUnique[] = "TpmGatekeeper password key";
62 *password_key = reinterpret_cast<const uint8_t*>(kPasswordUnique);
63 *length = sizeof(kPasswordUnique);
64 }
65
ComputePasswordSignature(uint8_t * signature,uint32_t signature_length,const uint8_t * key,uint32_t key_length,const uint8_t * password,uint32_t password_length,gatekeeper::salt_t salt) const66 void TpmGatekeeper::ComputePasswordSignature(
67 uint8_t* signature,
68 uint32_t signature_length,
69 const uint8_t* key,
70 uint32_t key_length,
71 const uint8_t* password,
72 uint32_t password_length,
73 gatekeeper::salt_t salt) const {
74 std::vector<uint8_t> message(password_length + sizeof(salt));
75 memcpy(message.data(), password, password_length);
76 memcpy(message.data() + password_length, &salt, sizeof(salt));
77 return ComputeSignature(
78 signature,
79 signature_length,
80 key,
81 key_length,
82 message.data(),
83 message.size());
84 }
85
GetRandom(void * random,uint32_t requested_size) const86 void TpmGatekeeper::GetRandom(void* random, uint32_t requested_size) const {
87 auto random_uint8 = reinterpret_cast<uint8_t*>(random);
88 TpmRandomSource(resource_manager_)
89 .GenerateRandom(random_uint8, requested_size);
90 }
91
ComputeSignature(uint8_t * signature,uint32_t signature_length,const uint8_t * key,uint32_t key_length,const uint8_t * message,uint32_t length) const92 void TpmGatekeeper::ComputeSignature(
93 uint8_t* signature,
94 uint32_t signature_length,
95 const uint8_t* key,
96 uint32_t key_length,
97 const uint8_t* message,
98 uint32_t length) const {
99 memset(signature, 0, signature_length);
100 std::string key_unique(reinterpret_cast<const char*>(key), key_length);
101
102 auto calculated_signature =
103 TpmHmacWithContext(resource_manager_, key_unique, message, length);
104 if (!calculated_signature) {
105 LOG(ERROR) << "Failure in calculating signature";
106 return;
107 }
108 memcpy(
109 signature,
110 calculated_signature->buffer,
111 std::min((int) calculated_signature->size, (int) signature_length));
112 }
113
GetMillisecondsSinceBoot() const114 uint64_t TpmGatekeeper::GetMillisecondsSinceBoot() const {
115 #ifdef _WIN32
116 return GetTickCount64();
117 #else
118 struct timespec time;
119 #ifdef __linux__
120 int res = clock_gettime(CLOCK_BOOTTIME, &time);
121 #else
122 int res = clock_gettime(CLOCK_MONOTONIC, &time);
123 #endif
124 if (res < 0) {
125 return 0;
126 }
127 return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000);
128 #endif
129 }
130
DefaultRecord(gatekeeper::secure_id_t secure_user_id)131 gatekeeper::failure_record_t DefaultRecord(
132 gatekeeper::secure_id_t secure_user_id) {
133 return (gatekeeper::failure_record_t) {
134 .secure_user_id = secure_user_id,
135 .last_checked_timestamp = 0,
136 .failure_counter = 0,
137 };
138 }
139
RecordToStorageData(const gatekeeper::failure_record_t & record)140 static Result<secure_env::ManagedStorageData> RecordToStorageData(
141 const gatekeeper::failure_record_t& record) {
142 return CF_EXPECT(secure_env::CreateStorageData(&record, sizeof(record)));
143 }
144
StorageDataToRecord(const secure_env::StorageData & data)145 static Result<gatekeeper::failure_record_t> StorageDataToRecord(
146 const secure_env::StorageData& data) {
147 gatekeeper::failure_record_t ret;
148 CF_EXPECT(data.size == sizeof(ret), "StorageData buffer had an incorrect size.");
149 memcpy(&ret, data.payload, data.size);
150 return ret;
151 }
152
GetFailureRecordImpl(secure_env::Storage & storage,uint32_t uid,gatekeeper::secure_id_t secure_user_id,gatekeeper::failure_record_t * record)153 static Result<void> GetFailureRecordImpl(
154 secure_env::Storage& storage,
155 uint32_t uid,
156 gatekeeper::secure_id_t secure_user_id,
157 gatekeeper::failure_record_t *record) {
158 std::string key = std::to_string(uid);
159 if (!CF_EXPECT(storage.HasKey(key))) {
160 auto data = CF_EXPECT(RecordToStorageData(DefaultRecord(secure_user_id)));
161 CF_EXPECT(storage.Write(key, *data));
162 }
163 auto record_read = CF_EXPECT(storage.Read(key));
164 auto record_decoded = CF_EXPECT(StorageDataToRecord(*record_read));
165 if (record_decoded.secure_user_id == secure_user_id) {
166 *record = record_decoded;
167 return {};
168 }
169 LOG(DEBUG) << "User id mismatch for " << uid;
170 auto record_to_write = DefaultRecord(secure_user_id);
171 auto data = CF_EXPECT(RecordToStorageData(record_to_write));
172 CF_EXPECT(storage.Write(key, *data));
173 *record = record_to_write;
174 return {};
175 }
176
GetFailureRecord(uint32_t uid,gatekeeper::secure_id_t secure_user_id,gatekeeper::failure_record_t * record,bool secure)177 bool TpmGatekeeper::GetFailureRecord(
178 uint32_t uid,
179 gatekeeper::secure_id_t secure_user_id,
180 gatekeeper::failure_record_t *record,
181 bool secure) {
182 secure_env::Storage& storage = secure ? secure_storage_ : insecure_storage_;
183 auto result = GetFailureRecordImpl(storage, uid, secure_user_id, record);
184 if (!result.ok()) {
185 LOG(ERROR) << "Failed to get failure record: "
186 << result.error().FormatForEnv();
187 }
188 return result.ok();
189 }
190
WriteFailureRecordImpl(secure_env::Storage & storage,uint32_t uid,gatekeeper::failure_record_t * record)191 static Result<void> WriteFailureRecordImpl(
192 secure_env::Storage& storage,
193 uint32_t uid,
194 gatekeeper::failure_record_t* record) {
195 std::string key = std::to_string(uid);
196 auto data = CF_EXPECT(RecordToStorageData(*record));
197 CF_EXPECT(storage.Write(key, *data));
198 return {};
199 }
200
ClearFailureRecord(uint32_t uid,gatekeeper::secure_id_t secure_user_id,bool secure)201 bool TpmGatekeeper::ClearFailureRecord(
202 uint32_t uid, gatekeeper::secure_id_t secure_user_id, bool secure) {
203 secure_env::Storage& storage = secure ? secure_storage_ : insecure_storage_;
204 gatekeeper::failure_record_t record = DefaultRecord(secure_user_id);
205 auto result = WriteFailureRecordImpl(storage, uid, &record);
206 if (!result.ok()) {
207 LOG(ERROR) << "Failed to clear failure record: "
208 << result.error().FormatForEnv();
209 }
210 return result.ok();
211 }
212
WriteFailureRecord(uint32_t uid,gatekeeper::failure_record_t * record,bool secure)213 bool TpmGatekeeper::WriteFailureRecord(
214 uint32_t uid, gatekeeper::failure_record_t *record, bool secure) {
215 secure_env::Storage& storage = secure ? secure_storage_ : insecure_storage_;
216 auto result = WriteFailureRecordImpl(storage, uid, record);
217 if (!result.ok()) {
218 LOG(ERROR) << "Failed to write failure record: "
219 << result.error().FormatForEnv();
220 }
221 return result.ok();
222 }
223
IsHardwareBacked() const224 bool TpmGatekeeper::IsHardwareBacked() const {
225 return true;
226 }
227
228 } // namespace cuttlefish
229