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 "Credential"
18 
19 #include <android-base/logging.h>
20 
21 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
22 
23 #include <android/security/identity/ICredentialStore.h>
24 
25 #include <android/security/keystore/BnCredstoreTokenCallback.h>
26 #include <android/security/keystore/IKeystoreService.h>
27 #include <binder/IPCThreadState.h>
28 #include <binder/IServiceManager.h>
29 #include <keymasterV4_0/keymaster_utils.h>
30 
31 #include <cppbor.h>
32 #include <cppbor_parse.h>
33 #include <future>
34 #include <tuple>
35 
36 #include "Credential.h"
37 #include "CredentialData.h"
38 #include "Util.h"
39 
40 namespace android {
41 namespace security {
42 namespace identity {
43 
44 using std::optional;
45 using std::promise;
46 using std::tuple;
47 
48 using android::security::keystore::IKeystoreService;
49 
50 using ::android::hardware::identity::support::ecKeyPairGetPkcs12;
51 using ::android::hardware::identity::support::ecKeyPairGetPrivateKey;
52 using ::android::hardware::identity::support::ecKeyPairGetPublicKey;
53 using ::android::hardware::identity::support::sha256;
54 
55 using android::hardware::keymaster::V4_0::HardwareAuthToken;
56 using android::hardware::keymaster::V4_0::VerificationToken;
57 using AidlHardwareAuthToken = android::hardware::keymaster::HardwareAuthToken;
58 using AidlVerificationToken = android::hardware::keymaster::VerificationToken;
59 
Credential(CipherSuite cipherSuite,const std::string & dataPath,const std::string & credentialName)60 Credential::Credential(CipherSuite cipherSuite, const std::string& dataPath,
61                        const std::string& credentialName)
62     : cipherSuite_(cipherSuite), dataPath_(dataPath), credentialName_(credentialName) {}
63 
~Credential()64 Credential::~Credential() {}
65 
loadCredential(sp<IIdentityCredentialStore> halStoreBinder)66 Status Credential::loadCredential(sp<IIdentityCredentialStore> halStoreBinder) {
67     uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
68     sp<CredentialData> data = new CredentialData(dataPath_, callingUid, credentialName_);
69     if (!data->loadFromDisk()) {
70         LOG(ERROR) << "Error loading data for credential";
71         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
72                                                 "Error loading data for credential");
73     }
74 
75     data_ = data;
76 
77     sp<IIdentityCredential> halBinder;
78     Status status =
79         halStoreBinder->getCredential(cipherSuite_, data_->getCredentialData(), &halBinder);
80     if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
81         int code = status.serviceSpecificErrorCode();
82         if (code == IIdentityCredentialStore::STATUS_CIPHER_SUITE_NOT_SUPPORTED) {
83             return halStatusToError(status, ICredentialStore::ERROR_CIPHER_SUITE_NOT_SUPPORTED);
84         }
85     }
86     if (!status.isOk()) {
87         LOG(ERROR) << "Error getting HAL binder";
88         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC);
89     }
90 
91     halBinder_ = halBinder;
92 
93     return Status::ok();
94 }
95 
getCredentialKeyCertificateChain(std::vector<uint8_t> * _aidl_return)96 Status Credential::getCredentialKeyCertificateChain(std::vector<uint8_t>* _aidl_return) {
97     *_aidl_return = data_->getAttestationCertificate();
98     return Status::ok();
99 }
100 
101 // Returns operation handle
selectAuthKey(bool allowUsingExhaustedKeys,int64_t * _aidl_return)102 Status Credential::selectAuthKey(bool allowUsingExhaustedKeys, int64_t* _aidl_return) {
103 
104     selectedAuthKey_ = data_->selectAuthKey(allowUsingExhaustedKeys);
105     if (selectedAuthKey_ == nullptr) {
106         return Status::fromServiceSpecificError(
107             ICredentialStore::ERROR_NO_AUTHENTICATION_KEY_AVAILABLE,
108             "No suitable authentication key available");
109     }
110 
111     int64_t challenge;
112     Status status = halBinder_->createAuthChallenge(&challenge);
113     if (!status.isOk()) {
114         return halStatusToGenericError(status);
115     }
116     if (challenge == 0) {
117         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
118                                                 "Returned challenge is 0 (bug in HAL or TA)");
119     }
120 
121     selectedChallenge_ = challenge;
122     *_aidl_return = challenge;
123     return Status::ok();
124 }
125 
126 class CredstoreTokenCallback : public android::security::keystore::BnCredstoreTokenCallback,
127                                public promise<tuple<bool, vector<uint8_t>, vector<uint8_t>>> {
128   public:
CredstoreTokenCallback()129     CredstoreTokenCallback() {}
onFinished(bool success,const vector<uint8_t> & authToken,const vector<uint8_t> & verificationToken)130     virtual Status onFinished(bool success, const vector<uint8_t>& authToken,
131                               const vector<uint8_t>& verificationToken) override {
132         this->set_value({success, authToken, verificationToken});
133         return Status::ok();
134     }
135 };
136 
137 // Returns false if an error occurred communicating with keystore.
138 //
getTokensFromKeystore(uint64_t challenge,uint64_t secureUserId,unsigned int authTokenMaxAgeMillis,vector<uint8_t> & authToken,vector<uint8_t> & verificationToken)139 bool getTokensFromKeystore(uint64_t challenge, uint64_t secureUserId,
140                            unsigned int authTokenMaxAgeMillis, vector<uint8_t>& authToken,
141                            vector<uint8_t>& verificationToken) {
142     sp<IServiceManager> sm = defaultServiceManager();
143     sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
144     sp<IKeystoreService> keystore = interface_cast<IKeystoreService>(binder);
145     if (keystore == nullptr) {
146         return false;
147     }
148 
149     sp<CredstoreTokenCallback> callback = new CredstoreTokenCallback();
150     auto future = callback->get_future();
151 
152     Status status =
153         keystore->getTokensForCredstore(challenge, secureUserId, authTokenMaxAgeMillis, callback);
154     if (!status.isOk()) {
155         return false;
156     }
157 
158     auto fstatus = future.wait_for(std::chrono::milliseconds(5000));
159     if (fstatus != std::future_status::ready) {
160         LOG(ERROR) << "Waited 5 seconds from tokens for credstore, aborting";
161         return false;
162     }
163     auto [success, returnedAuthToken, returnedVerificationToken] = future.get();
164     if (!success) {
165         LOG(ERROR) << "Error getting tokens from credstore";
166         return false;
167     }
168     authToken = returnedAuthToken;
169     verificationToken = returnedVerificationToken;
170     return true;
171 }
172 
getEntries(const vector<uint8_t> & requestMessage,const vector<RequestNamespaceParcel> & requestNamespaces,const vector<uint8_t> & sessionTranscript,const vector<uint8_t> & readerSignature,bool allowUsingExhaustedKeys,GetEntriesResultParcel * _aidl_return)173 Status Credential::getEntries(const vector<uint8_t>& requestMessage,
174                               const vector<RequestNamespaceParcel>& requestNamespaces,
175                               const vector<uint8_t>& sessionTranscript,
176                               const vector<uint8_t>& readerSignature, bool allowUsingExhaustedKeys,
177                               GetEntriesResultParcel* _aidl_return) {
178     GetEntriesResultParcel ret;
179 
180     // Calculate requestCounts ahead of time and be careful not to include
181     // elements that don't exist.
182     //
183     // Also go through and figure out which access control profiles to include
184     // in the startRetrieval() call.
185     vector<int32_t> requestCounts;
186     const vector<SecureAccessControlProfile>& allProfiles = data_->getSecureAccessControlProfiles();
187 
188     // We don't support ACP identifiers which isn't in the range 0 to 31. This
189     // guarantee exists so it's feasible to implement the TA part of an Identity
190     // Credential HAL implementation where the TA uses a 32-bit word to indicate
191     // which profiles are authorized.
192     for (const SecureAccessControlProfile& profile : allProfiles) {
193         if (profile.id < 0 || profile.id >= 32) {
194             return Status::fromServiceSpecificError(
195                 ICredentialStore::ERROR_GENERIC,
196                 "Invalid accessProfileId in profile (must be between 0 and 31)");
197         }
198     }
199 
200     vector<bool> includeProfile(32);
201 
202     for (const RequestNamespaceParcel& rns : requestNamespaces) {
203         size_t numEntriesInNsToRequest = 0;
204         for (const RequestEntryParcel& rep : rns.entries) {
205             if (data_->hasEntryData(rns.namespaceName, rep.name)) {
206                 numEntriesInNsToRequest++;
207             }
208 
209             optional<EntryData> data = data_->getEntryData(rns.namespaceName, rep.name);
210             if (data) {
211                 for (int32_t id : data.value().accessControlProfileIds) {
212                     if (id < 0 || id >= 32) {
213                         LOG(ERROR) << "Invalid accessControlProfileId " << id << " for "
214                                    << rns.namespaceName << ": " << rep.name;
215                         return Status::fromServiceSpecificError(
216                             ICredentialStore::ERROR_GENERIC,
217                             "Invalid accessProfileId in entry (must be between 0 and 31)");
218                     }
219                     includeProfile[id] = true;
220                 }
221             }
222         }
223         requestCounts.push_back(numEntriesInNsToRequest);
224     }
225 
226     // Now that we know which profiles are needed, send only those to the
227     // HAL.
228     vector<SecureAccessControlProfile> selectedProfiles;
229     for (size_t n = 0; n < allProfiles.size(); n++) {
230         if (includeProfile[allProfiles[n].id]) {
231             selectedProfiles.push_back(allProfiles[n]);
232         }
233     }
234 
235     // Calculate the highest [1] non-zero timeout and if user-auth is needed
236     // ... we need this to select an appropriate authToken.
237     //
238     // [1] : Why do we request the highest timeout and not the lowest? Well, we
239     //       return partial results in getEntries e.g. if some data elements
240     //       fail to authorize we'll still return the ones that did not fail. So
241     //       e.g. consider data elements A and B where A has an ACP with 60
242     //       seconds and B has an ACP with 3600 seconds. In this case we'll be
243     //       fine with getting an authToken for e.g. 2400 seconds which would
244     //       mean returning only B.
245     //
246     bool userAuthNeeded = false;
247     unsigned int authTokenMaxAgeMillis = 0;
248     for (auto& profile : selectedProfiles) {
249         if (profile.userAuthenticationRequired) {
250             userAuthNeeded = true;
251             if (profile.timeoutMillis > 0) {
252                 if (profile.timeoutMillis > authTokenMaxAgeMillis) {
253                     authTokenMaxAgeMillis = profile.timeoutMillis;
254                 }
255             }
256         }
257     }
258 
259     // If requesting a challenge-based authToken the idea is that authentication
260     // happens as part of the transaction. As such, authTokenMaxAgeMillis should
261     // be nearly zero. We'll use 10 seconds for this.
262     if (userAuthNeeded && selectedChallenge_ != 0) {
263         authTokenMaxAgeMillis = 10 * 1000;
264     }
265 
266     // Reset tokens and only get them if they're actually needed, e.g. if user authentication
267     // is needed in any of the access control profiles for data items being requested.
268     //
269     AidlHardwareAuthToken aidlAuthToken;
270     AidlVerificationToken aidlVerificationToken;
271     aidlAuthToken.challenge = 0;
272     aidlAuthToken.userId = 0;
273     aidlAuthToken.authenticatorId = 0;
274     aidlAuthToken.authenticatorType =
275         ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
276     aidlAuthToken.timestamp.milliSeconds = 0;
277     aidlAuthToken.mac.clear();
278     aidlVerificationToken.challenge = 0;
279     aidlVerificationToken.timestamp.milliSeconds = 0;
280     aidlVerificationToken.securityLevel = ::android::hardware::keymaster::SecurityLevel::SOFTWARE;
281     aidlVerificationToken.mac.clear();
282     if (userAuthNeeded) {
283         vector<uint8_t> authTokenBytes;
284         vector<uint8_t> verificationTokenBytes;
285         if (!getTokensFromKeystore(selectedChallenge_, data_->getSecureUserId(),
286                                    authTokenMaxAgeMillis, authTokenBytes, verificationTokenBytes)) {
287             LOG(ERROR) << "Error getting tokens from keystore";
288             return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
289                                                     "Error getting tokens from keystore");
290         }
291 
292         // It's entirely possible getTokensFromKeystore() succeeded but didn't
293         // return any tokens (in which case the returned byte-vectors are
294         // empty). For example, this can happen if no auth token is available
295         // which satifies e.g. |authTokenMaxAgeMillis|.
296         //
297         if (authTokenBytes.size() > 0) {
298             HardwareAuthToken authToken =
299                 android::hardware::keymaster::V4_0::support::hidlVec2AuthToken(authTokenBytes);
300             // Convert from HIDL to AIDL...
301             aidlAuthToken.challenge = int64_t(authToken.challenge);
302             aidlAuthToken.userId = int64_t(authToken.userId);
303             aidlAuthToken.authenticatorId = int64_t(authToken.authenticatorId);
304             aidlAuthToken.authenticatorType =
305                 ::android::hardware::keymaster::HardwareAuthenticatorType(
306                     int32_t(authToken.authenticatorType));
307             aidlAuthToken.timestamp.milliSeconds = int64_t(authToken.timestamp);
308             aidlAuthToken.mac = authToken.mac;
309         }
310 
311         if (verificationTokenBytes.size() > 0) {
312             optional<VerificationToken> token =
313                 android::hardware::keymaster::V4_0::support::deserializeVerificationToken(
314                     verificationTokenBytes);
315             if (!token) {
316                 LOG(ERROR) << "Error deserializing verification token";
317                 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
318                                                         "Error deserializing verification token");
319             }
320             aidlVerificationToken.challenge = token->challenge;
321             aidlVerificationToken.timestamp.milliSeconds = token->timestamp;
322             aidlVerificationToken.securityLevel =
323                 ::android::hardware::keymaster::SecurityLevel(token->securityLevel);
324             aidlVerificationToken.mac = token->mac;
325         }
326     }
327 
328     // Note that the selectAuthKey() method is only called if a CryptoObject is involved at
329     // the Java layer. So we could end up with no previously selected auth key and we may
330     // need one.
331     const AuthKeyData* authKey = selectedAuthKey_;
332     if (sessionTranscript.size() > 0) {
333         if (authKey == nullptr) {
334             authKey = data_->selectAuthKey(allowUsingExhaustedKeys);
335             if (authKey == nullptr) {
336                 return Status::fromServiceSpecificError(
337                     ICredentialStore::ERROR_NO_AUTHENTICATION_KEY_AVAILABLE,
338                     "No suitable authentication key available");
339             }
340         }
341     }
342     vector<uint8_t> signingKeyBlob;
343     if (authKey != nullptr) {
344         signingKeyBlob = authKey->keyBlob;
345     }
346 
347     // Pass the HAL enough information to allow calculating the size of
348     // DeviceNameSpaces ahead of time.
349     vector<RequestNamespace> halRequestNamespaces;
350     for (const RequestNamespaceParcel& rns : requestNamespaces) {
351         RequestNamespace ns;
352         ns.namespaceName = rns.namespaceName;
353         for (const RequestEntryParcel& rep : rns.entries) {
354             optional<EntryData> entryData = data_->getEntryData(rns.namespaceName, rep.name);
355             if (entryData) {
356                 RequestDataItem di;
357                 di.name = rep.name;
358                 di.size = entryData.value().size;
359                 di.accessControlProfileIds = entryData.value().accessControlProfileIds;
360                 ns.items.push_back(di);
361             }
362         }
363         if (ns.items.size() > 0) {
364             halRequestNamespaces.push_back(ns);
365         }
366     }
367     // This is not catastrophic, we might be dealing with a version 1 implementation which
368     // doesn't have this method.
369     Status status = halBinder_->setRequestedNamespaces(halRequestNamespaces);
370     if (!status.isOk()) {
371         LOG(INFO) << "Failed setting expected requested namespaces, assuming V1 HAL "
372                   << "and continuing";
373     }
374 
375     // Pass the verification token. Failure is OK, this method isn't in the V1 HAL.
376     status = halBinder_->setVerificationToken(aidlVerificationToken);
377     if (!status.isOk()) {
378         LOG(INFO) << "Failed setting verification token, assuming V1 HAL "
379                   << "and continuing";
380     }
381 
382     status =
383         halBinder_->startRetrieval(selectedProfiles, aidlAuthToken, requestMessage, signingKeyBlob,
384                                    sessionTranscript, readerSignature, requestCounts);
385     if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
386         int code = status.serviceSpecificErrorCode();
387         if (code == IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND) {
388             return halStatusToError(status, ICredentialStore::ERROR_EPHEMERAL_PUBLIC_KEY_NOT_FOUND);
389         } else if (code == IIdentityCredentialStore::STATUS_READER_SIGNATURE_CHECK_FAILED) {
390             return halStatusToError(status, ICredentialStore::ERROR_INVALID_READER_SIGNATURE);
391         } else if (code == IIdentityCredentialStore::STATUS_INVALID_ITEMS_REQUEST_MESSAGE) {
392             return halStatusToError(status, ICredentialStore::ERROR_INVALID_ITEMS_REQUEST_MESSAGE);
393         } else if (code == IIdentityCredentialStore::STATUS_SESSION_TRANSCRIPT_MISMATCH) {
394             return halStatusToError(status, ICredentialStore::ERROR_SESSION_TRANSCRIPT_MISMATCH);
395         }
396     }
397     if (!status.isOk()) {
398         return halStatusToGenericError(status);
399     }
400 
401     for (const RequestNamespaceParcel& rns : requestNamespaces) {
402         ResultNamespaceParcel resultNamespaceParcel;
403         resultNamespaceParcel.namespaceName = rns.namespaceName;
404 
405         for (const RequestEntryParcel& rep : rns.entries) {
406             ResultEntryParcel resultEntryParcel;
407             resultEntryParcel.name = rep.name;
408 
409             optional<EntryData> data = data_->getEntryData(rns.namespaceName, rep.name);
410             if (!data) {
411                 resultEntryParcel.status = STATUS_NO_SUCH_ENTRY;
412                 resultNamespaceParcel.entries.push_back(resultEntryParcel);
413                 continue;
414             }
415 
416             status =
417                 halBinder_->startRetrieveEntryValue(rns.namespaceName, rep.name, data.value().size,
418                                                     data.value().accessControlProfileIds);
419             if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
420                 int code = status.serviceSpecificErrorCode();
421                 if (code == IIdentityCredentialStore::STATUS_USER_AUTHENTICATION_FAILED) {
422                     resultEntryParcel.status = STATUS_USER_AUTHENTICATION_FAILED;
423                     resultNamespaceParcel.entries.push_back(resultEntryParcel);
424                     continue;
425                 } else if (code == IIdentityCredentialStore::STATUS_READER_AUTHENTICATION_FAILED) {
426                     resultEntryParcel.status = STATUS_READER_AUTHENTICATION_FAILED;
427                     resultNamespaceParcel.entries.push_back(resultEntryParcel);
428                     continue;
429                 } else if (code == IIdentityCredentialStore::STATUS_NOT_IN_REQUEST_MESSAGE) {
430                     resultEntryParcel.status = STATUS_NOT_IN_REQUEST_MESSAGE;
431                     resultNamespaceParcel.entries.push_back(resultEntryParcel);
432                     continue;
433                 } else if (code == IIdentityCredentialStore::STATUS_NO_ACCESS_CONTROL_PROFILES) {
434                     resultEntryParcel.status = STATUS_NO_ACCESS_CONTROL_PROFILES;
435                     resultNamespaceParcel.entries.push_back(resultEntryParcel);
436                     continue;
437                 }
438             }
439             if (!status.isOk()) {
440                 return halStatusToGenericError(status);
441             }
442 
443             vector<uint8_t> value;
444             for (const auto& encryptedChunk : data.value().encryptedChunks) {
445                 vector<uint8_t> chunk;
446                 status = halBinder_->retrieveEntryValue(encryptedChunk, &chunk);
447                 if (!status.isOk()) {
448                     return halStatusToGenericError(status);
449                 }
450                 value.insert(value.end(), chunk.begin(), chunk.end());
451             }
452 
453             resultEntryParcel.status = STATUS_OK;
454             resultEntryParcel.value = value;
455             resultNamespaceParcel.entries.push_back(resultEntryParcel);
456         }
457         ret.resultNamespaces.push_back(resultNamespaceParcel);
458     }
459 
460     status = halBinder_->finishRetrieval(&ret.mac, &ret.deviceNameSpaces);
461     if (!status.isOk()) {
462         return halStatusToGenericError(status);
463     }
464     if (authKey != nullptr) {
465         ret.staticAuthenticationData = authKey->staticAuthenticationData;
466     }
467 
468     // Ensure useCount is updated on disk.
469     if (authKey != nullptr) {
470         if (!data_->saveToDisk()) {
471             return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
472                                                     "Error saving data");
473         }
474     }
475 
476     *_aidl_return = ret;
477     return Status::ok();
478 }
479 
deleteCredential(vector<uint8_t> * _aidl_return)480 Status Credential::deleteCredential(vector<uint8_t>* _aidl_return) {
481     vector<uint8_t> proofOfDeletionSignature;
482     Status status = halBinder_->deleteCredential(&proofOfDeletionSignature);
483     if (!status.isOk()) {
484         return halStatusToGenericError(status);
485     }
486     if (!data_->deleteCredential()) {
487         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
488                                                 "Error deleting credential data on disk");
489     }
490     *_aidl_return = proofOfDeletionSignature;
491     return Status::ok();
492 }
493 
createEphemeralKeyPair(vector<uint8_t> * _aidl_return)494 Status Credential::createEphemeralKeyPair(vector<uint8_t>* _aidl_return) {
495     vector<uint8_t> keyPair;
496     Status status = halBinder_->createEphemeralKeyPair(&keyPair);
497     if (!status.isOk()) {
498         return halStatusToGenericError(status);
499     }
500 
501     optional<vector<uint8_t>> pkcs12Bytes = ecKeyPairGetPkcs12(keyPair,
502                                                                "ephemeralKey",  // Alias for key
503                                                                "0",  // Serial, as a decimal number
504                                                                "Credstore",      // Issuer
505                                                                "Ephemeral Key",  // Subject
506                                                                0,  // Validity Not Before
507                                                                24 * 60 * 60);  // Validity Not After
508     if (!pkcs12Bytes) {
509         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
510                                                 "Error creating PKCS#12 structure for key pair");
511     }
512     *_aidl_return = pkcs12Bytes.value();
513     return Status::ok();
514 }
515 
setReaderEphemeralPublicKey(const vector<uint8_t> & publicKey)516 Status Credential::setReaderEphemeralPublicKey(const vector<uint8_t>& publicKey) {
517     Status status = halBinder_->setReaderEphemeralPublicKey(publicKey);
518     if (!status.isOk()) {
519         return halStatusToGenericError(status);
520     }
521     return Status::ok();
522 }
523 
setAvailableAuthenticationKeys(int32_t keyCount,int32_t maxUsesPerKey)524 Status Credential::setAvailableAuthenticationKeys(int32_t keyCount, int32_t maxUsesPerKey) {
525     data_->setAvailableAuthenticationKeys(keyCount, maxUsesPerKey);
526     if (!data_->saveToDisk()) {
527         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
528                                                 "Error saving data");
529     }
530     return Status::ok();
531 }
532 
getAuthKeysNeedingCertification(vector<AuthKeyParcel> * _aidl_return)533 Status Credential::getAuthKeysNeedingCertification(vector<AuthKeyParcel>* _aidl_return) {
534     optional<vector<vector<uint8_t>>> keysNeedingCert =
535         data_->getAuthKeysNeedingCertification(halBinder_);
536     if (!keysNeedingCert) {
537         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
538                                                 "Error getting auth keys neededing certification");
539     }
540     vector<AuthKeyParcel> authKeyParcels;
541     for (const vector<uint8_t>& key : keysNeedingCert.value()) {
542         AuthKeyParcel authKeyParcel;
543         authKeyParcel.x509cert = key;
544         authKeyParcels.push_back(authKeyParcel);
545     }
546     if (!data_->saveToDisk()) {
547         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
548                                                 "Error saving data");
549     }
550     *_aidl_return = authKeyParcels;
551     return Status::ok();
552 }
553 
storeStaticAuthenticationData(const AuthKeyParcel & authenticationKey,const vector<uint8_t> & staticAuthData)554 Status Credential::storeStaticAuthenticationData(const AuthKeyParcel& authenticationKey,
555                                                  const vector<uint8_t>& staticAuthData) {
556     if (!data_->storeStaticAuthenticationData(authenticationKey.x509cert, staticAuthData)) {
557         return Status::fromServiceSpecificError(
558             ICredentialStore::ERROR_AUTHENTICATION_KEY_NOT_FOUND,
559             "Error finding authentication key to store static "
560             "authentication data for");
561     }
562     if (!data_->saveToDisk()) {
563         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
564                                                 "Error saving data");
565     }
566     return Status::ok();
567 }
568 
getAuthenticationDataUsageCount(vector<int32_t> * _aidl_return)569 Status Credential::getAuthenticationDataUsageCount(vector<int32_t>* _aidl_return) {
570     const vector<AuthKeyData>& authKeyDatas = data_->getAuthKeyDatas();
571     vector<int32_t> ret;
572     for (const AuthKeyData& authKeyData : authKeyDatas) {
573         ret.push_back(authKeyData.useCount);
574     }
575     *_aidl_return = ret;
576     return Status::ok();
577 }
578 
579 }  // namespace identity
580 }  // namespace security
581 }  // namespace android
582