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 "host/commands/secure_env/tpm_keymaster_enforcement.h"
17
18 #include <android-base/logging.h>
19 #if defined(__BIONIC__)
20 #include <sys/endian.h> // for be64toh
21 #endif
22
23 #include "host/commands/secure_env/primary_key_builder.h"
24 #include "host/commands/secure_env/tpm_hmac.h"
25 #include "host/commands/secure_env/tpm_key_blob_maker.h"
26 #include "host/commands/secure_env/tpm_random_source.h"
27
28 using keymaster::km_id_t;
29 using keymaster::HmacSharingParameters;
30 using keymaster::HmacSharingParametersArray;
31 using keymaster::KeymasterBlob;
32 using keymaster::KeymasterEnforcement;
33 using keymaster::VerifyAuthorizationRequest;
34 using keymaster::VerifyAuthorizationResponse;
35 namespace {
operator ==(const keymaster_blob_t & a,const keymaster_blob_t & b)36 inline bool operator==(const keymaster_blob_t& a, const keymaster_blob_t& b) {
37 if (!a.data_length && !b.data_length) return true;
38 if (!(a.data && b.data)) return a.data == b.data;
39 return (a.data_length == b.data_length &&
40 !memcmp(a.data, b.data, a.data_length));
41 }
42
operator ==(const HmacSharingParameters & a,const HmacSharingParameters & b)43 bool operator==(const HmacSharingParameters& a,
44 const HmacSharingParameters& b) {
45 return a.seed == b.seed && !memcmp(a.nonce, b.nonce, sizeof(a.nonce));
46 }
47 } // namespace
48 class CompareHmacSharingParams {
49 public:
operator ()(const HmacSharingParameters & a,const HmacSharingParameters & b) const50 bool operator()(
51 const HmacSharingParameters& a, const HmacSharingParameters& b) const {
52 if (a.seed.data_length != b.seed.data_length) {
53 return a.seed.data_length < b.seed.data_length;
54 }
55 auto res = memcmp(a.seed.data, b.seed.data, a.seed.data_length);
56 if (res != 0) {
57 return res < 0;
58 }
59 static_assert(sizeof(a.nonce) == sizeof(b.nonce));
60 return memcmp(a.nonce, b.nonce, sizeof(a.nonce)) < 0;
61 }
62 };
63
64 namespace {
65
timespec_to_ms(const struct timespec & tp)66 uint64_t timespec_to_ms(const struct timespec& tp) {
67 if (tp.tv_sec < 0) {
68 return 0;
69 }
70 return static_cast<uint64_t>(tp.tv_sec) * 1000 +
71 static_cast<uint64_t>(tp.tv_nsec) / 1000000;
72 }
73
get_wall_clock_time_ms()74 uint64_t get_wall_clock_time_ms() {
75 struct timespec tp;
76 int err = clock_gettime(CLOCK_REALTIME, &tp);
77 if (err) {
78 return 0;
79 }
80 return timespec_to_ms(tp);
81 }
82
83 } // namespace
84
TpmKeymasterEnforcement(TpmResourceManager & resource_manager,TpmGatekeeper & gatekeeper)85 TpmKeymasterEnforcement::TpmKeymasterEnforcement(
86 TpmResourceManager& resource_manager, TpmGatekeeper& gatekeeper)
87 : KeymasterEnforcement(64, 64),
88 resource_manager_(resource_manager),
89 gatekeeper_(gatekeeper) {
90 }
91
~TpmKeymasterEnforcement()92 TpmKeymasterEnforcement::~TpmKeymasterEnforcement() {
93 }
94
activation_date_valid(uint64_t activation_date) const95 bool TpmKeymasterEnforcement::activation_date_valid(
96 uint64_t activation_date) const {
97 return activation_date < get_wall_clock_time_ms();
98 }
99
expiration_date_passed(uint64_t expiration_date) const100 bool TpmKeymasterEnforcement::expiration_date_passed(
101 uint64_t expiration_date) const {
102 return expiration_date > get_wall_clock_time_ms();
103 }
104
auth_token_timed_out(const hw_auth_token_t & token,uint32_t timeout) const105 bool TpmKeymasterEnforcement::auth_token_timed_out(
106 const hw_auth_token_t& token, uint32_t timeout) const {
107 // timeout comes in seconds, token.timestamp comes in milliseconds
108 uint64_t timeout_ms = 1000 * (uint64_t) timeout;
109 return (be64toh(token.timestamp) + timeout_ms) < get_current_time_ms();
110 }
111
get_current_time_ms() const112 uint64_t TpmKeymasterEnforcement::get_current_time_ms() const {
113 struct timespec tp;
114 int err = clock_gettime(CLOCK_BOOTTIME, &tp);
115 if (err) {
116 return 0;
117 }
118 return timespec_to_ms(tp);
119 }
120
SecurityLevel() const121 keymaster_security_level_t TpmKeymasterEnforcement::SecurityLevel() const {
122 return KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT;
123 }
124
ValidateTokenSignature(const hw_auth_token_t & token) const125 bool TpmKeymasterEnforcement::ValidateTokenSignature(
126 const hw_auth_token_t& token) const {
127 hw_auth_token_t comparison_token = token;
128 memset(comparison_token.hmac, 0, sizeof(comparison_token.hmac));
129
130 /*
131 * Should match implementation in system/gatekeeper/gatekeeper.cpp
132 * GateKeeper::MintAuthToken
133 */
134
135 const uint8_t *auth_token_key = nullptr;
136 uint32_t auth_token_key_len = 0;
137 if (!gatekeeper_.GetAuthTokenKey(&auth_token_key, &auth_token_key_len)) {
138 LOG(WARNING) << "Unable to get gatekeeper auth token";
139 return false;
140 }
141
142
143 constexpr uint32_t hashable_length = sizeof(token.version) +
144 sizeof(token.challenge) +
145 sizeof(token.user_id) +
146 sizeof(token.authenticator_id) +
147 sizeof(token.authenticator_type) +
148 sizeof(token.timestamp);
149
150 static_assert(
151 offsetof(hw_auth_token_t, hmac) == hashable_length,
152 "hw_auth_token_t does not appear to be packed");
153
154
155 gatekeeper_.ComputeSignature(
156 comparison_token.hmac,
157 sizeof(comparison_token.hmac),
158 auth_token_key,
159 auth_token_key_len,
160 reinterpret_cast<uint8_t*>(&comparison_token),
161 hashable_length);
162
163 static_assert(sizeof(token.hmac) == sizeof(comparison_token.hmac));
164
165 return memcmp(token.hmac, comparison_token.hmac, sizeof(token.hmac)) == 0;
166 }
167
GetHmacSharingParameters(HmacSharingParameters * params)168 keymaster_error_t TpmKeymasterEnforcement::GetHmacSharingParameters(
169 HmacSharingParameters* params) {
170 if (!have_saved_params_) {
171 saved_params_.seed = {};
172 TpmRandomSource random_source{resource_manager_.Esys()};
173 auto rc =
174 random_source.GenerateRandom(
175 saved_params_.nonce, sizeof(saved_params_.nonce));
176 if (rc != KM_ERROR_OK) {
177 LOG(ERROR) << "Failed to generate HmacSharingParameters nonce";
178 return rc;
179 }
180 have_saved_params_ = true;
181 }
182 params->seed = saved_params_.seed;
183 memcpy(params->nonce, saved_params_.nonce, sizeof(params->nonce));
184 return KM_ERROR_OK;
185 }
186
ComputeSharedHmac(const HmacSharingParametersArray & hmac_array,KeymasterBlob * sharingCheck)187 keymaster_error_t TpmKeymasterEnforcement::ComputeSharedHmac(
188 const HmacSharingParametersArray& hmac_array,
189 KeymasterBlob* sharingCheck) {
190 std::set<HmacSharingParameters, CompareHmacSharingParams> sorted_hmac_inputs;
191 bool found_mine = false;
192 for (int i = 0; i < hmac_array.num_params; i++) {
193 HmacSharingParameters sharing_params;
194 sharing_params.seed =
195 keymaster::KeymasterBlob(hmac_array.params_array[i].seed);
196 memcpy(
197 sharing_params.nonce,
198 hmac_array.params_array[i].nonce,
199 sizeof(sharing_params.nonce));
200 found_mine = found_mine || (sharing_params == saved_params_);
201 sorted_hmac_inputs.emplace(std::move(sharing_params));
202 }
203
204 if (!found_mine) return KM_ERROR_INVALID_ARGUMENT;
205
206 // unique data has a low maximum size, so combine the hmac parameters
207 char unique_data[] = "\0\0\0\0\0\0\0\0\0\0";
208 int unique_index = 0;
209 for (const auto& hmac_sharing : sorted_hmac_inputs) {
210 for (size_t j = 0; j < hmac_sharing.seed.data_length; j++) {
211 unique_data[unique_index % sizeof(unique_data)] ^=
212 hmac_sharing.seed.data[j];
213 unique_index++;
214 }
215 for (auto nonce_byte : hmac_sharing.nonce) {
216 unique_data[unique_index % sizeof(unique_data)] ^= nonce_byte;
217 unique_index++;
218 }
219 }
220
221
222 auto signing_key_builder = PrimaryKeyBuilder();
223 signing_key_builder.SigningKey();
224 signing_key_builder.UniqueData(std::string(unique_data, sizeof(unique_data)));
225 auto signing_key = signing_key_builder.CreateKey(resource_manager_);
226 if (!signing_key) {
227 LOG(ERROR) << "Could not make signing key for key id";
228 return KM_ERROR_UNKNOWN_ERROR;
229 }
230
231 static const uint8_t signing_input[] = "Keymaster HMAC Verification";
232
233 auto hmac = TpmHmac(
234 resource_manager_,
235 signing_key->get(),
236 TpmAuth(ESYS_TR_PASSWORD),
237 signing_input,
238 sizeof(signing_input));
239
240 if (!hmac) {
241 LOG(ERROR) << "Unable to complete signing check";
242 return KM_ERROR_UNKNOWN_ERROR;
243 }
244
245 *sharingCheck = KeymasterBlob(hmac->buffer, hmac->size);
246
247 return KM_ERROR_OK;
248 }
249
VerifyAuthorization(const VerifyAuthorizationRequest & request)250 VerifyAuthorizationResponse TpmKeymasterEnforcement::VerifyAuthorization(
251 const VerifyAuthorizationRequest& request) {
252 struct VerificationData {
253 uint64_t challenge;
254 uint64_t timestamp;
255 keymaster_security_level_t security_level;
256 };
257 VerifyAuthorizationResponse response(keymaster::kDefaultMessageVersion);
258 response.error = KM_ERROR_UNKNOWN_ERROR;
259 response.token.challenge = request.challenge;
260 response.token.timestamp = get_current_time_ms();
261 response.token.security_level = SecurityLevel();
262
263 VerificationData verify_data {
264 .challenge = response.token.challenge,
265 .timestamp = response.token.timestamp,
266 .security_level = response.token.security_level,
267 };
268
269 auto signing_key_builder = PrimaryKeyBuilder();
270 signing_key_builder.SigningKey();
271 signing_key_builder.UniqueData("verify_authorization");
272 auto signing_key = signing_key_builder.CreateKey(resource_manager_);
273 if (!signing_key) {
274 LOG(ERROR) << "Could not make signing key for verifying authorization";
275 return response;
276 }
277 auto hmac = TpmHmac(
278 resource_manager_,
279 signing_key->get(),
280 TpmAuth(ESYS_TR_PASSWORD),
281 reinterpret_cast<uint8_t*>(&verify_data),
282 sizeof(verify_data));
283
284 if (!hmac) {
285 LOG(ERROR) << "Could not calculate verification hmac";
286 return response;
287 } else if (hmac->size == 0) {
288 LOG(ERROR) << "hmac was too short";
289 return response;
290 }
291 response.token.mac = KeymasterBlob(hmac->buffer, hmac->size);
292 response.error = KM_ERROR_OK;
293
294 return response;
295 }
296
CreateKeyId(const keymaster_key_blob_t & key_blob,km_id_t * keyid) const297 bool TpmKeymasterEnforcement::CreateKeyId(
298 const keymaster_key_blob_t& key_blob, km_id_t* keyid) const {
299 keymaster::AuthorizationSet hw_enforced;
300 keymaster::AuthorizationSet sw_enforced;
301 keymaster::KeymasterKeyBlob key_material;
302 auto rc =
303 TpmKeyBlobMaker(resource_manager_)
304 .UnwrapKeyBlob(key_blob, &hw_enforced, &sw_enforced, &key_material);
305 if (rc != KM_ERROR_OK) {
306 LOG(ERROR) << "Could not unwrap key: " << rc;
307 return false;
308 }
309 auto signing_key_builder = PrimaryKeyBuilder();
310 signing_key_builder.SigningKey();
311 signing_key_builder.UniqueData("key_id");
312 auto signing_key = signing_key_builder.CreateKey(resource_manager_);
313 if (!signing_key) {
314 LOG(ERROR) << "Could not make signing key for key id";
315 return false;
316 }
317 auto hmac = TpmHmac(
318 resource_manager_,
319 signing_key->get(),
320 TpmAuth(ESYS_TR_PASSWORD),
321 key_material.key_material,
322 key_material.key_material_size);
323 if (!hmac) {
324 LOG(ERROR) << "Failed to make a signature for a key id";
325 return false;
326 }
327 if (hmac->size < sizeof(km_id_t)) {
328 LOG(ERROR) << "hmac return size was less than " << sizeof(km_id_t)
329 << ", got " << hmac->size;
330 return false;
331 }
332 memcpy(keyid, hmac->buffer, sizeof(km_id_t));
333 return true;
334 }
335