1 /*
2 * Copyright (c) 2019, 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
17 #define LOG_TAG "credstore"
18
19 #include <chrono>
20
21 #include <fcntl.h>
22 #include <stdlib.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26
27 #include <android-base/logging.h>
28 #include <android-base/stringprintf.h>
29
30 #include <cppbor.h>
31 #include <cppbor_parse.h>
32
33 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
34
35 #include "CredentialData.h"
36 #include "Util.h"
37
38 namespace android {
39 namespace security {
40 namespace identity {
41
42 using std::optional;
43
calculateCredentialFileName(const string & dataPath,uid_t ownerUid,const string & name)44 string CredentialData::calculateCredentialFileName(const string& dataPath, uid_t ownerUid,
45 const string& name) {
46 return android::base::StringPrintf(
47 "%s/%d-%s", dataPath.c_str(), (int)ownerUid,
48 android::hardware::identity::support::encodeHex(name).c_str());
49 }
50
CredentialData(const string & dataPath,uid_t ownerUid,const string & name)51 CredentialData::CredentialData(const string& dataPath, uid_t ownerUid, const string& name)
52 : dataPath_(dataPath), ownerUid_(ownerUid), name_(name), secureUserId_(0) {
53 fileName_ = calculateCredentialFileName(dataPath_, ownerUid_, name_);
54 }
55
setSecureUserId(int64_t secureUserId)56 void CredentialData::setSecureUserId(int64_t secureUserId) {
57 secureUserId_ = secureUserId;
58 }
59
setCredentialData(const vector<uint8_t> & credentialData)60 void CredentialData::setCredentialData(const vector<uint8_t>& credentialData) {
61 credentialData_ = credentialData;
62 }
63
setAttestationCertificate(const vector<uint8_t> & attestationCertificate)64 void CredentialData::setAttestationCertificate(const vector<uint8_t>& attestationCertificate) {
65 attestationCertificate_ = attestationCertificate;
66 }
67
addSecureAccessControlProfile(const SecureAccessControlProfile & secureAccessControlProfile)68 void CredentialData::addSecureAccessControlProfile(
69 const SecureAccessControlProfile& secureAccessControlProfile) {
70 secureAccessControlProfiles_.push_back(secureAccessControlProfile);
71 }
72
addEntryData(const string & namespaceName,const string & entryName,const EntryData & data)73 void CredentialData::addEntryData(const string& namespaceName, const string& entryName,
74 const EntryData& data) {
75 idToEncryptedChunks_[namespaceName + ":" + entryName] = data;
76 }
77
saveToDisk() const78 bool CredentialData::saveToDisk() const {
79 cppbor::Map map;
80
81 map.add("secureUserId", secureUserId_);
82
83 map.add("credentialData", credentialData_);
84
85 map.add("attestationCertificate", attestationCertificate_);
86
87 cppbor::Array sacpArray;
88 for (const SecureAccessControlProfile& sacp : secureAccessControlProfiles_) {
89 cppbor::Array array;
90 array.add(sacp.id);
91 array.add(sacp.readerCertificate.encodedCertificate);
92 array.add(sacp.userAuthenticationRequired);
93 array.add(sacp.timeoutMillis);
94 array.add(sacp.secureUserId);
95 vector<uint8_t> mac = sacp.mac;
96 array.add(mac);
97 sacpArray.add(std::move(array));
98 }
99 map.add("secureAccessControlProfiles", std::move(sacpArray));
100
101 cppbor::Map encryptedBlobsMap;
102 for (auto const& [nsAndName, entryData] : idToEncryptedChunks_) {
103 cppbor::Array encryptedChunkArray;
104 for (const vector<uint8_t>& encryptedChunk : entryData.encryptedChunks) {
105 encryptedChunkArray.add(encryptedChunk);
106 }
107 cppbor::Array entryDataArray;
108 entryDataArray.add(entryData.size);
109 cppbor::Array idsArray;
110 for (int32_t id : entryData.accessControlProfileIds) {
111 idsArray.add(id);
112 }
113 entryDataArray.add(std::move(idsArray));
114 entryDataArray.add(std::move(encryptedChunkArray));
115 encryptedBlobsMap.add(nsAndName, std::move(entryDataArray));
116 }
117 map.add("entryData", std::move(encryptedBlobsMap));
118 map.add("authKeyCount", keyCount_);
119 map.add("maxUsesPerAuthKey", maxUsesPerKey_);
120 map.add("minValidTimeMillis", minValidTimeMillis_);
121
122 cppbor::Array authKeyDatasArray;
123 for (const AuthKeyData& data : authKeyDatas_) {
124 cppbor::Array array;
125 // Fields 0-6 was in the original version in Android 11
126 array.add(data.certificate);
127 array.add(data.keyBlob);
128 array.add(data.staticAuthenticationData);
129 array.add(data.pendingCertificate);
130 array.add(data.pendingKeyBlob);
131 array.add(data.useCount);
132 // Field 7 was added in Android 12
133 array.add(data.expirationDateMillisSinceEpoch);
134 authKeyDatasArray.add(std::move(array));
135 }
136 map.add("authKeyData", std::move(authKeyDatasArray));
137
138 vector<uint8_t> credentialData = map.encode();
139
140 return fileSetContents(fileName_, credentialData);
141 }
142
parseSacp(const cppbor::Item & item)143 optional<SecureAccessControlProfile> parseSacp(const cppbor::Item& item) {
144 const cppbor::Array* array = item.asArray();
145 if (array == nullptr || array->size() < 6) {
146 LOG(ERROR) << "The SACP CBOR is not an array with at least six elements (size="
147 << (array != nullptr ? array->size() : -1) << ")";
148 return {};
149 }
150 const cppbor::Int* itemId = ((*array)[0])->asInt();
151 const cppbor::Bstr* itemReaderCertificate = ((*array)[1])->asBstr();
152 const cppbor::Simple* simple = ((*array)[2])->asSimple();
153 const cppbor::Bool* itemUserAuthenticationRequired =
154 (simple != nullptr ? (simple->asBool()) : nullptr);
155 const cppbor::Int* itemTimeoutMillis = ((*array)[3])->asInt();
156 const cppbor::Int* itesecureUserId_ = ((*array)[4])->asInt();
157 const cppbor::Bstr* itemMac = ((*array)[5])->asBstr();
158 if (itemId == nullptr || itemReaderCertificate == nullptr ||
159 itemUserAuthenticationRequired == nullptr || itemTimeoutMillis == nullptr ||
160 itesecureUserId_ == nullptr || itemMac == nullptr) {
161 LOG(ERROR) << "One or more items SACP array in CBOR is of wrong type";
162 return {};
163 }
164 SecureAccessControlProfile sacp;
165 sacp.id = itemId->value();
166 sacp.readerCertificate.encodedCertificate = itemReaderCertificate->value();
167 sacp.userAuthenticationRequired = itemUserAuthenticationRequired->value();
168 sacp.timeoutMillis = itemTimeoutMillis->value();
169 sacp.secureUserId = itesecureUserId_->value();
170 sacp.mac = itemMac->value();
171 return sacp;
172 }
173
parseAuthKeyData(const cppbor::Item & item)174 optional<AuthKeyData> parseAuthKeyData(const cppbor::Item& item) {
175 const cppbor::Array* array = item.asArray();
176 if (array == nullptr || array->size() < 6) {
177 LOG(ERROR) << "The AuthKeyData CBOR is not an array with at least six elements";
178 return {};
179 }
180 const cppbor::Bstr* itemCertificate = ((*array)[0])->asBstr();
181 const cppbor::Bstr* itemKeyBlob = ((*array)[1])->asBstr();
182 const cppbor::Bstr* itemStaticAuthenticationData = ((*array)[2])->asBstr();
183 const cppbor::Bstr* itemPendingCertificate = ((*array)[3])->asBstr();
184 const cppbor::Bstr* itemPendingKeyBlob = ((*array)[4])->asBstr();
185 const cppbor::Int* itemUseCount = ((*array)[5])->asInt();
186 if (itemCertificate == nullptr || itemKeyBlob == nullptr ||
187 itemStaticAuthenticationData == nullptr || itemPendingCertificate == nullptr ||
188 itemPendingKeyBlob == nullptr || itemUseCount == nullptr) {
189 LOG(ERROR) << "One or more items in AuthKeyData array in CBOR is of wrong type";
190 return {};
191 }
192 // expirationDateMillisSinceEpoch was added as the 7th element for Android 12. If not
193 // present, default to longest possible expiration date.
194 int64_t expirationDateMillisSinceEpoch = INT64_MAX;
195 if (array->size() >= 7) {
196 const cppbor::Int* itemExpirationDateMillisSinceEpoch = ((*array)[6])->asInt();
197 expirationDateMillisSinceEpoch = itemExpirationDateMillisSinceEpoch->value();
198 }
199 AuthKeyData authKeyData;
200 authKeyData.certificate = itemCertificate->value();
201 authKeyData.keyBlob = itemKeyBlob->value();
202 authKeyData.expirationDateMillisSinceEpoch = expirationDateMillisSinceEpoch;
203 authKeyData.staticAuthenticationData = itemStaticAuthenticationData->value();
204 authKeyData.pendingCertificate = itemPendingCertificate->value();
205 authKeyData.pendingKeyBlob = itemPendingKeyBlob->value();
206 authKeyData.useCount = itemUseCount->value();
207 return authKeyData;
208 }
209
parseAccessControlProfileIds(const cppbor::Item & item)210 vector<int32_t> parseAccessControlProfileIds(const cppbor::Item& item) {
211 const cppbor::Array* array = item.asArray();
212 if (array == nullptr) {
213 LOG(ERROR) << "The accessControlProfileIds member is not an array";
214 return {};
215 }
216
217 vector<int32_t> accessControlProfileIds;
218 for (size_t n = 0; n < array->size(); n++) {
219 const cppbor::Int* itemInt = ((*array)[n])->asInt();
220 if (itemInt == nullptr) {
221 LOG(ERROR) << "An item in the accessControlProfileIds array is not a bstr";
222 return {};
223 }
224 accessControlProfileIds.push_back(itemInt->value());
225 }
226 return accessControlProfileIds;
227 }
228
parseEncryptedChunks(const cppbor::Item & item)229 optional<vector<vector<uint8_t>>> parseEncryptedChunks(const cppbor::Item& item) {
230 const cppbor::Array* array = item.asArray();
231 if (array == nullptr) {
232 LOG(ERROR) << "The encryptedChunks member is not an array";
233 return {};
234 }
235
236 vector<vector<uint8_t>> encryptedChunks;
237 for (size_t n = 0; n < array->size(); n++) {
238 const cppbor::Bstr* itemBstr = ((*array)[n])->asBstr();
239 if (itemBstr == nullptr) {
240 LOG(ERROR) << "An item in the encryptedChunks array is not a bstr";
241 return {};
242 }
243 encryptedChunks.push_back(itemBstr->value());
244 }
245 return encryptedChunks;
246 }
247
loadFromDisk()248 bool CredentialData::loadFromDisk() {
249 // Reset all data.
250 credentialData_.clear();
251 attestationCertificate_.clear();
252 secureAccessControlProfiles_.clear();
253 idToEncryptedChunks_.clear();
254 authKeyDatas_.clear();
255 keyCount_ = 0;
256 maxUsesPerKey_ = 1;
257 minValidTimeMillis_ = 0;
258
259 optional<vector<uint8_t>> data = fileGetContents(fileName_);
260 if (!data) {
261 LOG(ERROR) << "Error loading data";
262 return false;
263 }
264
265 auto [item, _ /* newPos */, message] = cppbor::parse(data.value());
266 if (item == nullptr) {
267 LOG(ERROR) << "Data loaded from " << fileName_ << " is not valid CBOR: " << message;
268 return false;
269 }
270
271 const cppbor::Map* map = item->asMap();
272 if (map == nullptr) {
273 LOG(ERROR) << "Top-level item is not a map";
274 return false;
275 }
276
277 for (size_t n = 0; n < map->size(); n++) {
278 auto& [keyItem, valueItem] = (*map)[n];
279 const cppbor::Tstr* tstr = keyItem->asTstr();
280 if (tstr == nullptr) {
281 LOG(ERROR) << "Key item in top-level map is not a tstr";
282 return false;
283 }
284 const string& key = tstr->value();
285
286 if (key == "secureUserId") {
287 const cppbor::Int* number = valueItem->asInt();
288 if (number == nullptr) {
289 LOG(ERROR) << "Value for secureUserId is not a number";
290 return false;
291 }
292 secureUserId_ = number->value();
293 } else if (key == "credentialData") {
294 const cppbor::Bstr* valueBstr = valueItem->asBstr();
295 if (valueBstr == nullptr) {
296 LOG(ERROR) << "Value for credentialData is not a bstr";
297 return false;
298 }
299 credentialData_ = valueBstr->value();
300 } else if (key == "attestationCertificate") {
301 const cppbor::Bstr* valueBstr = valueItem->asBstr();
302 if (valueBstr == nullptr) {
303 LOG(ERROR) << "Value for attestationCertificate is not a bstr";
304 return false;
305 }
306 attestationCertificate_ = valueBstr->value();
307 } else if (key == "secureAccessControlProfiles") {
308 const cppbor::Array* array = valueItem->asArray();
309 if (array == nullptr) {
310 LOG(ERROR) << "Value for attestationCertificate is not an array";
311 return false;
312 }
313 for (size_t m = 0; m < array->size(); m++) {
314 const std::unique_ptr<cppbor::Item>& item = (*array)[m];
315 optional<SecureAccessControlProfile> sacp = parseSacp(*item);
316 if (!sacp) {
317 LOG(ERROR) << "Error parsing SecureAccessControlProfile";
318 return false;
319 }
320 secureAccessControlProfiles_.push_back(sacp.value());
321 }
322
323 } else if (key == "entryData") {
324 const cppbor::Map* map = valueItem->asMap();
325 if (map == nullptr) {
326 LOG(ERROR) << "Value for encryptedChunks is not an map";
327 return false;
328 }
329 for (size_t m = 0; m < map->size(); m++) {
330 auto& [ecKeyItem, ecValueItem] = (*map)[m];
331 const cppbor::Tstr* ecTstr = ecKeyItem->asTstr();
332 if (ecTstr == nullptr) {
333 LOG(ERROR) << "Key item in encryptedChunks map is not a tstr";
334 return false;
335 }
336 const string& ecId = ecTstr->value();
337
338 const cppbor::Array* ecEntryArrayItem = ecValueItem->asArray();
339 if (ecEntryArrayItem == nullptr || ecEntryArrayItem->size() < 3) {
340 LOG(ERROR) << "Value item in encryptedChunks map is an array with at least two "
341 "elements";
342 return false;
343 }
344 const cppbor::Int* ecEntrySizeItem = (*ecEntryArrayItem)[0]->asInt();
345 if (ecEntrySizeItem == nullptr) {
346 LOG(ERROR) << "Entry size not a number";
347 return false;
348 }
349 uint64_t entrySize = ecEntrySizeItem->value();
350
351 optional<vector<int32_t>> accessControlProfileIds =
352 parseAccessControlProfileIds(*(*ecEntryArrayItem)[1]);
353 if (!accessControlProfileIds) {
354 LOG(ERROR) << "Error parsing access control profile ids";
355 return false;
356 }
357
358 optional<vector<vector<uint8_t>>> encryptedChunks =
359 parseEncryptedChunks(*(*ecEntryArrayItem)[2]);
360 if (!encryptedChunks) {
361 LOG(ERROR) << "Error parsing encrypted chunks";
362 return false;
363 }
364
365 EntryData data;
366 data.size = entrySize;
367 data.accessControlProfileIds = accessControlProfileIds.value();
368 data.encryptedChunks = encryptedChunks.value();
369 idToEncryptedChunks_[ecId] = data;
370 }
371
372 } else if (key == "authKeyData") {
373 const cppbor::Array* array = valueItem->asArray();
374 if (array == nullptr) {
375 LOG(ERROR) << "Value for authData is not an array";
376 return false;
377 }
378 for (size_t m = 0; m < array->size(); m++) {
379 const std::unique_ptr<cppbor::Item>& item = (*array)[m];
380 optional<AuthKeyData> authKeyData = parseAuthKeyData(*item);
381 if (!authKeyData) {
382 LOG(ERROR) << "Error parsing AuthKeyData";
383 return false;
384 }
385 authKeyDatas_.push_back(authKeyData.value());
386 }
387
388 } else if (key == "authKeyCount") {
389 const cppbor::Int* number = valueItem->asInt();
390 if (number == nullptr) {
391 LOG(ERROR) << "Value for authKeyCount is not a number";
392 return false;
393 }
394 keyCount_ = number->value();
395
396 } else if (key == "maxUsesPerAuthKey") {
397 const cppbor::Int* number = valueItem->asInt();
398 if (number == nullptr) {
399 LOG(ERROR) << "Value for maxUsesPerAuthKey is not a number";
400 return false;
401 }
402 maxUsesPerKey_ = number->value();
403
404 } else if (key == "minValidTimeMillis") {
405 const cppbor::Int* number = valueItem->asInt();
406 if (number == nullptr) {
407 LOG(ERROR) << "Value for minValidTimeMillis is not a number";
408 return false;
409 }
410 minValidTimeMillis_ = number->value();
411 }
412 }
413
414 if (credentialData_.size() == 0) {
415 LOG(ERROR) << "Missing credentialData";
416 return false;
417 }
418
419 if (attestationCertificate_.size() == 0) {
420 LOG(ERROR) << "Missing attestationCertificate";
421 return false;
422 }
423
424 if (size_t(keyCount_) != authKeyDatas_.size()) {
425 LOG(ERROR) << "keyCount_=" << keyCount_
426 << " != authKeyDatas_.size()=" << authKeyDatas_.size();
427 return false;
428 }
429
430 return true;
431 }
432
getCredentialData() const433 const vector<uint8_t>& CredentialData::getCredentialData() const {
434 return credentialData_;
435 }
436
getSecureUserId()437 int64_t CredentialData::getSecureUserId() {
438 return secureUserId_;
439 }
440
getAttestationCertificate() const441 const vector<uint8_t>& CredentialData::getAttestationCertificate() const {
442 return attestationCertificate_;
443 }
444
getSecureAccessControlProfiles() const445 const vector<SecureAccessControlProfile>& CredentialData::getSecureAccessControlProfiles() const {
446 return secureAccessControlProfiles_;
447 }
448
hasEntryData(const string & namespaceName,const string & entryName) const449 bool CredentialData::hasEntryData(const string& namespaceName, const string& entryName) const {
450 string id = namespaceName + ":" + entryName;
451 auto iter = idToEncryptedChunks_.find(id);
452 if (iter == idToEncryptedChunks_.end()) {
453 return false;
454 }
455 return true;
456 }
457
getEntryData(const string & namespaceName,const string & entryName) const458 optional<EntryData> CredentialData::getEntryData(const string& namespaceName,
459 const string& entryName) const {
460 string id = namespaceName + ":" + entryName;
461 auto iter = idToEncryptedChunks_.find(id);
462 if (iter == idToEncryptedChunks_.end()) {
463 return {};
464 }
465 return iter->second;
466 }
467
deleteCredential()468 bool CredentialData::deleteCredential() {
469 if (unlink(fileName_.c_str()) != 0) {
470 PLOG(ERROR) << "Error deleting " << fileName_;
471 return false;
472 }
473 return true;
474 }
475
credentialExists(const string & dataPath,uid_t ownerUid,const string & name)476 optional<bool> CredentialData::credentialExists(const string& dataPath, uid_t ownerUid,
477 const string& name) {
478 struct stat statbuf;
479 string filename = calculateCredentialFileName(dataPath, ownerUid, name);
480 if (stat(filename.c_str(), &statbuf) != 0) {
481 if (errno == ENOENT) {
482 return false;
483 }
484 PLOG(ERROR) << "Error getting information about " << filename;
485 return {};
486 }
487 return true;
488 }
489
490 // ---
491
setAvailableAuthenticationKeys(int keyCount,int maxUsesPerKey,int64_t minValidTimeMillis)492 void CredentialData::setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey,
493 int64_t minValidTimeMillis) {
494 keyCount_ = keyCount;
495 maxUsesPerKey_ = maxUsesPerKey;
496 minValidTimeMillis_ = minValidTimeMillis;
497
498 // If growing the number of auth keys (prevKeyCount < keyCount_ case) we'll add
499 // new AuthKeyData structs to |authKeyDatas_| and each struct will have empty |certificate|
500 // and |pendingCertificate| fields. Those will be filled out when the
501 // getAuthKeysNeedingCertification() is called.
502 //
503 // If shrinking, we'll just delete the AuthKeyData structs at the end. There's nothing
504 // else to do, the HAL doesn't need to know we're nuking these authentication keys.
505 //
506 // Therefore, in either case it's as simple as just resizing the vector.
507 authKeyDatas_.resize(keyCount_);
508 }
509
getAuthKeyDatas() const510 const vector<AuthKeyData>& CredentialData::getAuthKeyDatas() const {
511 return authKeyDatas_;
512 }
513
514 tuple<int /* keyCount */, int /*maxUsersPerKey */, int64_t /* minValidTimeMillis */>
getAvailableAuthenticationKeys() const515 CredentialData::getAvailableAuthenticationKeys() const {
516 return std::make_tuple(keyCount_, maxUsesPerKey_, minValidTimeMillis_);
517 }
518
findAuthKey_(bool allowUsingExhaustedKeys,bool allowUsingExpiredKeys)519 AuthKeyData* CredentialData::findAuthKey_(bool allowUsingExhaustedKeys,
520 bool allowUsingExpiredKeys) {
521 AuthKeyData* candidate = nullptr;
522
523 time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
524 int64_t nowMilliSeconds;
525 if (__builtin_mul_overflow(int64_t(now), int64_t(1000), &nowMilliSeconds)) {
526 LOG(ERROR) << "Overflow converting " << now << " to milliseconds";
527 return nullptr;
528 }
529
530 for (AuthKeyData& data : authKeyDatas_) {
531 if (nowMilliSeconds > data.expirationDateMillisSinceEpoch) {
532 if (!allowUsingExpiredKeys) {
533 continue;
534 }
535 }
536 if (data.certificate.size() != 0) {
537 // Not expired, include in normal check
538 if (candidate == nullptr || data.useCount < candidate->useCount) {
539 candidate = &data;
540 }
541 }
542 }
543
544 if (candidate == nullptr) {
545 return nullptr;
546 }
547
548 if (candidate->useCount >= maxUsesPerKey_ && !allowUsingExhaustedKeys) {
549 return nullptr;
550 }
551
552 return candidate;
553 }
554
selectAuthKey(bool allowUsingExhaustedKeys,bool allowUsingExpiredKeys,bool incrementUsageCount)555 const AuthKeyData* CredentialData::selectAuthKey(bool allowUsingExhaustedKeys,
556 bool allowUsingExpiredKeys,
557 bool incrementUsageCount) {
558 AuthKeyData* candidate;
559
560 // First try to find a un-expired key..
561 candidate = findAuthKey_(allowUsingExhaustedKeys, false);
562 if (candidate == nullptr) {
563 // That didn't work, there are no un-expired keys and we don't allow using expired keys.
564 if (!allowUsingExpiredKeys) {
565 return nullptr;
566 }
567
568 // See if there's an expired key then...
569 candidate = findAuthKey_(allowUsingExhaustedKeys, true);
570 if (candidate == nullptr) {
571 return nullptr;
572 }
573 }
574
575 if (incrementUsageCount) {
576 candidate->useCount += 1;
577 }
578 return candidate;
579 }
580
581 optional<vector<vector<uint8_t>>>
getAuthKeysNeedingCertification(const sp<IIdentityCredential> & halBinder)582 CredentialData::getAuthKeysNeedingCertification(const sp<IIdentityCredential>& halBinder) {
583
584 vector<vector<uint8_t>> keysNeedingCert;
585
586 time_t now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
587 int64_t nowMilliseconds;
588 if (__builtin_mul_overflow(int64_t(now), int64_t(1000), &nowMilliseconds)) {
589 LOG(ERROR) << "Overflow converting " << now << " to milliseconds";
590 return {};
591 }
592
593 for (AuthKeyData& data : authKeyDatas_) {
594 bool keyExceedUseCount = (data.useCount >= maxUsesPerKey_);
595 int64_t expirationDateAdjusted = data.expirationDateMillisSinceEpoch - minValidTimeMillis_;
596 bool keyBeyondAdjustedExpirationDate = (nowMilliseconds > expirationDateAdjusted);
597 bool newKeyNeeded =
598 (data.certificate.size() == 0) || keyExceedUseCount || keyBeyondAdjustedExpirationDate;
599 bool certificationPending = (data.pendingCertificate.size() > 0);
600 if (newKeyNeeded && !certificationPending) {
601 vector<uint8_t> signingKeyBlob;
602 Certificate signingKeyCertificate;
603 if (!halBinder->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate)
604 .isOk()) {
605 LOG(ERROR) << "Error generating signing key-pair";
606 return {};
607 }
608 data.pendingCertificate = signingKeyCertificate.encodedCertificate;
609 data.pendingKeyBlob = signingKeyBlob;
610 certificationPending = true;
611 }
612
613 if (certificationPending) {
614 keysNeedingCert.push_back(data.pendingCertificate);
615 }
616 }
617 return keysNeedingCert;
618 }
619
storeStaticAuthenticationData(const vector<uint8_t> & authenticationKey,int64_t expirationDateMillisSinceEpoch,const vector<uint8_t> & staticAuthData)620 bool CredentialData::storeStaticAuthenticationData(const vector<uint8_t>& authenticationKey,
621 int64_t expirationDateMillisSinceEpoch,
622 const vector<uint8_t>& staticAuthData) {
623 for (AuthKeyData& data : authKeyDatas_) {
624 if (data.pendingCertificate == authenticationKey) {
625 data.certificate = data.pendingCertificate;
626 data.keyBlob = data.pendingKeyBlob;
627 data.expirationDateMillisSinceEpoch = expirationDateMillisSinceEpoch;
628 data.staticAuthenticationData = staticAuthData;
629 data.pendingCertificate.clear();
630 data.pendingKeyBlob.clear();
631 data.useCount = 0;
632 return true;
633 }
634 }
635 return false;
636 }
637
638 } // namespace identity
639 } // namespace security
640 } // namespace android
641