• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <optional>
20 #include <vector>
21 
22 #include <android-base/logging.h>
23 #include <tss2/tss2_esys.h>
24 #include <tss2/tss2_mu.h>
25 #include <tss2/tss2_rc.h>
26 
27 #include "host/commands/secure_env/primary_key_builder.h"
28 #include "host/commands/secure_env/tpm_auth.h"
29 #include "host/commands/secure_env/tpm_hmac.h"
30 #include "host/commands/secure_env/tpm_random_source.h"
31 
TpmGatekeeper(TpmResourceManager & resource_manager,GatekeeperStorage & secure_storage,GatekeeperStorage & insecure_storage)32 TpmGatekeeper::TpmGatekeeper(
33     TpmResourceManager& resource_manager,
34     GatekeeperStorage& secure_storage,
35     GatekeeperStorage& insecure_storage)
36     : resource_manager_(resource_manager)
37     , secure_storage_(secure_storage)
38     , insecure_storage_(insecure_storage) {
39 }
40 
41 /*
42  * The reinterpret_cast and kPasswordUnique data is combined together with TPM
43  * internal state to create the actual key used for Gatekeeper operations.
44  */
45 
GetAuthTokenKey(const uint8_t ** auth_token_key,uint32_t * length) const46 bool TpmGatekeeper::GetAuthTokenKey(
47     const uint8_t** auth_token_key, uint32_t* length) const {
48   static constexpr char kAuthTokenUnique[] = "TpmGatekeeper auth token key";
49   *auth_token_key = reinterpret_cast<const uint8_t*>(kAuthTokenUnique);
50   *length = sizeof(kAuthTokenUnique);
51   return true;
52 }
53 
GetPasswordKey(const uint8_t ** password_key,uint32_t * length)54 void TpmGatekeeper::GetPasswordKey(
55     const uint8_t** password_key, uint32_t* length) {
56   static constexpr char kPasswordUnique[] = "TpmGatekeeper password key";
57   *password_key = reinterpret_cast<const uint8_t*>(kPasswordUnique);
58   *length = sizeof(kPasswordUnique);
59 }
60 
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) const61 void TpmGatekeeper::ComputePasswordSignature(
62     uint8_t* signature,
63     uint32_t signature_length,
64     const uint8_t* key,
65     uint32_t key_length,
66     const uint8_t* password,
67     uint32_t password_length,
68     gatekeeper::salt_t salt) const {
69   std::vector<uint8_t> message(password_length + sizeof(salt));
70   memcpy(message.data(), password, password_length);
71   memcpy(message.data() + password_length, &salt, sizeof(salt));
72   return ComputeSignature(
73       signature,
74       signature_length,
75       key,
76       key_length,
77       message.data(),
78       message.size());
79 }
80 
GetRandom(void * random,uint32_t requested_size) const81 void TpmGatekeeper::GetRandom(void* random, uint32_t requested_size) const {
82   auto random_uint8 = reinterpret_cast<uint8_t*>(random);
83   TpmRandomSource(resource_manager_.Esys())
84       .GenerateRandom(random_uint8, requested_size);
85 }
86 
ComputeSignature(uint8_t * signature,uint32_t signature_length,const uint8_t * key,uint32_t key_length,const uint8_t * message,uint32_t length) const87 void TpmGatekeeper::ComputeSignature(
88     uint8_t* signature,
89     uint32_t signature_length,
90     const uint8_t* key,
91     uint32_t key_length,
92     const uint8_t* message,
93     uint32_t length) const {
94   memset(signature, 0, signature_length);
95   std::string key_unique(reinterpret_cast<const char*>(key), key_length);
96   PrimaryKeyBuilder key_builder;
97   key_builder.UniqueData(key_unique);
98   key_builder.SigningKey();
99   auto key_slot = key_builder.CreateKey(resource_manager_);
100   if (!key_slot) {
101     LOG(ERROR) << "Unable to load signing key into TPM memory";
102     return;
103   }
104   auto calculated_signature =
105       TpmHmac(
106           resource_manager_,
107           key_slot->get(),
108           TpmAuth(ESYS_TR_PASSWORD),
109           message,
110           length);
111   if (!calculated_signature) {
112     LOG(ERROR) << "Failure in calculating signature";
113     return;
114   }
115   memcpy(
116       signature,
117       calculated_signature->buffer,
118       std::min((int) calculated_signature->size, (int) signature_length));
119 }
120 
GetMillisecondsSinceBoot() const121 uint64_t TpmGatekeeper::GetMillisecondsSinceBoot() const {
122   struct timespec time;
123   int res = clock_gettime(CLOCK_BOOTTIME, &time);
124   if (res < 0) return 0;
125   return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000);
126 }
127 
DefaultRecord(gatekeeper::secure_id_t secure_user_id)128 gatekeeper::failure_record_t DefaultRecord(
129     gatekeeper::secure_id_t secure_user_id) {
130   return (gatekeeper::failure_record_t) {
131     .secure_user_id = secure_user_id,
132     .last_checked_timestamp = 0,
133     .failure_counter = 0,
134   };
135 }
136 
RecordToNvBuffer(const gatekeeper::failure_record_t & record)137 static std::unique_ptr<TPM2B_MAX_NV_BUFFER> RecordToNvBuffer(
138     const gatekeeper::failure_record_t& record) {
139   auto ret = std::make_unique<TPM2B_MAX_NV_BUFFER>();
140   static_assert(sizeof(ret->buffer) >= sizeof(record));
141   ret->size = sizeof(record);
142   std::memcpy(ret->buffer, &record, sizeof(record));
143   return ret;
144 }
145 
NvBufferToRecord(const TPM2B_MAX_NV_BUFFER & buffer)146 static std::optional<gatekeeper::failure_record_t> NvBufferToRecord(
147     const TPM2B_MAX_NV_BUFFER& buffer) {
148   gatekeeper::failure_record_t ret;
149   if (buffer.size != sizeof(ret)) {
150     LOG(ERROR) << "NV Buffer had an incorrect size.";
151     return {};
152   }
153   memcpy(&ret, buffer.buffer, sizeof(ret));
154   return ret;
155 }
156 
GetFailureRecordImpl(GatekeeperStorage & storage,uint32_t uid,gatekeeper::secure_id_t secure_user_id,gatekeeper::failure_record_t * record)157 static bool GetFailureRecordImpl(
158     GatekeeperStorage& storage,
159     uint32_t uid,
160     gatekeeper::secure_id_t secure_user_id,
161     gatekeeper::failure_record_t *record) {
162   Json::Value key{std::to_string(uid)}; // jsoncpp integer comparisons are janky
163   if (!storage.HasKey(key)) {
164     if (!storage.Allocate(key, sizeof(gatekeeper::failure_record_t))) {
165       LOG(ERROR) << "Allocation failed for user " << uid;
166       return false;
167     }
168     auto buf = RecordToNvBuffer(DefaultRecord(secure_user_id));
169     if (!storage.Write(key, *buf)) {
170       LOG(ERROR) << "Failed to write record for " << uid;
171       return false;
172     }
173   }
174   auto record_read = storage.Read(key);
175   if (!record_read) {
176     LOG(ERROR) << "Failed to read record for " << uid;
177     return false;
178   }
179   auto record_decoded = NvBufferToRecord(*record_read);
180   if (!record_decoded) {
181     LOG(ERROR) << "Failed to deserialize record for " << uid;
182     return false;
183   }
184   if (record_decoded->secure_user_id == secure_user_id) {
185     *record = *record_decoded;
186     return true;
187   }
188   LOG(DEBUG) << "User id mismatch for " << uid;
189   auto buf = RecordToNvBuffer(DefaultRecord(secure_user_id));
190   if (!storage.Write(key, *buf)) {
191     LOG(ERROR) << "Failed to write record for " << uid;
192     return false;
193   }
194   *record = DefaultRecord(secure_user_id);
195   return true;
196 }
197 
GetFailureRecord(uint32_t uid,gatekeeper::secure_id_t secure_user_id,gatekeeper::failure_record_t * record,bool secure)198 bool TpmGatekeeper::GetFailureRecord(
199     uint32_t uid,
200     gatekeeper::secure_id_t secure_user_id,
201     gatekeeper::failure_record_t *record,
202     bool secure) {
203   GatekeeperStorage& storage = secure ? secure_storage_ : insecure_storage_;
204   return GetFailureRecordImpl(storage, uid, secure_user_id, record);
205 }
206 
WriteFailureRecordImpl(GatekeeperStorage & storage,uint32_t uid,gatekeeper::failure_record_t * record)207 static bool WriteFailureRecordImpl(
208     GatekeeperStorage& storage,
209     uint32_t uid,
210     gatekeeper::failure_record_t* record) {
211   Json::Value key{std::to_string(uid)}; // jsoncpp integer comparisons are janky
212   if (!storage.HasKey(key)) {
213     if (!storage.Allocate(key, sizeof(gatekeeper::failure_record_t))) {
214       LOG(ERROR) << "Allocation failed for user " << uid;
215       return false;
216     }
217   }
218   auto buf = RecordToNvBuffer(*record);
219   if (!storage.Write(key, *buf)) {
220     LOG(ERROR) << "Failed to write record for " << uid;
221     return false;
222   }
223   return true;
224 }
225 
ClearFailureRecord(uint32_t uid,gatekeeper::secure_id_t secure_user_id,bool secure)226 bool TpmGatekeeper::ClearFailureRecord(
227     uint32_t uid, gatekeeper::secure_id_t secure_user_id, bool secure) {
228   GatekeeperStorage& storage = secure ? secure_storage_ : insecure_storage_;
229   gatekeeper::failure_record_t record = DefaultRecord(secure_user_id);
230   return WriteFailureRecordImpl(storage, uid, &record);
231 }
232 
WriteFailureRecord(uint32_t uid,gatekeeper::failure_record_t * record,bool secure)233 bool TpmGatekeeper::WriteFailureRecord(
234     uint32_t uid, gatekeeper::failure_record_t *record, bool secure) {
235   GatekeeperStorage& storage = secure ? secure_storage_ : insecure_storage_;
236   return WriteFailureRecordImpl(storage, uid, record);
237 }
238 
IsHardwareBacked() const239 bool TpmGatekeeper::IsHardwareBacked() const {
240   return true;
241 }
242 
243