| /* | 
 |  * Copyright (c) 2019, The Android Open Source Project | 
 |  * | 
 |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
 |  * you may not use this file except in compliance with the License. | 
 |  * You may obtain a copy of the License at | 
 |  * | 
 |  *     http://www.apache.org/licenses/LICENSE-2.0 | 
 |  * | 
 |  * Unless required by applicable law or agreed to in writing, software | 
 |  * distributed under the License is distributed on an "AS IS" BASIS, | 
 |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 |  * See the License for the specific language governing permissions and | 
 |  * limitations under the License. | 
 |  */ | 
 |  | 
 | #define LOG_TAG "credstore" | 
 |  | 
 | #include <algorithm> | 
 |  | 
 | #include <android-base/logging.h> | 
 |  | 
 | #include <binder/IPCThreadState.h> | 
 |  | 
 | #include "Credential.h" | 
 | #include "CredentialData.h" | 
 | #include "CredentialStore.h" | 
 | #include "Util.h" | 
 | #include "WritableCredential.h" | 
 |  | 
 | namespace android { | 
 | namespace security { | 
 | namespace identity { | 
 |  | 
 | CredentialStore::CredentialStore(const std::string& dataPath, sp<IIdentityCredentialStore> hal) | 
 |     : dataPath_(dataPath), hal_(hal) {} | 
 |  | 
 | bool CredentialStore::init() { | 
 |     Status status = hal_->getHardwareInformation(&hwInfo_); | 
 |     if (!status.isOk()) { | 
 |         LOG(ERROR) << "Error getting hardware information: " << status.toString8(); | 
 |         return false; | 
 |     } | 
 |     halApiVersion_ = hal_->getInterfaceVersion(); | 
 |  | 
 |     LOG(INFO) << "Connected to Identity Credential HAL with API version " << halApiVersion_ | 
 |               << " and name '" << hwInfo_.credentialStoreName << "' authored by '" | 
 |               << hwInfo_.credentialStoreAuthorName << "' with chunk size " << hwInfo_.dataChunkSize | 
 |               << " and directoAccess set to " << (hwInfo_.isDirectAccess ? "true" : "false"); | 
 |     return true; | 
 | } | 
 |  | 
 | CredentialStore::~CredentialStore() {} | 
 |  | 
 | Status CredentialStore::getSecurityHardwareInfo(SecurityHardwareInfoParcel* _aidl_return) { | 
 |     SecurityHardwareInfoParcel info; | 
 |     info.directAccess = hwInfo_.isDirectAccess; | 
 |     info.supportedDocTypes = hwInfo_.supportedDocTypes; | 
 |     *_aidl_return = info; | 
 |     return Status::ok(); | 
 | }; | 
 |  | 
 | Status CredentialStore::createCredential(const std::string& credentialName, | 
 |                                          const std::string& docType, | 
 |                                          sp<IWritableCredential>* _aidl_return) { | 
 |     uid_t callingUid = android::IPCThreadState::self()->getCallingUid(); | 
 |     optional<bool> credentialExists = | 
 |         CredentialData::credentialExists(dataPath_, callingUid, credentialName); | 
 |     if (!credentialExists.has_value()) { | 
 |         return Status::fromServiceSpecificError( | 
 |             ERROR_GENERIC, "Error determining if credential with given name exists"); | 
 |     } | 
 |     if (credentialExists.value()) { | 
 |         return Status::fromServiceSpecificError(ERROR_ALREADY_PERSONALIZED, | 
 |                                                 "Credential with given name already exists"); | 
 |     } | 
 |  | 
 |     if (hwInfo_.supportedDocTypes.size() > 0) { | 
 |         if (std::find(hwInfo_.supportedDocTypes.begin(), hwInfo_.supportedDocTypes.end(), | 
 |                       docType) == hwInfo_.supportedDocTypes.end()) { | 
 |             return Status::fromServiceSpecificError(ERROR_DOCUMENT_TYPE_NOT_SUPPORTED, | 
 |                                                     "No support for given document type"); | 
 |         } | 
 |     } | 
 |  | 
 |     sp<IWritableIdentityCredential> halWritableCredential; | 
 |     Status status = hal_->createCredential(docType, false, &halWritableCredential); | 
 |     if (!status.isOk()) { | 
 |         return halStatusToGenericError(status); | 
 |     } | 
 |  | 
 |     sp<IWritableCredential> writableCredential = new WritableCredential( | 
 |         dataPath_, credentialName, docType, false, hwInfo_, halWritableCredential); | 
 |     *_aidl_return = writableCredential; | 
 |     return Status::ok(); | 
 | } | 
 |  | 
 | Status CredentialStore::getCredentialByName(const std::string& credentialName, int32_t cipherSuite, | 
 |                                             sp<ICredential>* _aidl_return) { | 
 |     *_aidl_return = nullptr; | 
 |  | 
 |     uid_t callingUid = android::IPCThreadState::self()->getCallingUid(); | 
 |     optional<bool> credentialExists = | 
 |         CredentialData::credentialExists(dataPath_, callingUid, credentialName); | 
 |     if (!credentialExists.has_value()) { | 
 |         return Status::fromServiceSpecificError( | 
 |             ERROR_GENERIC, "Error determining if credential with given name exists"); | 
 |     } | 
 |     if (!credentialExists.value()) { | 
 |         return Status::fromServiceSpecificError(ERROR_NO_SUCH_CREDENTIAL, | 
 |                                                 "Credential with given name doesn't exist"); | 
 |     } | 
 |  | 
 |     // Note: IdentityCredentialStore.java's CipherSuite enumeration and CipherSuite from the | 
 |     // HAL is manually kept in sync. So this cast is safe. | 
 |     sp<Credential> credential = new Credential(CipherSuite(cipherSuite), dataPath_, credentialName, | 
 |                                                callingUid, hwInfo_, hal_, halApiVersion_); | 
 |  | 
 |     Status loadStatus = credential->ensureOrReplaceHalBinder(); | 
 |     if (!loadStatus.isOk()) { | 
 |         LOG(ERROR) << "Error loading credential"; | 
 |     } else { | 
 |         *_aidl_return = credential; | 
 |     } | 
 |     return loadStatus; | 
 | } | 
 |  | 
 | }  // namespace identity | 
 | }  // namespace security | 
 | }  // namespace android |