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