1 /*
2 * Copyright (c) 2019, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "credstore"
18
19 #include <algorithm>
20
21 #include <android-base/logging.h>
22
23 #include <binder/IPCThreadState.h>
24
25 #include "Credential.h"
26 #include "CredentialData.h"
27 #include "CredentialStore.h"
28 #include "Util.h"
29 #include "WritableCredential.h"
30
31 namespace android {
32 namespace security {
33 namespace identity {
34
CredentialStore(const std::string & dataPath,sp<IIdentityCredentialStore> hal)35 CredentialStore::CredentialStore(const std::string& dataPath, sp<IIdentityCredentialStore> hal)
36 : dataPath_(dataPath), hal_(hal) {}
37
init()38 bool CredentialStore::init() {
39 Status status = hal_->getHardwareInformation(&hwInfo_);
40 if (!status.isOk()) {
41 LOG(ERROR) << "Error getting hardware information: " << status.toString8();
42 return false;
43 }
44 halApiVersion_ = hal_->getInterfaceVersion();
45
46 LOG(INFO) << "Connected to Identity Credential HAL with API version " << halApiVersion_
47 << " and name '" << hwInfo_.credentialStoreName << "' authored by '"
48 << hwInfo_.credentialStoreAuthorName << "' with chunk size " << hwInfo_.dataChunkSize
49 << " and directoAccess set to " << (hwInfo_.isDirectAccess ? "true" : "false");
50 return true;
51 }
52
~CredentialStore()53 CredentialStore::~CredentialStore() {}
54
getSecurityHardwareInfo(SecurityHardwareInfoParcel * _aidl_return)55 Status CredentialStore::getSecurityHardwareInfo(SecurityHardwareInfoParcel* _aidl_return) {
56 SecurityHardwareInfoParcel info;
57 info.directAccess = hwInfo_.isDirectAccess;
58 info.supportedDocTypes = hwInfo_.supportedDocTypes;
59 *_aidl_return = info;
60 return Status::ok();
61 };
62
createCredential(const std::string & credentialName,const std::string & docType,sp<IWritableCredential> * _aidl_return)63 Status CredentialStore::createCredential(const std::string& credentialName,
64 const std::string& docType,
65 sp<IWritableCredential>* _aidl_return) {
66 uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
67 optional<bool> credentialExists =
68 CredentialData::credentialExists(dataPath_, callingUid, credentialName);
69 if (!credentialExists.has_value()) {
70 return Status::fromServiceSpecificError(
71 ERROR_GENERIC, "Error determining if credential with given name exists");
72 }
73 if (credentialExists.value()) {
74 return Status::fromServiceSpecificError(ERROR_ALREADY_PERSONALIZED,
75 "Credential with given name already exists");
76 }
77
78 if (hwInfo_.supportedDocTypes.size() > 0) {
79 if (std::find(hwInfo_.supportedDocTypes.begin(), hwInfo_.supportedDocTypes.end(),
80 docType) == hwInfo_.supportedDocTypes.end()) {
81 return Status::fromServiceSpecificError(ERROR_DOCUMENT_TYPE_NOT_SUPPORTED,
82 "No support for given document type");
83 }
84 }
85
86 sp<IWritableIdentityCredential> halWritableCredential;
87 Status status = hal_->createCredential(docType, false, &halWritableCredential);
88 if (!status.isOk()) {
89 return halStatusToGenericError(status);
90 }
91
92 sp<IWritableCredential> writableCredential = new WritableCredential(
93 dataPath_, credentialName, docType, false, hwInfo_, halWritableCredential);
94 *_aidl_return = writableCredential;
95 return Status::ok();
96 }
97
getCredentialByName(const std::string & credentialName,int32_t cipherSuite,sp<ICredential> * _aidl_return)98 Status CredentialStore::getCredentialByName(const std::string& credentialName, int32_t cipherSuite,
99 sp<ICredential>* _aidl_return) {
100 *_aidl_return = nullptr;
101
102 uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
103 optional<bool> credentialExists =
104 CredentialData::credentialExists(dataPath_, callingUid, credentialName);
105 if (!credentialExists.has_value()) {
106 return Status::fromServiceSpecificError(
107 ERROR_GENERIC, "Error determining if credential with given name exists");
108 }
109 if (!credentialExists.value()) {
110 return Status::fromServiceSpecificError(ERROR_NO_SUCH_CREDENTIAL,
111 "Credential with given name doesn't exist");
112 }
113
114 // Note: IdentityCredentialStore.java's CipherSuite enumeration and CipherSuite from the
115 // HAL is manually kept in sync. So this cast is safe.
116 sp<Credential> credential = new Credential(CipherSuite(cipherSuite), dataPath_, credentialName,
117 callingUid, hwInfo_, hal_, halApiVersion_);
118
119 Status loadStatus = credential->ensureOrReplaceHalBinder();
120 if (!loadStatus.isOk()) {
121 LOG(ERROR) << "Error loading credential";
122 } else {
123 *_aidl_return = credential;
124 }
125 return loadStatus;
126 }
127
128 } // namespace identity
129 } // namespace security
130 } // namespace android
131