• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
121     cppbor::Array authKeyDatasArray;
122     for (const AuthKeyData& data : authKeyDatas_) {
123         cppbor::Array array;
124         // Fields 0-6 was in the original version in Android 11
125         array.add(data.certificate);
126         array.add(data.keyBlob);
127         array.add(data.staticAuthenticationData);
128         array.add(data.pendingCertificate);
129         array.add(data.pendingKeyBlob);
130         array.add(data.useCount);
131         // Field 7 was added in Android 12
132         array.add(data.expirationDateMillisSinceEpoch);
133         authKeyDatasArray.add(std::move(array));
134     }
135     map.add("authKeyData", std::move(authKeyDatasArray));
136 
137     vector<uint8_t> credentialData = map.encode();
138 
139     return fileSetContents(fileName_, credentialData);
140 }
141 
parseSacp(const cppbor::Item & item)142 optional<SecureAccessControlProfile> parseSacp(const cppbor::Item& item) {
143     const cppbor::Array* array = item.asArray();
144     if (array == nullptr || array->size() < 6) {
145         LOG(ERROR) << "The SACP CBOR is not an array with at least six elements (size="
146                    << (array != nullptr ? array->size() : -1) << ")";
147         return {};
148     }
149     const cppbor::Int* itemId = ((*array)[0])->asInt();
150     const cppbor::Bstr* itemReaderCertificate = ((*array)[1])->asBstr();
151     const cppbor::Simple* simple = ((*array)[2])->asSimple();
152     const cppbor::Bool* itemUserAuthenticationRequired =
153         (simple != nullptr ? (simple->asBool()) : nullptr);
154     const cppbor::Int* itemTimeoutMillis = ((*array)[3])->asInt();
155     const cppbor::Int* itesecureUserId_ = ((*array)[4])->asInt();
156     const cppbor::Bstr* itemMac = ((*array)[5])->asBstr();
157     if (itemId == nullptr || itemReaderCertificate == nullptr ||
158         itemUserAuthenticationRequired == nullptr || itemTimeoutMillis == nullptr ||
159         itesecureUserId_ == nullptr || itemMac == nullptr) {
160         LOG(ERROR) << "One or more items SACP array in CBOR is of wrong type";
161         return {};
162     }
163     SecureAccessControlProfile sacp;
164     sacp.id = itemId->value();
165     sacp.readerCertificate.encodedCertificate = itemReaderCertificate->value();
166     sacp.userAuthenticationRequired = itemUserAuthenticationRequired->value();
167     sacp.timeoutMillis = itemTimeoutMillis->value();
168     sacp.secureUserId = itesecureUserId_->value();
169     sacp.mac = itemMac->value();
170     return sacp;
171 }
172 
parseAuthKeyData(const cppbor::Item & item)173 optional<AuthKeyData> parseAuthKeyData(const cppbor::Item& item) {
174     const cppbor::Array* array = item.asArray();
175     if (array == nullptr || array->size() < 6) {
176         LOG(ERROR) << "The AuthKeyData CBOR is not an array with at least six elements";
177         return {};
178     }
179     const cppbor::Bstr* itemCertificate = ((*array)[0])->asBstr();
180     const cppbor::Bstr* itemKeyBlob = ((*array)[1])->asBstr();
181     const cppbor::Bstr* itemStaticAuthenticationData = ((*array)[2])->asBstr();
182     const cppbor::Bstr* itemPendingCertificate = ((*array)[3])->asBstr();
183     const cppbor::Bstr* itemPendingKeyBlob = ((*array)[4])->asBstr();
184     const cppbor::Int* itemUseCount = ((*array)[5])->asInt();
185     if (itemCertificate == nullptr || itemKeyBlob == nullptr ||
186         itemStaticAuthenticationData == nullptr || itemPendingCertificate == nullptr ||
187         itemPendingKeyBlob == nullptr || itemUseCount == nullptr) {
188         LOG(ERROR) << "One or more items in AuthKeyData array in CBOR is of wrong type";
189         return {};
190     }
191     // expirationDateMillisSinceEpoch was added as the 7th element for Android 12. If not
192     // present, default to longest possible expiration date.
193     int64_t expirationDateMillisSinceEpoch = INT64_MAX;
194     if (array->size() >= 7) {
195         const cppbor::Int* itemExpirationDateMillisSinceEpoch = ((*array)[6])->asInt();
196         expirationDateMillisSinceEpoch = itemExpirationDateMillisSinceEpoch->value();
197     }
198     AuthKeyData authKeyData;
199     authKeyData.certificate = itemCertificate->value();
200     authKeyData.keyBlob = itemKeyBlob->value();
201     authKeyData.expirationDateMillisSinceEpoch = expirationDateMillisSinceEpoch;
202     authKeyData.staticAuthenticationData = itemStaticAuthenticationData->value();
203     authKeyData.pendingCertificate = itemPendingCertificate->value();
204     authKeyData.pendingKeyBlob = itemPendingKeyBlob->value();
205     authKeyData.useCount = itemUseCount->value();
206     return authKeyData;
207 }
208 
parseAccessControlProfileIds(const cppbor::Item & item)209 vector<int32_t> parseAccessControlProfileIds(const cppbor::Item& item) {
210     const cppbor::Array* array = item.asArray();
211     if (array == nullptr) {
212         LOG(ERROR) << "The accessControlProfileIds member is not an array";
213         return {};
214     }
215 
216     vector<int32_t> accessControlProfileIds;
217     for (size_t n = 0; n < array->size(); n++) {
218         const cppbor::Int* itemInt = ((*array)[n])->asInt();
219         if (itemInt == nullptr) {
220             LOG(ERROR) << "An item in the accessControlProfileIds array is not a bstr";
221             return {};
222         }
223         accessControlProfileIds.push_back(itemInt->value());
224     }
225     return accessControlProfileIds;
226 }
227 
parseEncryptedChunks(const cppbor::Item & item)228 optional<vector<vector<uint8_t>>> parseEncryptedChunks(const cppbor::Item& item) {
229     const cppbor::Array* array = item.asArray();
230     if (array == nullptr) {
231         LOG(ERROR) << "The encryptedChunks member is not an array";
232         return {};
233     }
234 
235     vector<vector<uint8_t>> encryptedChunks;
236     for (size_t n = 0; n < array->size(); n++) {
237         const cppbor::Bstr* itemBstr = ((*array)[n])->asBstr();
238         if (itemBstr == nullptr) {
239             LOG(ERROR) << "An item in the encryptedChunks array is not a bstr";
240             return {};
241         }
242         encryptedChunks.push_back(itemBstr->value());
243     }
244     return encryptedChunks;
245 }
246 
loadFromDisk()247 bool CredentialData::loadFromDisk() {
248     // Reset all data.
249     credentialData_.clear();
250     attestationCertificate_.clear();
251     secureAccessControlProfiles_.clear();
252     idToEncryptedChunks_.clear();
253     authKeyDatas_.clear();
254     keyCount_ = 0;
255     maxUsesPerKey_ = 1;
256 
257     optional<vector<uint8_t>> data = fileGetContents(fileName_);
258     if (!data) {
259         LOG(ERROR) << "Error loading data";
260         return false;
261     }
262 
263     auto [item, _ /* newPos */, message] = cppbor::parse(data.value());
264     if (item == nullptr) {
265         LOG(ERROR) << "Data loaded from " << fileName_ << " is not valid CBOR: " << message;
266         return false;
267     }
268 
269     const cppbor::Map* map = item->asMap();
270     if (map == nullptr) {
271         LOG(ERROR) << "Top-level item is not a map";
272         return false;
273     }
274 
275     for (size_t n = 0; n < map->size(); n++) {
276         auto& [keyItem, valueItem] = (*map)[n];
277         const cppbor::Tstr* tstr = keyItem->asTstr();
278         if (tstr == nullptr) {
279             LOG(ERROR) << "Key item in top-level map is not a tstr";
280             return false;
281         }
282         const string& key = tstr->value();
283 
284         if (key == "secureUserId") {
285             const cppbor::Int* number = valueItem->asInt();
286             if (number == nullptr) {
287                 LOG(ERROR) << "Value for secureUserId is not a number";
288                 return false;
289             }
290             secureUserId_ = number->value();
291         } else if (key == "credentialData") {
292             const cppbor::Bstr* valueBstr = valueItem->asBstr();
293             if (valueBstr == nullptr) {
294                 LOG(ERROR) << "Value for credentialData is not a bstr";
295                 return false;
296             }
297             credentialData_ = valueBstr->value();
298         } else if (key == "attestationCertificate") {
299             const cppbor::Bstr* valueBstr = valueItem->asBstr();
300             if (valueBstr == nullptr) {
301                 LOG(ERROR) << "Value for attestationCertificate is not a bstr";
302                 return false;
303             }
304             attestationCertificate_ = valueBstr->value();
305         } else if (key == "secureAccessControlProfiles") {
306             const cppbor::Array* array = valueItem->asArray();
307             if (array == nullptr) {
308                 LOG(ERROR) << "Value for attestationCertificate is not an array";
309                 return false;
310             }
311             for (size_t m = 0; m < array->size(); m++) {
312                 const std::unique_ptr<cppbor::Item>& item = (*array)[m];
313                 optional<SecureAccessControlProfile> sacp = parseSacp(*item);
314                 if (!sacp) {
315                     LOG(ERROR) << "Error parsing SecureAccessControlProfile";
316                     return false;
317                 }
318                 secureAccessControlProfiles_.push_back(sacp.value());
319             }
320 
321         } else if (key == "entryData") {
322             const cppbor::Map* map = valueItem->asMap();
323             if (map == nullptr) {
324                 LOG(ERROR) << "Value for encryptedChunks is not an map";
325                 return false;
326             }
327             for (size_t m = 0; m < map->size(); m++) {
328                 auto& [ecKeyItem, ecValueItem] = (*map)[m];
329                 const cppbor::Tstr* ecTstr = ecKeyItem->asTstr();
330                 if (ecTstr == nullptr) {
331                     LOG(ERROR) << "Key item in encryptedChunks map is not a tstr";
332                     return false;
333                 }
334                 const string& ecId = ecTstr->value();
335 
336                 const cppbor::Array* ecEntryArrayItem = ecValueItem->asArray();
337                 if (ecEntryArrayItem == nullptr || ecEntryArrayItem->size() < 3) {
338                     LOG(ERROR) << "Value item in encryptedChunks map is an array with at least two "
339                                   "elements";
340                     return false;
341                 }
342                 const cppbor::Int* ecEntrySizeItem = (*ecEntryArrayItem)[0]->asInt();
343                 if (ecEntrySizeItem == nullptr) {
344                     LOG(ERROR) << "Entry size not a number";
345                     return false;
346                 }
347                 uint64_t entrySize = ecEntrySizeItem->value();
348 
349                 optional<vector<int32_t>> accessControlProfileIds =
350                     parseAccessControlProfileIds(*(*ecEntryArrayItem)[1]);
351                 if (!accessControlProfileIds) {
352                     LOG(ERROR) << "Error parsing access control profile ids";
353                     return false;
354                 }
355 
356                 optional<vector<vector<uint8_t>>> encryptedChunks =
357                     parseEncryptedChunks(*(*ecEntryArrayItem)[2]);
358                 if (!encryptedChunks) {
359                     LOG(ERROR) << "Error parsing encrypted chunks";
360                     return false;
361                 }
362 
363                 EntryData data;
364                 data.size = entrySize;
365                 data.accessControlProfileIds = accessControlProfileIds.value();
366                 data.encryptedChunks = encryptedChunks.value();
367                 idToEncryptedChunks_[ecId] = data;
368             }
369 
370         } else if (key == "authKeyData") {
371             const cppbor::Array* array = valueItem->asArray();
372             if (array == nullptr) {
373                 LOG(ERROR) << "Value for authData is not an array";
374                 return false;
375             }
376             for (size_t m = 0; m < array->size(); m++) {
377                 const std::unique_ptr<cppbor::Item>& item = (*array)[m];
378                 optional<AuthKeyData> authKeyData = parseAuthKeyData(*item);
379                 if (!authKeyData) {
380                     LOG(ERROR) << "Error parsing AuthKeyData";
381                     return false;
382                 }
383                 authKeyDatas_.push_back(authKeyData.value());
384             }
385 
386         } else if (key == "authKeyCount") {
387             const cppbor::Int* number = valueItem->asInt();
388             if (number == nullptr) {
389                 LOG(ERROR) << "Value for authKeyCount is not a number";
390                 return false;
391             }
392             keyCount_ = number->value();
393 
394         } else if (key == "maxUsesPerAuthKey") {
395             const cppbor::Int* number = valueItem->asInt();
396             if (number == nullptr) {
397                 LOG(ERROR) << "Value for maxUsesPerAuthKey is not a number";
398                 return false;
399             }
400             maxUsesPerKey_ = number->value();
401         }
402     }
403 
404     if (credentialData_.size() == 0) {
405         LOG(ERROR) << "Missing credentialData";
406         return false;
407     }
408 
409     if (attestationCertificate_.size() == 0) {
410         LOG(ERROR) << "Missing attestationCertificate";
411         return false;
412     }
413 
414     if (size_t(keyCount_) != authKeyDatas_.size()) {
415         LOG(ERROR) << "keyCount_=" << keyCount_
416                    << " != authKeyDatas_.size()=" << authKeyDatas_.size();
417         return false;
418     }
419 
420     return true;
421 }
422 
getCredentialData() const423 const vector<uint8_t>& CredentialData::getCredentialData() const {
424     return credentialData_;
425 }
426 
getSecureUserId()427 int64_t CredentialData::getSecureUserId() {
428     return secureUserId_;
429 }
430 
getAttestationCertificate() const431 const vector<uint8_t>& CredentialData::getAttestationCertificate() const {
432     return attestationCertificate_;
433 }
434 
getSecureAccessControlProfiles() const435 const vector<SecureAccessControlProfile>& CredentialData::getSecureAccessControlProfiles() const {
436     return secureAccessControlProfiles_;
437 }
438 
hasEntryData(const string & namespaceName,const string & entryName) const439 bool CredentialData::hasEntryData(const string& namespaceName, const string& entryName) const {
440     string id = namespaceName + ":" + entryName;
441     auto iter = idToEncryptedChunks_.find(id);
442     if (iter == idToEncryptedChunks_.end()) {
443         return false;
444     }
445     return true;
446 }
447 
getEntryData(const string & namespaceName,const string & entryName) const448 optional<EntryData> CredentialData::getEntryData(const string& namespaceName,
449                                                  const string& entryName) const {
450     string id = namespaceName + ":" + entryName;
451     auto iter = idToEncryptedChunks_.find(id);
452     if (iter == idToEncryptedChunks_.end()) {
453         return {};
454     }
455     return iter->second;
456 }
457 
deleteCredential()458 bool CredentialData::deleteCredential() {
459     if (unlink(fileName_.c_str()) != 0) {
460         PLOG(ERROR) << "Error deleting " << fileName_;
461         return false;
462     }
463     return true;
464 }
465 
credentialExists(const string & dataPath,uid_t ownerUid,const string & name)466 optional<bool> CredentialData::credentialExists(const string& dataPath, uid_t ownerUid,
467                                                 const string& name) {
468     struct stat statbuf;
469     string filename = calculateCredentialFileName(dataPath, ownerUid, name);
470     if (stat(filename.c_str(), &statbuf) != 0) {
471         if (errno == ENOENT) {
472             return false;
473         }
474         PLOG(ERROR) << "Error getting information about " << filename;
475         return {};
476     }
477     return true;
478 }
479 
480 // ---
481 
setAvailableAuthenticationKeys(int keyCount,int maxUsesPerKey)482 void CredentialData::setAvailableAuthenticationKeys(int keyCount, int maxUsesPerKey) {
483     keyCount_ = keyCount;
484     maxUsesPerKey_ = maxUsesPerKey;
485 
486     // If growing the number of auth keys (prevKeyCount < keyCount_ case) we'll add
487     // new AuthKeyData structs to |authKeyDatas_| and each struct will have empty |certificate|
488     // and |pendingCertificate| fields. Those will be filled out when the
489     // getAuthKeysNeedingCertification() is called.
490     //
491     // If shrinking, we'll just delete the AuthKeyData structs at the end. There's nothing
492     // else to do, the HAL doesn't need to know we're nuking these authentication keys.
493     //
494     // Therefore, in either case it's as simple as just resizing the vector.
495     authKeyDatas_.resize(keyCount_);
496 }
497 
getAuthKeyDatas() const498 const vector<AuthKeyData>& CredentialData::getAuthKeyDatas() const {
499     return authKeyDatas_;
500 }
501 
getAvailableAuthenticationKeys()502 pair<int /* keyCount */, int /*maxUsersPerKey */> CredentialData::getAvailableAuthenticationKeys() {
503     return std::make_pair(keyCount_, maxUsesPerKey_);
504 }
505 
findAuthKey_(bool allowUsingExhaustedKeys,bool allowUsingExpiredKeys)506 AuthKeyData* CredentialData::findAuthKey_(bool allowUsingExhaustedKeys,
507                                           bool allowUsingExpiredKeys) {
508     AuthKeyData* candidate = nullptr;
509 
510     int64_t nowMilliSeconds =
511         std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) * 1000;
512 
513     int n = 0;
514     for (AuthKeyData& data : authKeyDatas_) {
515         if (nowMilliSeconds > data.expirationDateMillisSinceEpoch) {
516             if (!allowUsingExpiredKeys) {
517                 continue;
518             }
519         }
520         if (data.certificate.size() != 0) {
521             // Not expired, include in normal check
522             if (candidate == nullptr || data.useCount < candidate->useCount) {
523                 candidate = &data;
524             }
525         }
526         n++;
527     }
528 
529     if (candidate == nullptr) {
530         return nullptr;
531     }
532 
533     if (candidate->useCount >= maxUsesPerKey_ && !allowUsingExhaustedKeys) {
534         return nullptr;
535     }
536 
537     return candidate;
538 }
539 
selectAuthKey(bool allowUsingExhaustedKeys,bool allowUsingExpiredKeys)540 const AuthKeyData* CredentialData::selectAuthKey(bool allowUsingExhaustedKeys,
541                                                  bool allowUsingExpiredKeys) {
542     AuthKeyData* candidate;
543 
544     // First try to find a un-expired key..
545     candidate = findAuthKey_(allowUsingExhaustedKeys, false);
546     if (candidate == nullptr) {
547         // That didn't work, there are no un-expired keys and we don't allow using expired keys.
548         if (!allowUsingExpiredKeys) {
549             return nullptr;
550         }
551 
552         // See if there's an expired key then...
553         candidate = findAuthKey_(allowUsingExhaustedKeys, true);
554         if (candidate == nullptr) {
555             return nullptr;
556         }
557     }
558 
559     candidate->useCount += 1;
560     return candidate;
561 }
562 
563 optional<vector<vector<uint8_t>>>
getAuthKeysNeedingCertification(const sp<IIdentityCredential> & halBinder)564 CredentialData::getAuthKeysNeedingCertification(const sp<IIdentityCredential>& halBinder) {
565 
566     vector<vector<uint8_t>> keysNeedingCert;
567 
568     int64_t nowMilliSeconds =
569         std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) * 1000;
570 
571     for (AuthKeyData& data : authKeyDatas_) {
572         bool keyExceedUseCount = (data.useCount >= maxUsesPerKey_);
573         bool keyBeyondExpirationDate = (nowMilliSeconds > data.expirationDateMillisSinceEpoch);
574         bool newKeyNeeded =
575             (data.certificate.size() == 0) || keyExceedUseCount || keyBeyondExpirationDate;
576         bool certificationPending = (data.pendingCertificate.size() > 0);
577         if (newKeyNeeded && !certificationPending) {
578             vector<uint8_t> signingKeyBlob;
579             Certificate signingKeyCertificate;
580             if (!halBinder->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate)
581                      .isOk()) {
582                 LOG(ERROR) << "Error generating signing key-pair";
583                 return {};
584             }
585             data.pendingCertificate = signingKeyCertificate.encodedCertificate;
586             data.pendingKeyBlob = signingKeyBlob;
587             certificationPending = true;
588         }
589 
590         if (certificationPending) {
591             keysNeedingCert.push_back(data.pendingCertificate);
592         }
593     }
594     return keysNeedingCert;
595 }
596 
storeStaticAuthenticationData(const vector<uint8_t> & authenticationKey,int64_t expirationDateMillisSinceEpoch,const vector<uint8_t> & staticAuthData)597 bool CredentialData::storeStaticAuthenticationData(const vector<uint8_t>& authenticationKey,
598                                                    int64_t expirationDateMillisSinceEpoch,
599                                                    const vector<uint8_t>& staticAuthData) {
600     for (AuthKeyData& data : authKeyDatas_) {
601         if (data.pendingCertificate == authenticationKey) {
602             data.certificate = data.pendingCertificate;
603             data.keyBlob = data.pendingKeyBlob;
604             data.expirationDateMillisSinceEpoch = expirationDateMillisSinceEpoch;
605             data.staticAuthenticationData = staticAuthData;
606             data.pendingCertificate.clear();
607             data.pendingKeyBlob.clear();
608             data.useCount = 0;
609             return true;
610         }
611     }
612     return false;
613 }
614 
615 }  // namespace identity
616 }  // namespace security
617 }  // namespace android
618