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