blob: 59a4d81e776ef172dd1e72f4aca82d2cbfaad4c5 [file] [log] [blame]
David Zeuthenab3e5652019-10-28 13:32:48 -04001/*
2 * Copyright (c) 2019, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "Credential"
18
19#include <android-base/logging.h>
20
21#include <android/hardware/identity/support/IdentityCredentialSupport.h>
22
23#include <android/security/identity/ICredentialStore.h>
24
David Zeuthen59102f32020-05-08 10:58:09 -040025#include <android/security/keystore/BnCredstoreTokenCallback.h>
David Zeuthenab3e5652019-10-28 13:32:48 -040026#include <android/security/keystore/IKeystoreService.h>
27#include <binder/IPCThreadState.h>
28#include <binder/IServiceManager.h>
29#include <keymasterV4_0/keymaster_utils.h>
30
31#include <cppbor.h>
32#include <cppbor_parse.h>
David Zeuthen59102f32020-05-08 10:58:09 -040033#include <future>
34#include <tuple>
David Zeuthenab3e5652019-10-28 13:32:48 -040035
36#include "Credential.h"
37#include "CredentialData.h"
38#include "Util.h"
39
40namespace android {
41namespace security {
42namespace identity {
43
44using std::optional;
David Zeuthen59102f32020-05-08 10:58:09 -040045using std::promise;
46using std::tuple;
David Zeuthenab3e5652019-10-28 13:32:48 -040047
48using android::security::keystore::IKeystoreService;
49
David Zeuthenab3e5652019-10-28 13:32:48 -040050using ::android::hardware::identity::support::ecKeyPairGetPkcs12;
51using ::android::hardware::identity::support::ecKeyPairGetPrivateKey;
52using ::android::hardware::identity::support::ecKeyPairGetPublicKey;
53using ::android::hardware::identity::support::sha256;
54
55using android::hardware::keymaster::V4_0::HardwareAuthToken;
David Zeuthen59102f32020-05-08 10:58:09 -040056using android::hardware::keymaster::V4_0::VerificationToken;
David Zeuthena6f9fba2020-02-11 22:08:27 -050057using AidlHardwareAuthToken = android::hardware::keymaster::HardwareAuthToken;
David Zeuthen59102f32020-05-08 10:58:09 -040058using AidlVerificationToken = android::hardware::keymaster::VerificationToken;
David Zeuthenab3e5652019-10-28 13:32:48 -040059
David Zeuthena6f9fba2020-02-11 22:08:27 -050060Credential::Credential(CipherSuite cipherSuite, const std::string& dataPath,
61 const std::string& credentialName)
62 : cipherSuite_(cipherSuite), dataPath_(dataPath), credentialName_(credentialName) {}
David Zeuthenab3e5652019-10-28 13:32:48 -040063
64Credential::~Credential() {}
65
66Status Credential::loadCredential(sp<IIdentityCredentialStore> halStoreBinder) {
67 uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
68 sp<CredentialData> data = new CredentialData(dataPath_, callingUid, credentialName_);
69 if (!data->loadFromDisk()) {
70 LOG(ERROR) << "Error loading data for credential";
71 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
72 "Error loading data for credential");
73 }
74
75 data_ = data;
76
David Zeuthenab3e5652019-10-28 13:32:48 -040077 sp<IIdentityCredential> halBinder;
David Zeuthena6f9fba2020-02-11 22:08:27 -050078 Status status =
79 halStoreBinder->getCredential(cipherSuite_, data_->getCredentialData(), &halBinder);
80 if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
81 int code = status.serviceSpecificErrorCode();
82 if (code == IIdentityCredentialStore::STATUS_CIPHER_SUITE_NOT_SUPPORTED) {
83 return halStatusToError(status, ICredentialStore::ERROR_CIPHER_SUITE_NOT_SUPPORTED);
84 }
85 }
86 if (!status.isOk()) {
David Zeuthenab3e5652019-10-28 13:32:48 -040087 LOG(ERROR) << "Error getting HAL binder";
88 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC);
89 }
90
91 halBinder_ = halBinder;
92
93 return Status::ok();
94}
95
96Status Credential::getCredentialKeyCertificateChain(std::vector<uint8_t>* _aidl_return) {
97 *_aidl_return = data_->getAttestationCertificate();
98 return Status::ok();
99}
100
101// Returns operation handle
102Status Credential::selectAuthKey(bool allowUsingExhaustedKeys, int64_t* _aidl_return) {
103
104 selectedAuthKey_ = data_->selectAuthKey(allowUsingExhaustedKeys);
105 if (selectedAuthKey_ == nullptr) {
106 return Status::fromServiceSpecificError(
107 ICredentialStore::ERROR_NO_AUTHENTICATION_KEY_AVAILABLE,
108 "No suitable authentication key available");
109 }
110
David Zeuthena6f9fba2020-02-11 22:08:27 -0500111 int64_t challenge;
112 Status status = halBinder_->createAuthChallenge(&challenge);
113 if (!status.isOk()) {
114 return halStatusToGenericError(status);
David Zeuthenab3e5652019-10-28 13:32:48 -0400115 }
116 if (challenge == 0) {
117 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
118 "Returned challenge is 0 (bug in HAL or TA)");
119 }
120
121 selectedChallenge_ = challenge;
122 *_aidl_return = challenge;
123 return Status::ok();
124}
125
David Zeuthen59102f32020-05-08 10:58:09 -0400126class CredstoreTokenCallback : public android::security::keystore::BnCredstoreTokenCallback,
127 public promise<tuple<bool, vector<uint8_t>, vector<uint8_t>>> {
128 public:
129 CredstoreTokenCallback() {}
130 virtual Status onFinished(bool success, const vector<uint8_t>& authToken,
131 const vector<uint8_t>& verificationToken) override {
132 this->set_value({success, authToken, verificationToken});
133 return Status::ok();
134 }
135};
136
David Zeuthenab3e5652019-10-28 13:32:48 -0400137// Returns false if an error occurred communicating with keystore.
138//
David Zeuthen59102f32020-05-08 10:58:09 -0400139bool getTokensFromKeystore(uint64_t challenge, uint64_t secureUserId,
140 unsigned int authTokenMaxAgeMillis, vector<uint8_t>& authToken,
141 vector<uint8_t>& verificationToken) {
David Zeuthenab3e5652019-10-28 13:32:48 -0400142 sp<IServiceManager> sm = defaultServiceManager();
143 sp<IBinder> binder = sm->getService(String16("android.security.keystore"));
144 sp<IKeystoreService> keystore = interface_cast<IKeystoreService>(binder);
145 if (keystore == nullptr) {
146 return false;
147 }
148
David Zeuthen59102f32020-05-08 10:58:09 -0400149 sp<CredstoreTokenCallback> callback = new CredstoreTokenCallback();
150 auto future = callback->get_future();
151
152 Status status =
153 keystore->getTokensForCredstore(challenge, secureUserId, authTokenMaxAgeMillis, callback);
154 if (!status.isOk()) {
155 return false;
156 }
157
158 auto fstatus = future.wait_for(std::chrono::milliseconds(5000));
159 if (fstatus != std::future_status::ready) {
160 LOG(ERROR) << "Waited 5 seconds from tokens for credstore, aborting";
161 return false;
162 }
163 auto [success, returnedAuthToken, returnedVerificationToken] = future.get();
164 if (!success) {
165 LOG(ERROR) << "Error getting tokens from credstore";
David Zeuthenab3e5652019-10-28 13:32:48 -0400166 return false;
167 }
168 authToken = returnedAuthToken;
David Zeuthen59102f32020-05-08 10:58:09 -0400169 verificationToken = returnedVerificationToken;
David Zeuthenab3e5652019-10-28 13:32:48 -0400170 return true;
171}
172
173Status Credential::getEntries(const vector<uint8_t>& requestMessage,
174 const vector<RequestNamespaceParcel>& requestNamespaces,
175 const vector<uint8_t>& sessionTranscript,
176 const vector<uint8_t>& readerSignature, bool allowUsingExhaustedKeys,
177 GetEntriesResultParcel* _aidl_return) {
178 GetEntriesResultParcel ret;
179
180 // Calculate requestCounts ahead of time and be careful not to include
181 // elements that don't exist.
182 //
183 // Also go through and figure out which access control profiles to include
184 // in the startRetrieval() call.
David Zeuthena6f9fba2020-02-11 22:08:27 -0500185 vector<int32_t> requestCounts;
David Zeuthenab3e5652019-10-28 13:32:48 -0400186 const vector<SecureAccessControlProfile>& allProfiles = data_->getSecureAccessControlProfiles();
187 vector<bool> includeProfile(allProfiles.size());
188 for (const RequestNamespaceParcel& rns : requestNamespaces) {
189 size_t numEntriesInNsToRequest = 0;
190 for (const RequestEntryParcel& rep : rns.entries) {
191 if (data_->hasEntryData(rns.namespaceName, rep.name)) {
192 numEntriesInNsToRequest++;
193 }
194
195 optional<EntryData> data = data_->getEntryData(rns.namespaceName, rep.name);
196 if (data) {
David Zeuthena6f9fba2020-02-11 22:08:27 -0500197 for (int32_t id : data.value().accessControlProfileIds) {
198 if (id >= int32_t(includeProfile.size())) {
David Zeuthenab3e5652019-10-28 13:32:48 -0400199 LOG(ERROR) << "Invalid accessControlProfileId " << id << " for "
200 << rns.namespaceName << ": " << rep.name;
201 return Status::fromServiceSpecificError(
202 ICredentialStore::ERROR_GENERIC, "Invalid accessProfileId for entry");
203 }
204 includeProfile[id] = true;
205 }
206 }
207 }
208 requestCounts.push_back(numEntriesInNsToRequest);
209 }
210
211 // Now that we know which profiles are needed, send only those to the
212 // HAL.
213 vector<SecureAccessControlProfile> selectedProfiles;
214 for (size_t n = 0; n < allProfiles.size(); n++) {
215 if (includeProfile[n]) {
216 selectedProfiles.push_back(allProfiles[n]);
217 }
218 }
219
220 // Calculate the highest [1] non-zero timeout and if user-auth is needed
221 // ... we need this to select an appropriate authToken.
222 //
223 // [1] : Why do we request the highest timeout and not the lowest? Well, we
224 // return partial results in getEntries e.g. if some data elements
225 // fail to authorize we'll still return the ones that did not fail. So
226 // e.g. consider data elements A and B where A has an ACP with 60
227 // seconds and B has an ACP with 3600 seconds. In this case we'll be
228 // fine with getting an authToken for e.g. 2400 seconds which would
229 // mean returning only B.
230 //
231 bool userAuthNeeded = false;
232 unsigned int authTokenMaxAgeMillis = 0;
233 for (auto& profile : selectedProfiles) {
234 if (profile.userAuthenticationRequired) {
235 userAuthNeeded = true;
236 if (profile.timeoutMillis > 0) {
237 if (profile.timeoutMillis > authTokenMaxAgeMillis) {
238 authTokenMaxAgeMillis = profile.timeoutMillis;
239 }
240 }
241 }
242 }
243
244 // If requesting a challenge-based authToken the idea is that authentication
245 // happens as part of the transaction. As such, authTokenMaxAgeMillis should
246 // be nearly zero. We'll use 10 seconds for this.
247 if (userAuthNeeded && selectedChallenge_ != 0) {
248 authTokenMaxAgeMillis = 10 * 1000;
249 }
250
David Zeuthen59102f32020-05-08 10:58:09 -0400251 // Reset tokens and only get them if they're actually needed, e.g. if user authentication
252 // is needed in any of the access control profiles for data items being requested.
253 //
David Zeuthena6f9fba2020-02-11 22:08:27 -0500254 AidlHardwareAuthToken aidlAuthToken;
David Zeuthen59102f32020-05-08 10:58:09 -0400255 AidlVerificationToken aidlVerificationToken;
256 aidlAuthToken.challenge = 0;
257 aidlAuthToken.userId = 0;
258 aidlAuthToken.authenticatorId = 0;
259 aidlAuthToken.authenticatorType =
260 ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
261 aidlAuthToken.timestamp.milliSeconds = 0;
262 aidlAuthToken.mac.clear();
263 aidlVerificationToken.challenge = 0;
264 aidlVerificationToken.timestamp.milliSeconds = 0;
265 aidlVerificationToken.securityLevel = ::android::hardware::keymaster::SecurityLevel::SOFTWARE;
266 aidlVerificationToken.mac.clear();
David Zeuthenab3e5652019-10-28 13:32:48 -0400267 if (userAuthNeeded) {
268 vector<uint8_t> authTokenBytes;
David Zeuthen59102f32020-05-08 10:58:09 -0400269 vector<uint8_t> verificationTokenBytes;
270 if (!getTokensFromKeystore(selectedChallenge_, data_->getSecureUserId(),
271 authTokenMaxAgeMillis, authTokenBytes, verificationTokenBytes)) {
272 LOG(ERROR) << "Error getting tokens from keystore";
David Zeuthenab3e5652019-10-28 13:32:48 -0400273 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
David Zeuthen59102f32020-05-08 10:58:09 -0400274 "Error getting tokens from keystore");
David Zeuthenab3e5652019-10-28 13:32:48 -0400275 }
David Zeuthen59102f32020-05-08 10:58:09 -0400276
277 // It's entirely possible getTokensFromKeystore() succeeded but didn't
278 // return any tokens (in which case the returned byte-vectors are
279 // empty). For example, this can happen if no auth token is available
280 // which satifies e.g. |authTokenMaxAgeMillis|.
281 //
David Zeuthenab3e5652019-10-28 13:32:48 -0400282 if (authTokenBytes.size() > 0) {
David Zeuthena6f9fba2020-02-11 22:08:27 -0500283 HardwareAuthToken authToken =
David Zeuthenab3e5652019-10-28 13:32:48 -0400284 android::hardware::keymaster::V4_0::support::hidlVec2AuthToken(authTokenBytes);
David Zeuthena6f9fba2020-02-11 22:08:27 -0500285 // Convert from HIDL to AIDL...
286 aidlAuthToken.challenge = int64_t(authToken.challenge);
287 aidlAuthToken.userId = int64_t(authToken.userId);
288 aidlAuthToken.authenticatorId = int64_t(authToken.authenticatorId);
289 aidlAuthToken.authenticatorType =
290 ::android::hardware::keymaster::HardwareAuthenticatorType(
291 int32_t(authToken.authenticatorType));
292 aidlAuthToken.timestamp.milliSeconds = int64_t(authToken.timestamp);
293 aidlAuthToken.mac = authToken.mac;
David Zeuthenab3e5652019-10-28 13:32:48 -0400294 }
David Zeuthen59102f32020-05-08 10:58:09 -0400295
296 if (verificationTokenBytes.size() > 0) {
297 optional<VerificationToken> token =
298 android::hardware::keymaster::V4_0::support::deserializeVerificationToken(
299 verificationTokenBytes);
300 if (!token) {
301 LOG(ERROR) << "Error deserializing verification token";
302 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
303 "Error deserializing verification token");
304 }
305 aidlVerificationToken.challenge = token->challenge;
306 aidlVerificationToken.timestamp.milliSeconds = token->timestamp;
307 aidlVerificationToken.securityLevel =
308 ::android::hardware::keymaster::SecurityLevel(token->securityLevel);
309 aidlVerificationToken.mac = token->mac;
310 }
David Zeuthenab3e5652019-10-28 13:32:48 -0400311 }
312
David Zeuthen55975ec2020-02-27 14:28:18 -0500313 // Note that the selectAuthKey() method is only called if a CryptoObject is involved at
314 // the Java layer. So we could end up with no previously selected auth key and we may
315 // need one.
316 const AuthKeyData* authKey = selectedAuthKey_;
317 if (sessionTranscript.size() > 0) {
318 if (authKey == nullptr) {
319 authKey = data_->selectAuthKey(allowUsingExhaustedKeys);
320 if (authKey == nullptr) {
321 return Status::fromServiceSpecificError(
322 ICredentialStore::ERROR_NO_AUTHENTICATION_KEY_AVAILABLE,
323 "No suitable authentication key available");
324 }
325 }
326 }
327 vector<uint8_t> signingKeyBlob;
328 if (authKey != nullptr) {
329 signingKeyBlob = authKey->keyBlob;
330 }
331
David Zeuthene2a78a42020-04-27 13:34:38 -0400332 // Pass the HAL enough information to allow calculating the size of
333 // DeviceNameSpaces ahead of time.
334 vector<RequestNamespace> halRequestNamespaces;
335 for (const RequestNamespaceParcel& rns : requestNamespaces) {
336 RequestNamespace ns;
337 ns.namespaceName = rns.namespaceName;
338 for (const RequestEntryParcel& rep : rns.entries) {
339 optional<EntryData> entryData = data_->getEntryData(rns.namespaceName, rep.name);
340 if (entryData) {
341 RequestDataItem di;
342 di.name = rep.name;
343 di.size = entryData.value().size;
344 di.accessControlProfileIds = entryData.value().accessControlProfileIds;
345 ns.items.push_back(di);
346 }
347 }
348 if (ns.items.size() > 0) {
349 halRequestNamespaces.push_back(ns);
350 }
351 }
352 // This is not catastrophic, we might be dealing with a version 1 implementation which
353 // doesn't have this method.
354 Status status = halBinder_->setRequestedNamespaces(halRequestNamespaces);
355 if (!status.isOk()) {
David Zeuthen59102f32020-05-08 10:58:09 -0400356 LOG(INFO) << "Failed setting expected requested namespaces, assuming V1 HAL "
357 << "and continuing";
358 }
359
360 // Pass the verification token. Failure is OK, this method isn't in the V1 HAL.
361 status = halBinder_->setVerificationToken(aidlVerificationToken);
362 if (!status.isOk()) {
363 LOG(INFO) << "Failed setting verification token, assuming V1 HAL "
David Zeuthene2a78a42020-04-27 13:34:38 -0400364 << "and continuing";
365 }
366
367 status =
David Zeuthen55975ec2020-02-27 14:28:18 -0500368 halBinder_->startRetrieval(selectedProfiles, aidlAuthToken, requestMessage, signingKeyBlob,
369 sessionTranscript, readerSignature, requestCounts);
David Zeuthena6f9fba2020-02-11 22:08:27 -0500370 if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
371 int code = status.serviceSpecificErrorCode();
372 if (code == IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND) {
373 return halStatusToError(status, ICredentialStore::ERROR_EPHEMERAL_PUBLIC_KEY_NOT_FOUND);
374 } else if (code == IIdentityCredentialStore::STATUS_READER_SIGNATURE_CHECK_FAILED) {
375 return halStatusToError(status, ICredentialStore::ERROR_INVALID_READER_SIGNATURE);
376 } else if (code == IIdentityCredentialStore::STATUS_INVALID_ITEMS_REQUEST_MESSAGE) {
377 return halStatusToError(status, ICredentialStore::ERROR_INVALID_ITEMS_REQUEST_MESSAGE);
378 } else if (code == IIdentityCredentialStore::STATUS_SESSION_TRANSCRIPT_MISMATCH) {
379 return halStatusToError(status, ICredentialStore::ERROR_SESSION_TRANSCRIPT_MISMATCH);
380 }
381 }
382 if (!status.isOk()) {
383 return halStatusToGenericError(status);
David Zeuthenab3e5652019-10-28 13:32:48 -0400384 }
385
386 for (const RequestNamespaceParcel& rns : requestNamespaces) {
387 ResultNamespaceParcel resultNamespaceParcel;
388 resultNamespaceParcel.namespaceName = rns.namespaceName;
389
390 for (const RequestEntryParcel& rep : rns.entries) {
391 ResultEntryParcel resultEntryParcel;
392 resultEntryParcel.name = rep.name;
393
394 optional<EntryData> data = data_->getEntryData(rns.namespaceName, rep.name);
395 if (!data) {
396 resultEntryParcel.status = STATUS_NO_SUCH_ENTRY;
397 resultNamespaceParcel.entries.push_back(resultEntryParcel);
398 continue;
399 }
400
David Zeuthena6f9fba2020-02-11 22:08:27 -0500401 status =
402 halBinder_->startRetrieveEntryValue(rns.namespaceName, rep.name, data.value().size,
403 data.value().accessControlProfileIds);
404 if (!status.isOk() && status.exceptionCode() == binder::Status::EX_SERVICE_SPECIFIC) {
405 int code = status.serviceSpecificErrorCode();
406 if (code == IIdentityCredentialStore::STATUS_USER_AUTHENTICATION_FAILED) {
407 resultEntryParcel.status = STATUS_USER_AUTHENTICATION_FAILED;
408 resultNamespaceParcel.entries.push_back(resultEntryParcel);
409 continue;
410 } else if (code == IIdentityCredentialStore::STATUS_READER_AUTHENTICATION_FAILED) {
411 resultEntryParcel.status = STATUS_READER_AUTHENTICATION_FAILED;
412 resultNamespaceParcel.entries.push_back(resultEntryParcel);
413 continue;
414 } else if (code == IIdentityCredentialStore::STATUS_NOT_IN_REQUEST_MESSAGE) {
415 resultEntryParcel.status = STATUS_NOT_IN_REQUEST_MESSAGE;
416 resultNamespaceParcel.entries.push_back(resultEntryParcel);
417 continue;
418 } else if (code == IIdentityCredentialStore::STATUS_NO_ACCESS_CONTROL_PROFILES) {
419 resultEntryParcel.status = STATUS_NO_ACCESS_CONTROL_PROFILES;
420 resultNamespaceParcel.entries.push_back(resultEntryParcel);
421 continue;
422 }
423 }
424 if (!status.isOk()) {
425 return halStatusToGenericError(status);
David Zeuthenab3e5652019-10-28 13:32:48 -0400426 }
427
428 vector<uint8_t> value;
429 for (const auto& encryptedChunk : data.value().encryptedChunks) {
David Zeuthena6f9fba2020-02-11 22:08:27 -0500430 vector<uint8_t> chunk;
431 status = halBinder_->retrieveEntryValue(encryptedChunk, &chunk);
432 if (!status.isOk()) {
433 return halStatusToGenericError(status);
David Zeuthenab3e5652019-10-28 13:32:48 -0400434 }
David Zeuthena6f9fba2020-02-11 22:08:27 -0500435 value.insert(value.end(), chunk.begin(), chunk.end());
David Zeuthenab3e5652019-10-28 13:32:48 -0400436 }
437
438 resultEntryParcel.status = STATUS_OK;
439 resultEntryParcel.value = value;
440 resultNamespaceParcel.entries.push_back(resultEntryParcel);
441 }
442 ret.resultNamespaces.push_back(resultNamespaceParcel);
443 }
444
David Zeuthen55975ec2020-02-27 14:28:18 -0500445 status = halBinder_->finishRetrieval(&ret.mac, &ret.deviceNameSpaces);
David Zeuthena6f9fba2020-02-11 22:08:27 -0500446 if (!status.isOk()) {
447 return halStatusToGenericError(status);
448 }
449 if (authKey != nullptr) {
450 ret.staticAuthenticationData = authKey->staticAuthenticationData;
David Zeuthenab3e5652019-10-28 13:32:48 -0400451 }
452
453 // Ensure useCount is updated on disk.
454 if (authKey != nullptr) {
455 if (!data_->saveToDisk()) {
456 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
457 "Error saving data");
458 }
459 }
460
461 *_aidl_return = ret;
462 return Status::ok();
463}
464
465Status Credential::deleteCredential(vector<uint8_t>* _aidl_return) {
David Zeuthena6f9fba2020-02-11 22:08:27 -0500466 vector<uint8_t> proofOfDeletionSignature;
467 Status status = halBinder_->deleteCredential(&proofOfDeletionSignature);
468 if (!status.isOk()) {
469 return halStatusToGenericError(status);
David Zeuthenab3e5652019-10-28 13:32:48 -0400470 }
471 if (!data_->deleteCredential()) {
472 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
473 "Error deleting credential data on disk");
474 }
David Zeuthena6f9fba2020-02-11 22:08:27 -0500475 *_aidl_return = proofOfDeletionSignature;
David Zeuthenab3e5652019-10-28 13:32:48 -0400476 return Status::ok();
477}
478
479Status Credential::createEphemeralKeyPair(vector<uint8_t>* _aidl_return) {
David Zeuthenab3e5652019-10-28 13:32:48 -0400480 vector<uint8_t> keyPair;
David Zeuthena6f9fba2020-02-11 22:08:27 -0500481 Status status = halBinder_->createEphemeralKeyPair(&keyPair);
482 if (!status.isOk()) {
483 return halStatusToGenericError(status);
David Zeuthenab3e5652019-10-28 13:32:48 -0400484 }
485
486 optional<vector<uint8_t>> pkcs12Bytes = ecKeyPairGetPkcs12(keyPair,
487 "ephemeralKey", // Alias for key
488 "0", // Serial, as a decimal number
489 "Credstore", // Issuer
490 "Ephemeral Key", // Subject
491 0, // Validity Not Before
492 24 * 60 * 60); // Validity Not After
493 if (!pkcs12Bytes) {
494 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
495 "Error creating PKCS#12 structure for key pair");
496 }
497 *_aidl_return = pkcs12Bytes.value();
498 return Status::ok();
499}
500
501Status Credential::setReaderEphemeralPublicKey(const vector<uint8_t>& publicKey) {
David Zeuthena6f9fba2020-02-11 22:08:27 -0500502 Status status = halBinder_->setReaderEphemeralPublicKey(publicKey);
503 if (!status.isOk()) {
504 return halStatusToGenericError(status);
David Zeuthenab3e5652019-10-28 13:32:48 -0400505 }
506 return Status::ok();
507}
508
509Status Credential::setAvailableAuthenticationKeys(int32_t keyCount, int32_t maxUsesPerKey) {
510 data_->setAvailableAuthenticationKeys(keyCount, maxUsesPerKey);
511 if (!data_->saveToDisk()) {
512 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
513 "Error saving data");
514 }
515 return Status::ok();
516}
517
518Status Credential::getAuthKeysNeedingCertification(vector<AuthKeyParcel>* _aidl_return) {
519 optional<vector<vector<uint8_t>>> keysNeedingCert =
520 data_->getAuthKeysNeedingCertification(halBinder_);
521 if (!keysNeedingCert) {
522 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
523 "Error getting auth keys neededing certification");
524 }
525 vector<AuthKeyParcel> authKeyParcels;
526 for (const vector<uint8_t>& key : keysNeedingCert.value()) {
527 AuthKeyParcel authKeyParcel;
528 authKeyParcel.x509cert = key;
529 authKeyParcels.push_back(authKeyParcel);
530 }
531 if (!data_->saveToDisk()) {
532 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
533 "Error saving data");
534 }
535 *_aidl_return = authKeyParcels;
536 return Status::ok();
537}
538
539Status Credential::storeStaticAuthenticationData(const AuthKeyParcel& authenticationKey,
540 const vector<uint8_t>& staticAuthData) {
541 if (!data_->storeStaticAuthenticationData(authenticationKey.x509cert, staticAuthData)) {
542 return Status::fromServiceSpecificError(
543 ICredentialStore::ERROR_AUTHENTICATION_KEY_NOT_FOUND,
544 "Error finding authentication key to store static "
545 "authentication data for");
546 }
547 if (!data_->saveToDisk()) {
548 return Status::fromServiceSpecificError(ICredentialStore::ERROR_GENERIC,
549 "Error saving data");
550 }
551 return Status::ok();
552}
553
554Status Credential::getAuthenticationDataUsageCount(vector<int32_t>* _aidl_return) {
555 const vector<AuthKeyData>& authKeyDatas = data_->getAuthKeyDatas();
556 vector<int32_t> ret;
557 for (const AuthKeyData& authKeyData : authKeyDatas) {
558 ret.push_back(authKeyData.useCount);
559 }
560 *_aidl_return = ret;
561 return Status::ok();
562}
563
564} // namespace identity
565} // namespace security
566} // namespace android