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 <android-base/logging.h>
20 #include <android/binder_manager.h>
21 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
22 
23 #include <android/security/identity/ICredentialStore.h>
24 
25 #include <binder/IPCThreadState.h>
26 #include <binder/IServiceManager.h>
27 #include <keymasterV4_0/keymaster_utils.h>
28 
29 #include <cppbor.h>
30 #include <cppbor_parse.h>
31 #include <future>
32 #include <tuple>
33 
34 #include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
35 #include <aidl/android/hardware/security/secureclock/TimeStampToken.h>
36 #include <aidl/android/security/authorization/AuthorizationTokens.h>
37 #include <aidl/android/security/authorization/IKeystoreAuthorization.h>
38 
39 #include "Credential.h"
40 #include "CredentialData.h"
41 #include "Util.h"
42 #include "WritableCredential.h"
43 
44 namespace android {
45 namespace security {
46 namespace identity {
47 
48 using std::optional;
49 using std::promise;
50 using std::tuple;
51 
52 using ::android::hardware::identity::IWritableIdentityCredential;
53 
54 using ::android::hardware::identity::support::ecKeyPairGetPkcs12;
55 using ::android::hardware::identity::support::ecKeyPairGetPrivateKey;
56 using ::android::hardware::identity::support::ecKeyPairGetPublicKey;
57 using ::android::hardware::identity::support::sha256;
58 
59 using android::hardware::keymaster::SecurityLevel;
60 using android::hardware::keymaster::V4_0::HardwareAuthToken;
61 using android::hardware::keymaster::V4_0::VerificationToken;
62 using AidlHardwareAuthToken = android::hardware::keymaster::HardwareAuthToken;
63 using AidlVerificationToken = android::hardware::keymaster::VerificationToken;
64 
65 using KeyMintAuthToken = ::aidl::android::hardware::security::keymint::HardwareAuthToken;
66 using ::aidl::android::hardware::security::secureclock::TimeStampToken;
67 using ::aidl::android::security::authorization::AuthorizationTokens;
68 using ::aidl::android::security::authorization::IKeystoreAuthorization;
69 
Credential(CipherSuite cipherSuite,const std::string & dataPath,const std::string & credentialName,uid_t callingUid,HardwareInformation hwInfo,sp<IIdentityCredentialStore> halStoreBinder,sp<IPresentationSession> halSessionBinder,int halApiVersion)70 Credential::Credential(CipherSuite cipherSuite, const std::string& dataPath,
71                        const std::string& credentialName, uid_t callingUid,
72                        HardwareInformation hwInfo, sp<IIdentityCredentialStore> halStoreBinder,
73                        sp<IPresentationSession> halSessionBinder, int halApiVersion)
74     : cipherSuite_(cipherSuite), dataPath_(dataPath), credentialName_(credentialName),
75       callingUid_(callingUid), hwInfo_(std::move(hwInfo)), halStoreBinder_(halStoreBinder),
76       halSessionBinder_(halSessionBinder), halApiVersion_(halApiVersion) {}
77 
~Credential()78 Credential::~Credential() {}
79 
ensureOrReplaceHalBinder()80 Status Credential::ensureOrReplaceHalBinder() {
81     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
82     if (!data->loadFromDisk()) {
83         LOG(ERROR) << "Error loading data for credential";
84         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
85                                                 "Error loading data for credential");
86     }
87 
88     // If we're in a session we explicitly don't get the binder to IIdentityCredential until
89     // it's used in getEntries() which is the only method call allowed for sessions.
90     //
91     // Why? This is because we want to throw the IIdentityCredential object away as soon as it's
92     // used because the HAL only guarantees a single IIdentityCredential object alive at a time
93     // and in a session there may be multiple credentials in play and we want to do multiple
94     // getEntries() calls on all of them.
95     //
96 
97     if (!halSessionBinder_) {
98         sp<IIdentityCredential> halBinder;
99         Status status =
100             halStoreBinder_->getCredential(cipherSuite_, data->getCredentialData(), &halBinder);
101         if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
102             int code = status.serviceSpecificErrorCode();
103             if (code == IIdentityCredentialStore::STATUS_CIPHER_SUITE_NOT_SUPPORTED) {
104                 return halStatusToError(status, ICredentialStore::ERROR_CIPHER_SUITE_NOT_SUPPORTED);
105             }
106         }
107         if (!status.isOk()) {
108             LOG(ERROR) << "Error getting HAL binder";
109             return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC);
110         }
111         halBinder_ = halBinder;
112     }
113 
114     return Status::ok();
115 }
116 
getCredentialKeyCertificateChain(std::vector<uint8_t> * _aidl_return)117 Status Credential::getCredentialKeyCertificateChain(std::vector<uint8_t>* _aidl_return) {
118     if (halSessionBinder_) {
119         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
120                                                 "Cannot be used with session");
121     }
122     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
123     if (!data->loadFromDisk()) {
124         LOG(ERROR) << "Error loading data for credential";
125         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
126                                                 "Error loading data for credential");
127     }
128     *_aidl_return = data->getAttestationCertificate();
129     return Status::ok();
130 }
131 
132 // Returns operation handle
selectAuthKey(bool allowUsingExhaustedKeys,bool allowUsingExpiredKeys,bool incrementUsageCount,int64_t * _aidl_return)133 Status Credential::selectAuthKey(bool allowUsingExhaustedKeys, bool allowUsingExpiredKeys,
134                                  bool incrementUsageCount, int64_t* _aidl_return) {
135     if (halSessionBinder_) {
136         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
137                                                 "Cannot be used with session");
138     }
139     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
140     if (!data->loadFromDisk()) {
141         LOG(ERROR) << "Error loading data for credential";
142         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
143                                                 "Error loading data for credential");
144     }
145 
146     // We just check if a key is available, we actually don't store it since we
147     // don't keep CredentialData around between binder calls.
148     const AuthKeyData* authKey =
149         data->selectAuthKey(allowUsingExhaustedKeys, allowUsingExpiredKeys, incrementUsageCount);
150     if (authKey == nullptr) {
151         return Status::fromServiceSpecificError(
152             ICredentialStore::ERROR_NO_AUTHENTICATION_KEY_AVAILABLE,
153             "No suitable authentication key available");
154     }
155 
156     if (!ensureChallenge()) {
157         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
158                                                 "Error getting challenge (bug in HAL or TA)");
159     }
160     *_aidl_return = selectedChallenge_;
161     return Status::ok();
162 }
163 
ensureChallenge()164 bool Credential::ensureChallenge() {
165     if (selectedChallenge_ != 0) {
166         return true;
167     }
168 
169     int64_t challenge;
170     // If we're in a session, the challenge is selected by the session
171     if (halSessionBinder_) {
172         Status status = halSessionBinder_->getAuthChallenge(&challenge);
173         if (!status.isOk()) {
174             LOG(ERROR) << "Error getting challenge from session: " << status.exceptionMessage();
175             return false;
176         }
177     } else {
178         Status status = halBinder_->createAuthChallenge(&challenge);
179         if (!status.isOk()) {
180             LOG(ERROR) << "Error getting challenge: " << status.exceptionMessage();
181             return false;
182         }
183     }
184     if (challenge == 0) {
185         LOG(ERROR) << "Returned challenge is 0 (bug in HAL or TA)";
186         return false;
187     }
188 
189     selectedChallenge_ = challenge;
190     return true;
191 }
192 
193 // Returns false if an error occurred communicating with keystore.
194 //
getTokensFromKeystore2(uint64_t challenge,uint64_t secureUserId,unsigned int authTokenMaxAgeMillis,AidlHardwareAuthToken & aidlAuthToken,AidlVerificationToken & aidlVerificationToken)195 bool getTokensFromKeystore2(uint64_t challenge, uint64_t secureUserId,
196                             unsigned int authTokenMaxAgeMillis,
197                             AidlHardwareAuthToken& aidlAuthToken,
198                             AidlVerificationToken& aidlVerificationToken) {
199     // try to connect to IKeystoreAuthorization AIDL service first.
200     AIBinder* authzAIBinder = AServiceManager_checkService("android.security.authorization");
201     ::ndk::SpAIBinder authzBinder(authzAIBinder);
202     auto authzService = IKeystoreAuthorization::fromBinder(authzBinder);
203     if (authzService) {
204         AuthorizationTokens authzTokens;
205         auto result = authzService->getAuthTokensForCredStore(challenge, secureUserId,
206                                                               authTokenMaxAgeMillis, &authzTokens);
207         // Convert KeyMint auth token to KeyMaster authtoken, only if tokens are
208         // returned
209         if (result.isOk()) {
210             KeyMintAuthToken keymintAuthToken = authzTokens.authToken;
211             aidlAuthToken.challenge = keymintAuthToken.challenge;
212             aidlAuthToken.userId = keymintAuthToken.userId;
213             aidlAuthToken.authenticatorId = keymintAuthToken.authenticatorId;
214             aidlAuthToken.authenticatorType =
215                 ::android::hardware::keymaster::HardwareAuthenticatorType(
216                     int32_t(keymintAuthToken.authenticatorType));
217             aidlAuthToken.timestamp.milliSeconds = keymintAuthToken.timestamp.milliSeconds;
218             aidlAuthToken.mac = keymintAuthToken.mac;
219 
220             // Convert timestamp token to KeyMaster verification token
221             TimeStampToken timestampToken = authzTokens.timestampToken;
222             aidlVerificationToken.challenge = timestampToken.challenge;
223             aidlVerificationToken.timestamp.milliSeconds = timestampToken.timestamp.milliSeconds;
224             // Legacy verification tokens were always minted by TEE.
225             aidlVerificationToken.securityLevel = SecurityLevel::TRUSTED_ENVIRONMENT;
226             aidlVerificationToken.mac = timestampToken.mac;
227         } else {
228             if (result.getServiceSpecificError() == 0) {
229                 // Here we differentiate the errors occurred during communication
230                 // from the service specific errors.
231                 LOG(ERROR) << "Error getting tokens from keystore2: " << result.getDescription();
232                 return false;
233             } else {
234                 // Log the reason for not receiving auth tokens from keystore2.
235                 LOG(INFO) << "Auth tokens were not received due to: " << result.getDescription();
236             }
237         }
238         return true;
239     } else {
240         LOG(ERROR) << "Error connecting to IKeystoreAuthorization service";
241         return false;
242     }
243 }
244 
getEntries(const vector<uint8_t> & requestMessage,const vector<RequestNamespaceParcel> & requestNamespaces,const vector<uint8_t> & sessionTranscript,const vector<uint8_t> & readerSignature,bool allowUsingExhaustedKeys,bool allowUsingExpiredKeys,bool incrementUsageCount,GetEntriesResultParcel * _aidl_return)245 Status Credential::getEntries(const vector<uint8_t>& requestMessage,
246                               const vector<RequestNamespaceParcel>& requestNamespaces,
247                               const vector<uint8_t>& sessionTranscript,
248                               const vector<uint8_t>& readerSignature, bool allowUsingExhaustedKeys,
249                               bool allowUsingExpiredKeys, bool incrementUsageCount,
250                               GetEntriesResultParcel* _aidl_return) {
251     GetEntriesResultParcel ret;
252 
253     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
254     if (!data->loadFromDisk()) {
255         LOG(ERROR) << "Error loading data for credential";
256         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
257                                                 "Error loading data for credential");
258     }
259 
260     // If used in a session, get the binder on demand...
261     //
262     sp<IIdentityCredential> halBinder = halBinder_;
263     if (halSessionBinder_) {
264         if (halBinder) {
265             LOG(ERROR) << "Unexpected HAL binder for session";
266             return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
267                                                     "Unexpected HAL binder for session");
268         }
269         Status status = halSessionBinder_->getCredential(data->getCredentialData(), &halBinder);
270         if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
271             int code = status.serviceSpecificErrorCode();
272             if (code == IIdentityCredentialStore::STATUS_CIPHER_SUITE_NOT_SUPPORTED) {
273                 return halStatusToError(status, ICredentialStore::ERROR_CIPHER_SUITE_NOT_SUPPORTED);
274             }
275         }
276         if (!status.isOk()) {
277             LOG(ERROR) << "Error getting HAL binder";
278             return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC);
279         }
280     }
281 
282     // Calculate requestCounts ahead of time and be careful not to include
283     // elements that don't exist.
284     //
285     // Also go through and figure out which access control profiles to include
286     // in the startRetrieval() call.
287     vector<int32_t> requestCounts;
288     const vector<SecureAccessControlProfile>& allProfiles = data->getSecureAccessControlProfiles();
289 
290     // We don't support ACP identifiers which isn't in the range 0 to 31. This
291     // guarantee exists so it's feasible to implement the TA part of an Identity
292     // Credential HAL implementation where the TA uses a 32-bit word to indicate
293     // which profiles are authorized.
294     for (const SecureAccessControlProfile& profile : allProfiles) {
295         if (profile.id < 0 || profile.id >= 32) {
296             return Status::fromServiceSpecificError(
297                 ICredentialStore::ERROR_GENERIC,
298                 "Invalid accessProfileId in profile (must be between 0 and 31)");
299         }
300     }
301 
302     vector<bool> includeProfile(32);
303 
304     for (const RequestNamespaceParcel& rns : requestNamespaces) {
305         size_t numEntriesInNsToRequest = 0;
306         for (const RequestEntryParcel& rep : rns.entries) {
307             if (data->hasEntryData(rns.namespaceName, rep.name)) {
308                 numEntriesInNsToRequest++;
309             }
310 
311             optional<EntryData> eData = data->getEntryData(rns.namespaceName, rep.name);
312             if (eData) {
313                 for (int32_t id : eData.value().accessControlProfileIds) {
314                     if (id < 0 || id >= 32) {
315                         LOG(ERROR) << "Invalid accessControlProfileId " << id << " for "
316                                    << rns.namespaceName << ": " << rep.name;
317                         return Status::fromServiceSpecificError(
318                             ICredentialStore::ERROR_GENERIC,
319                             "Invalid accessProfileId in entry (must be between 0 and 31)");
320                     }
321                     includeProfile[id] = true;
322                 }
323             }
324         }
325         requestCounts.push_back(numEntriesInNsToRequest);
326     }
327 
328     // Now that we know which profiles are needed, send only those to the
329     // HAL.
330     vector<SecureAccessControlProfile> selectedProfiles;
331     for (size_t n = 0; n < allProfiles.size(); n++) {
332         if (includeProfile[allProfiles[n].id]) {
333             selectedProfiles.push_back(allProfiles[n]);
334         }
335     }
336 
337     // Calculate the highest [1] non-zero timeout and if user-auth is needed
338     // ... we need this to select an appropriate authToken.
339     //
340     // [1] : Why do we request the highest timeout and not the lowest? Well, we
341     //       return partial results in getEntries e.g. if some data elements
342     //       fail to authorize we'll still return the ones that did not fail. So
343     //       e.g. consider data elements A and B where A has an ACP with 60
344     //       seconds and B has an ACP with 3600 seconds. In this case we'll be
345     //       fine with getting an authToken for e.g. 2400 seconds which would
346     //       mean returning only B.
347     //
348     bool userAuthNeeded = false;
349     unsigned int authTokenMaxAgeMillis = 0;
350     for (auto& profile : selectedProfiles) {
351         if (profile.userAuthenticationRequired) {
352             userAuthNeeded = true;
353             if (profile.timeoutMillis > 0) {
354                 if (profile.timeoutMillis > authTokenMaxAgeMillis) {
355                     authTokenMaxAgeMillis = profile.timeoutMillis;
356                 }
357             }
358         }
359     }
360 
361     // Reset tokens and only get them if they're actually needed, e.g. if user authentication
362     // is needed in any of the access control profiles for data items being requested.
363     //
364     AidlHardwareAuthToken aidlAuthToken;
365     AidlVerificationToken aidlVerificationToken;
366     aidlAuthToken.challenge = 0;
367     aidlAuthToken.userId = 0;
368     aidlAuthToken.authenticatorId = 0;
369     aidlAuthToken.authenticatorType =
370         ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
371     aidlAuthToken.timestamp.milliSeconds = 0;
372     aidlAuthToken.mac.clear();
373     aidlVerificationToken.challenge = 0;
374     aidlVerificationToken.timestamp.milliSeconds = 0;
375     aidlVerificationToken.securityLevel = ::android::hardware::keymaster::SecurityLevel::SOFTWARE;
376     aidlVerificationToken.mac.clear();
377     if (userAuthNeeded) {
378         // If user authentication is needed, always get a challenge from the
379         // HAL/TA since it'll need it to check the returned VerificationToken
380         // for freshness.
381         if (!ensureChallenge()) {
382             return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
383                                                     "Error getting challenge (bug in HAL or TA)");
384         }
385 
386         // Note: if all selected profiles require auth-on-every-presentation
387         // then authTokenMaxAgeMillis will be 0 (because timeoutMillis for each
388         // profile is 0). Which means that keystore will only return an
389         // AuthToken if its challenge matches what we pass, regardless of its
390         // age. This is intended b/c the HAL/TA will check not care about
391         // the age in this case, it only cares that the challenge matches.
392         //
393         // Otherwise, if one or more of the profiles is auth-with-a-timeout then
394         // authTokenMaxAgeMillis will be set to the largest of those
395         // timeouts. We'll get an AuthToken which satisfies this deadline if it
396         // exists. This authToken _may_ have the requested challenge but it's
397         // not a guarantee and it's also not required.
398         //
399 
400         if (!getTokensFromKeystore2(selectedChallenge_, data->getSecureUserId(),
401                                     authTokenMaxAgeMillis, aidlAuthToken, aidlVerificationToken)) {
402             LOG(ERROR) << "Error getting tokens from keystore2";
403             return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
404                                                     "Error getting tokens from keystore2");
405         }
406     }
407 
408     // Reuse the same AuthKey over multiple getEntries() calls.
409     //
410     bool updateUseCountOnDisk = false;
411     if (!selectedAuthKey_) {
412         // Note that the selectAuthKey() method is only called if a CryptoObject is involved at
413         // the Java layer. So we could end up with no previously selected auth key and we may
414         // need one.
415         //
416         const AuthKeyData* authKey = data->selectAuthKey(
417             allowUsingExhaustedKeys, allowUsingExpiredKeys, incrementUsageCount);
418         if (authKey == nullptr) {
419             // If no authKey is available, consider it an error only when a
420             // SessionTranscript was provided.
421             //
422             // We allow no SessionTranscript to be provided because it makes
423             // the API simpler to deal with insofar it can be used without having
424             // to generate any authentication keys.
425             //
426             // In this "no SessionTranscript is provided" mode we don't return
427             // DeviceNameSpaces nor a MAC over DeviceAuthentication so we don't
428             // need a device key.
429             //
430             if (sessionTranscript.size() > 0) {
431                 return Status::fromServiceSpecificError(
432                     ICredentialStore::ERROR_NO_AUTHENTICATION_KEY_AVAILABLE,
433                     "No suitable authentication key available and one is needed");
434             }
435         } else {
436             // We did find an authKey. Store its contents for future getEntries() calls.
437             updateUseCountOnDisk = true;
438             selectedAuthKeySigningKeyBlob_ = authKey->keyBlob;
439             selectedAuthKeyStaticAuthData_ = authKey->staticAuthenticationData;
440         }
441         selectedAuthKey_ = true;
442     }
443 
444     // Pass the HAL enough information to allow calculating the size of
445     // DeviceNameSpaces ahead of time.
446     vector<RequestNamespace> halRequestNamespaces;
447     for (const RequestNamespaceParcel& rns : requestNamespaces) {
448         RequestNamespace ns;
449         ns.namespaceName = rns.namespaceName;
450         for (const RequestEntryParcel& rep : rns.entries) {
451             optional<EntryData> entryData = data->getEntryData(rns.namespaceName, rep.name);
452             if (entryData) {
453                 RequestDataItem di;
454                 di.name = rep.name;
455                 di.size = entryData.value().size;
456                 di.accessControlProfileIds = entryData.value().accessControlProfileIds;
457                 ns.items.push_back(di);
458             }
459         }
460         if (ns.items.size() > 0) {
461             halRequestNamespaces.push_back(ns);
462         }
463     }
464     // This is not catastrophic, we might be dealing with a version 1 implementation which
465     // doesn't have this method.
466     Status status = halBinder->setRequestedNamespaces(halRequestNamespaces);
467     if (!status.isOk()) {
468         LOG(INFO) << "Failed setting expected requested namespaces, assuming V1 HAL "
469                   << "and continuing";
470     }
471 
472     // Pass the verification token. Failure is OK, this method isn't in the V1 HAL.
473     status = halBinder->setVerificationToken(aidlVerificationToken);
474     if (!status.isOk()) {
475         LOG(INFO) << "Failed setting verification token, assuming V1 HAL "
476                   << "and continuing";
477     }
478 
479     status = halBinder->startRetrieval(selectedProfiles, aidlAuthToken, requestMessage,
480                                        selectedAuthKeySigningKeyBlob_, sessionTranscript,
481                                        readerSignature, requestCounts);
482     if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
483         int code = status.serviceSpecificErrorCode();
484         if (code == IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND) {
485             return halStatusToError(status, ICredentialStore::ERROR_EPHEMERAL_PUBLIC_KEY_NOT_FOUND);
486         } else if (code == IIdentityCredentialStore::STATUS_READER_SIGNATURE_CHECK_FAILED) {
487             return halStatusToError(status, ICredentialStore::ERROR_INVALID_READER_SIGNATURE);
488         } else if (code == IIdentityCredentialStore::STATUS_INVALID_ITEMS_REQUEST_MESSAGE) {
489             return halStatusToError(status, ICredentialStore::ERROR_INVALID_ITEMS_REQUEST_MESSAGE);
490         } else if (code == IIdentityCredentialStore::STATUS_SESSION_TRANSCRIPT_MISMATCH) {
491             return halStatusToError(status, ICredentialStore::ERROR_SESSION_TRANSCRIPT_MISMATCH);
492         }
493     }
494     if (!status.isOk()) {
495         return halStatusToGenericError(status);
496     }
497 
498     for (const RequestNamespaceParcel& rns : requestNamespaces) {
499         ResultNamespaceParcel resultNamespaceParcel;
500         resultNamespaceParcel.namespaceName = rns.namespaceName;
501 
502         for (const RequestEntryParcel& rep : rns.entries) {
503             ResultEntryParcel resultEntryParcel;
504             resultEntryParcel.name = rep.name;
505 
506             optional<EntryData> eData = data->getEntryData(rns.namespaceName, rep.name);
507             if (!eData) {
508                 resultEntryParcel.status = STATUS_NO_SUCH_ENTRY;
509                 resultNamespaceParcel.entries.push_back(resultEntryParcel);
510                 continue;
511             }
512 
513             status =
514                 halBinder->startRetrieveEntryValue(rns.namespaceName, rep.name, eData.value().size,
515                                                    eData.value().accessControlProfileIds);
516             if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
517                 int code = status.serviceSpecificErrorCode();
518                 if (code == IIdentityCredentialStore::STATUS_USER_AUTHENTICATION_FAILED) {
519                     resultEntryParcel.status = STATUS_USER_AUTHENTICATION_FAILED;
520                     resultNamespaceParcel.entries.push_back(resultEntryParcel);
521                     continue;
522                 } else if (code == IIdentityCredentialStore::STATUS_READER_AUTHENTICATION_FAILED) {
523                     resultEntryParcel.status = STATUS_READER_AUTHENTICATION_FAILED;
524                     resultNamespaceParcel.entries.push_back(resultEntryParcel);
525                     continue;
526                 } else if (code == IIdentityCredentialStore::STATUS_NOT_IN_REQUEST_MESSAGE) {
527                     resultEntryParcel.status = STATUS_NOT_IN_REQUEST_MESSAGE;
528                     resultNamespaceParcel.entries.push_back(resultEntryParcel);
529                     continue;
530                 } else if (code == IIdentityCredentialStore::STATUS_NO_ACCESS_CONTROL_PROFILES) {
531                     resultEntryParcel.status = STATUS_NO_ACCESS_CONTROL_PROFILES;
532                     resultNamespaceParcel.entries.push_back(resultEntryParcel);
533                     continue;
534                 }
535             }
536             if (!status.isOk()) {
537                 return halStatusToGenericError(status);
538             }
539 
540             vector<uint8_t> value;
541             for (const auto& encryptedChunk : eData.value().encryptedChunks) {
542                 vector<uint8_t> chunk;
543                 status = halBinder->retrieveEntryValue(encryptedChunk, &chunk);
544                 if (!status.isOk()) {
545                     return halStatusToGenericError(status);
546                 }
547                 value.insert(value.end(), chunk.begin(), chunk.end());
548             }
549 
550             resultEntryParcel.status = STATUS_OK;
551             resultEntryParcel.value = value;
552             resultNamespaceParcel.entries.push_back(resultEntryParcel);
553         }
554         ret.resultNamespaces.push_back(resultNamespaceParcel);
555     }
556 
557     // API version 5 (feature version 202301) supports both MAC and ECDSA signature.
558     if (halApiVersion_ >= 5) {
559         status = halBinder->finishRetrievalWithSignature(&ret.mac, &ret.deviceNameSpaces,
560                                                          &ret.signature);
561         if (!status.isOk()) {
562             return halStatusToGenericError(status);
563         }
564     } else {
565         status = halBinder->finishRetrieval(&ret.mac, &ret.deviceNameSpaces);
566         if (!status.isOk()) {
567             return halStatusToGenericError(status);
568         }
569     }
570     ret.staticAuthenticationData = selectedAuthKeyStaticAuthData_;
571 
572     // Ensure useCount is updated on disk.
573     if (updateUseCountOnDisk) {
574         if (!data->saveToDisk()) {
575             return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
576                                                     "Error saving data");
577         }
578     }
579 
580     *_aidl_return = ret;
581     return Status::ok();
582 }
583 
deleteCredential(vector<uint8_t> * _aidl_return)584 Status Credential::deleteCredential(vector<uint8_t>* _aidl_return) {
585     if (halSessionBinder_) {
586         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
587                                                 "Cannot be used with session");
588     }
589 
590     vector<uint8_t> proofOfDeletionSignature;
591 
592     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
593     if (!data->loadFromDisk()) {
594         LOG(ERROR) << "Error loading data for credential";
595         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
596                                                 "Error loading data for credential");
597     }
598 
599     Status status = halBinder_->deleteCredential(&proofOfDeletionSignature);
600     if (!status.isOk()) {
601         return halStatusToGenericError(status);
602     }
603     if (!data->deleteCredential()) {
604         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
605                                                 "Error deleting credential data on disk");
606     }
607     *_aidl_return = proofOfDeletionSignature;
608     return Status::ok();
609 }
610 
deleteWithChallenge(const vector<uint8_t> & challenge,vector<uint8_t> * _aidl_return)611 Status Credential::deleteWithChallenge(const vector<uint8_t>& challenge,
612                                        vector<uint8_t>* _aidl_return) {
613     if (halApiVersion_ < 3) {
614         return Status::fromServiceSpecificError(ICredentialStore::ERROR_NOT_SUPPORTED,
615                                                 "Not implemented by HAL");
616     }
617 
618     if (halSessionBinder_) {
619         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
620                                                 "Cannot be used with session");
621     }
622 
623     vector<uint8_t> proofOfDeletionSignature;
624 
625     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
626     if (!data->loadFromDisk()) {
627         LOG(ERROR) << "Error loading data for credential";
628         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
629                                                 "Error loading data for credential");
630     }
631 
632     Status status = halBinder_->deleteCredentialWithChallenge(challenge, &proofOfDeletionSignature);
633     if (!status.isOk()) {
634         return halStatusToGenericError(status);
635     }
636     if (!data->deleteCredential()) {
637         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
638                                                 "Error deleting credential data on disk");
639     }
640     *_aidl_return = proofOfDeletionSignature;
641     return Status::ok();
642 }
643 
proveOwnership(const vector<uint8_t> & challenge,vector<uint8_t> * _aidl_return)644 Status Credential::proveOwnership(const vector<uint8_t>& challenge, vector<uint8_t>* _aidl_return) {
645     if (halApiVersion_ < 3) {
646         return Status::fromServiceSpecificError(ICredentialStore::ERROR_NOT_SUPPORTED,
647                                                 "Not implemented by HAL");
648     }
649 
650     if (halSessionBinder_) {
651         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
652                                                 "Cannot be used with session");
653     }
654 
655     vector<uint8_t> proofOfOwnershipSignature;
656     Status status = halBinder_->proveOwnership(challenge, &proofOfOwnershipSignature);
657     if (!status.isOk()) {
658         return halStatusToGenericError(status);
659     }
660     *_aidl_return = proofOfOwnershipSignature;
661     return Status::ok();
662 }
663 
createEphemeralKeyPair(vector<uint8_t> * _aidl_return)664 Status Credential::createEphemeralKeyPair(vector<uint8_t>* _aidl_return) {
665     if (halSessionBinder_) {
666         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
667                                                 "Cannot be used with session");
668     }
669 
670     vector<uint8_t> keyPair;
671     Status status = halBinder_->createEphemeralKeyPair(&keyPair);
672     if (!status.isOk()) {
673         return halStatusToGenericError(status);
674     }
675 
676     time_t nowSeconds = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
677     time_t validityNotBefore = nowSeconds;
678     time_t validityNotAfter = nowSeconds + 24 * 60 * 60;
679     optional<vector<uint8_t>> pkcs12Bytes = ecKeyPairGetPkcs12(keyPair,
680                                                                "ephemeralKey",  // Alias for key
681                                                                "0",  // Serial, as a decimal number
682                                                                "Credstore",      // Issuer
683                                                                "Ephemeral Key",  // Subject
684                                                                validityNotBefore, validityNotAfter);
685     if (!pkcs12Bytes) {
686         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
687                                                 "Error creating PKCS#12 structure for key pair");
688     }
689     *_aidl_return = pkcs12Bytes.value();
690     return Status::ok();
691 }
692 
setReaderEphemeralPublicKey(const vector<uint8_t> & publicKey)693 Status Credential::setReaderEphemeralPublicKey(const vector<uint8_t>& publicKey) {
694     if (halSessionBinder_) {
695         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
696                                                 "Cannot be used with session");
697     }
698 
699     Status status = halBinder_->setReaderEphemeralPublicKey(publicKey);
700     if (!status.isOk()) {
701         return halStatusToGenericError(status);
702     }
703     return Status::ok();
704 }
705 
setAvailableAuthenticationKeys(int32_t keyCount,int32_t maxUsesPerKey,int64_t minValidTimeMillis)706 Status Credential::setAvailableAuthenticationKeys(int32_t keyCount, int32_t maxUsesPerKey,
707                                                   int64_t minValidTimeMillis) {
708     if (halSessionBinder_) {
709         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
710                                                 "Cannot be used with session");
711     }
712 
713     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
714     if (!data->loadFromDisk()) {
715         LOG(ERROR) << "Error loading data for credential";
716         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
717                                                 "Error loading data for credential");
718     }
719     data->setAvailableAuthenticationKeys(keyCount, maxUsesPerKey, minValidTimeMillis);
720     if (!data->saveToDisk()) {
721         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
722                                                 "Error saving data");
723     }
724     return Status::ok();
725 }
726 
getAuthKeysNeedingCertification(vector<AuthKeyParcel> * _aidl_return)727 Status Credential::getAuthKeysNeedingCertification(vector<AuthKeyParcel>* _aidl_return) {
728     if (halSessionBinder_) {
729         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
730                                                 "Cannot be used with session");
731     }
732 
733     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
734     if (!data->loadFromDisk()) {
735         LOG(ERROR) << "Error loading data for credential";
736         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
737                                                 "Error loading data for credential");
738     }
739     optional<vector<vector<uint8_t>>> keysNeedingCert =
740         data->getAuthKeysNeedingCertification(halBinder_);
741     if (!keysNeedingCert) {
742         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
743                                                 "Error getting auth keys neededing certification");
744     }
745     vector<AuthKeyParcel> authKeyParcels;
746     for (const vector<uint8_t>& key : keysNeedingCert.value()) {
747         AuthKeyParcel authKeyParcel;
748         authKeyParcel.x509cert = key;
749         authKeyParcels.push_back(authKeyParcel);
750     }
751     if (!data->saveToDisk()) {
752         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
753                                                 "Error saving data");
754     }
755     *_aidl_return = authKeyParcels;
756     return Status::ok();
757 }
758 
storeStaticAuthenticationData(const AuthKeyParcel & authenticationKey,const vector<uint8_t> & staticAuthData)759 Status Credential::storeStaticAuthenticationData(const AuthKeyParcel& authenticationKey,
760                                                  const vector<uint8_t>& staticAuthData) {
761     if (halSessionBinder_) {
762         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
763                                                 "Cannot be used with session");
764     }
765 
766     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
767     if (!data->loadFromDisk()) {
768         LOG(ERROR) << "Error loading data for credential";
769         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
770                                                 "Error loading data for credential");
771     }
772     if (!data->storeStaticAuthenticationData(authenticationKey.x509cert,
773                                              std::numeric_limits<int64_t>::max(), staticAuthData)) {
774         return Status::fromServiceSpecificError(
775             ICredentialStore::ERROR_AUTHENTICATION_KEY_NOT_FOUND,
776             "Error finding authentication key to store static "
777             "authentication data for");
778     }
779     if (!data->saveToDisk()) {
780         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
781                                                 "Error saving data");
782     }
783     return Status::ok();
784 }
785 
786 Status
storeStaticAuthenticationDataWithExpiration(const AuthKeyParcel & authenticationKey,int64_t expirationDateMillisSinceEpoch,const vector<uint8_t> & staticAuthData)787 Credential::storeStaticAuthenticationDataWithExpiration(const AuthKeyParcel& authenticationKey,
788                                                         int64_t expirationDateMillisSinceEpoch,
789                                                         const vector<uint8_t>& staticAuthData) {
790     if (halSessionBinder_) {
791         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
792                                                 "Cannot be used with session");
793     }
794 
795     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
796     if (!data->loadFromDisk()) {
797         LOG(ERROR) << "Error loading data for credential";
798         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
799                                                 "Error loading data for credential");
800     }
801     if (!data->storeStaticAuthenticationData(authenticationKey.x509cert,
802                                              expirationDateMillisSinceEpoch, staticAuthData)) {
803         return Status::fromServiceSpecificError(
804             ICredentialStore::ERROR_AUTHENTICATION_KEY_NOT_FOUND,
805             "Error finding authentication key to store static "
806             "authentication data for");
807     }
808     if (!data->saveToDisk()) {
809         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
810                                                 "Error saving data");
811     }
812     return Status::ok();
813 }
814 
getAuthenticationDataUsageCount(vector<int32_t> * _aidl_return)815 Status Credential::getAuthenticationDataUsageCount(vector<int32_t>* _aidl_return) {
816     if (halSessionBinder_) {
817         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
818                                                 "Cannot be used with session");
819     }
820 
821     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
822     if (!data->loadFromDisk()) {
823         LOG(ERROR) << "Error loading data for credential";
824         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
825                                                 "Error loading data for credential");
826     }
827     const vector<AuthKeyData>& authKeyDatas = data->getAuthKeyDatas();
828     vector<int32_t> ret;
829     for (const AuthKeyData& authKeyData : authKeyDatas) {
830         ret.push_back(authKeyData.useCount);
831     }
832     *_aidl_return = ret;
833     return Status::ok();
834 }
835 
getAuthenticationDataExpirations(vector<int64_t> * _aidl_return)836 Status Credential::getAuthenticationDataExpirations(vector<int64_t>* _aidl_return) {
837     if (halSessionBinder_) {
838         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
839                                                 "Cannot be used with session");
840     }
841 
842     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
843     if (!data->loadFromDisk()) {
844         LOG(ERROR) << "Error loading data for credential";
845         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
846                                                 "Error loading data for credential");
847     }
848     const vector<AuthKeyData>& authKeyDatas = data->getAuthKeyDatas();
849     vector<int64_t> ret;
850     ret.reserve(authKeyDatas.size());
851     for (const AuthKeyData& authKeyData : authKeyDatas) {
852         // Note: value is INT64_MAX if expiration date is not set.
853         ret.push_back(authKeyData.expirationDateMillisSinceEpoch);
854     }
855     *_aidl_return = ret;
856     return Status::ok();
857 }
858 
extractDocType(const vector<uint8_t> & credentialData)859 optional<string> extractDocType(const vector<uint8_t>& credentialData) {
860     auto [item, _ /* newPos */, message] = cppbor::parse(credentialData);
861     if (item == nullptr) {
862         LOG(ERROR) << "CredentialData is not valid CBOR: " << message;
863         return {};
864     }
865     const cppbor::Array* array = item->asArray();
866     if (array == nullptr || array->size() < 1) {
867         LOG(ERROR) << "CredentialData array with at least one element";
868         return {};
869     }
870     const cppbor::Tstr* tstr = ((*array)[0])->asTstr();
871     if (tstr == nullptr) {
872         LOG(ERROR) << "First item in CredentialData is not a string";
873         return {};
874     }
875     return tstr->value();
876 }
877 
update(sp<IWritableCredential> * _aidl_return)878 Status Credential::update(sp<IWritableCredential>* _aidl_return) {
879     if (halApiVersion_ < 3) {
880         return Status::fromServiceSpecificError(ICredentialStore::ERROR_NOT_SUPPORTED,
881                                                 "Not implemented by HAL");
882     }
883 
884     if (halSessionBinder_) {
885         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
886                                                 "Cannot be used with session");
887     }
888 
889     sp<CredentialData> data = new CredentialData(dataPath_, callingUid_, credentialName_);
890     if (!data->loadFromDisk()) {
891         LOG(ERROR) << "Error loading data for credential";
892         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
893                                                 "Error loading data for credential");
894     }
895 
896     sp<IWritableIdentityCredential> halWritableCredential;
897     Status status = halBinder_->updateCredential(&halWritableCredential);
898     if (!status.isOk()) {
899         return halStatusToGenericError(status);
900     }
901 
902     optional<string> docType = extractDocType(data->getCredentialData());
903     if (!docType) {
904         return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
905                                                 "Unable to extract DocType from CredentialData");
906     }
907 
908     // NOTE: The caller is expected to call WritableCredential::personalize() which will
909     // write brand new data to disk, specifically it will overwrite any data already
910     // have _including_ authentication keys.
911     //
912     // It is because of this we need to set the CredentialKey certificate chain,
913     // keyCount, and maxUsesPerKey below.
914     sp<WritableCredential> writableCredential = new WritableCredential(
915         dataPath_, credentialName_, docType.value(), true, hwInfo_, halWritableCredential);
916 
917     writableCredential->setAttestationCertificate(data->getAttestationCertificate());
918     auto [keyCount, maxUsesPerKey, minValidTimeMillis] = data->getAvailableAuthenticationKeys();
919     writableCredential->setAvailableAuthenticationKeys(keyCount, maxUsesPerKey, minValidTimeMillis);
920 
921     // Because its data has changed, we need to replace the binder for the
922     // IIdentityCredential when the credential has been updated... otherwise the
923     // remote object will have stale data for future calls, for example
924     // getAuthKeysNeedingCertification().
925     //
926     // The way this is implemented is that setCredentialToReloadWhenUpdated()
927     // instructs the WritableCredential to call writableCredentialPersonalized()
928     // on |this|.
929     //
930     //
931     writableCredential->setCredentialToReloadWhenUpdated(this);
932 
933     *_aidl_return = writableCredential;
934     return Status::ok();
935 }
936 
writableCredentialPersonalized()937 void Credential::writableCredentialPersonalized() {
938     Status status = ensureOrReplaceHalBinder();
939     if (!status.isOk()) {
940         LOG(ERROR) << "Error reloading credential";
941     }
942 }
943 
944 }  // namespace identity
945 }  // namespace security
946 }  // namespace android
947