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