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