blob: c5c429b784ccc7c2576822c1115b2415d8836724 [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
David Zeuthen62d43bf2021-03-31 10:41:27 -040017#define LOG_TAG "credstore"
David Zeuthenab3e5652019-10-28 13:32:48 -040018
19#include <algorithm>
Seth Moore81db3782022-01-18 15:58:47 -080020#include <optional>
David Zeuthenab3e5652019-10-28 13:32:48 -040021
22#include <android-base/logging.h>
Seth Moore81db3782022-01-18 15:58:47 -080023#include <android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
24#include <android/hardware/security/keymint/RpcHardwareInfo.h>
25#include <android/security/remoteprovisioning/IRemotelyProvisionedKeyPool.h>
26#include <android/security/remoteprovisioning/RemotelyProvisionedKey.h>
David Zeuthenab3e5652019-10-28 13:32:48 -040027#include <binder/IPCThreadState.h>
Seth Moore81db3782022-01-18 15:58:47 -080028#include <binder/IServiceManager.h>
David Zeuthenab3e5652019-10-28 13:32:48 -040029
30#include "Credential.h"
David Zeuthena6f9fba2020-02-11 22:08:27 -050031#include "CredentialData.h"
David Zeuthenab3e5652019-10-28 13:32:48 -040032#include "CredentialStore.h"
David Zeuthen045a2c82021-09-11 13:52:17 -040033#include "Session.h"
David Zeuthenab3e5652019-10-28 13:32:48 -040034#include "Util.h"
35#include "WritableCredential.h"
36
37namespace android {
38namespace security {
39namespace identity {
Seth Moore81db3782022-01-18 15:58:47 -080040namespace {
41
42using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
43using ::android::hardware::security::keymint::RpcHardwareInfo;
44using ::android::security::remoteprovisioning::IRemotelyProvisionedKeyPool;
45using ::android::security::remoteprovisioning::RemotelyProvisionedKey;
46
47std::optional<std::string>
48getRemotelyProvisionedComponentId(const sp<IIdentityCredentialStore>& hal) {
49 auto init = [](const sp<IIdentityCredentialStore>& hal) -> std::optional<std::string> {
50 sp<IRemotelyProvisionedComponent> remotelyProvisionedComponent;
51 Status status = hal->getRemotelyProvisionedComponent(&remotelyProvisionedComponent);
52 if (!status.isOk()) {
53 LOG(ERROR) << "Error getting remotely provisioned component: " << status;
54 return std::nullopt;
55 }
56
57 RpcHardwareInfo rpcHwInfo;
58 status = remotelyProvisionedComponent->getHardwareInfo(&rpcHwInfo);
59 if (!status.isOk()) {
60 LOG(ERROR) << "Error getting remotely provisioned component hardware info: " << status;
61 return std::nullopt;
62 }
63
64 if (!rpcHwInfo.uniqueId) {
65 LOG(ERROR) << "Remotely provisioned component is missing a unique id, which is "
66 << "required for credential key remotely provisioned attestation keys. "
67 << "This is a bug in the vendor implementation.";
68 return std::nullopt;
69 }
70
71 // This id is required to later fetch remotely provisioned attestation keys.
72 return *rpcHwInfo.uniqueId;
73 };
74
75 static std::optional<std::string> id = init(hal);
76 return id;
77}
78
79} // namespace
David Zeuthenab3e5652019-10-28 13:32:48 -040080
David Zeuthenab3e5652019-10-28 13:32:48 -040081CredentialStore::CredentialStore(const std::string& dataPath, sp<IIdentityCredentialStore> hal)
82 : dataPath_(dataPath), hal_(hal) {}
83
84bool CredentialStore::init() {
David Zeuthena6f9fba2020-02-11 22:08:27 -050085 Status status = hal_->getHardwareInformation(&hwInfo_);
86 if (!status.isOk()) {
87 LOG(ERROR) << "Error getting hardware information: " << status.toString8();
David Zeuthenab3e5652019-10-28 13:32:48 -040088 return false;
89 }
David Zeuthen472e6c82020-10-16 11:50:13 -040090 halApiVersion_ = hal_->getInterfaceVersion();
David Zeuthena6f9fba2020-02-11 22:08:27 -050091
Seth Moore81db3782022-01-18 15:58:47 -080092 if (hwInfo_.isRemoteKeyProvisioningSupported) {
93 keyPool_ = android::waitForService<IRemotelyProvisionedKeyPool>(
94 IRemotelyProvisionedKeyPool::descriptor);
95 if (keyPool_.get() == nullptr) {
96 LOG(ERROR) << "Error getting IRemotelyProvisionedKeyPool HAL with service name '"
97 << IRemotelyProvisionedKeyPool::descriptor << "'";
98 return false;
99 }
100 }
101
David Zeuthen472e6c82020-10-16 11:50:13 -0400102 LOG(INFO) << "Connected to Identity Credential HAL with API version " << halApiVersion_
103 << " and name '" << hwInfo_.credentialStoreName << "' authored by '"
104 << hwInfo_.credentialStoreAuthorName << "' with chunk size " << hwInfo_.dataChunkSize
105 << " and directoAccess set to " << (hwInfo_.isDirectAccess ? "true" : "false");
David Zeuthenab3e5652019-10-28 13:32:48 -0400106 return true;
107}
108
109CredentialStore::~CredentialStore() {}
110
111Status CredentialStore::getSecurityHardwareInfo(SecurityHardwareInfoParcel* _aidl_return) {
112 SecurityHardwareInfoParcel info;
David Zeuthena6f9fba2020-02-11 22:08:27 -0500113 info.directAccess = hwInfo_.isDirectAccess;
114 info.supportedDocTypes = hwInfo_.supportedDocTypes;
David Zeuthenab3e5652019-10-28 13:32:48 -0400115 *_aidl_return = info;
116 return Status::ok();
117};
118
119Status CredentialStore::createCredential(const std::string& credentialName,
120 const std::string& docType,
121 sp<IWritableCredential>* _aidl_return) {
122 uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
123 optional<bool> credentialExists =
124 CredentialData::credentialExists(dataPath_, callingUid, credentialName);
125 if (!credentialExists.has_value()) {
126 return Status::fromServiceSpecificError(
127 ERROR_GENERIC, "Error determining if credential with given name exists");
128 }
129 if (credentialExists.value()) {
130 return Status::fromServiceSpecificError(ERROR_ALREADY_PERSONALIZED,
131 "Credential with given name already exists");
132 }
133
David Zeuthena6f9fba2020-02-11 22:08:27 -0500134 if (hwInfo_.supportedDocTypes.size() > 0) {
135 if (std::find(hwInfo_.supportedDocTypes.begin(), hwInfo_.supportedDocTypes.end(),
136 docType) == hwInfo_.supportedDocTypes.end()) {
David Zeuthenab3e5652019-10-28 13:32:48 -0400137 return Status::fromServiceSpecificError(ERROR_DOCUMENT_TYPE_NOT_SUPPORTED,
138 "No support for given document type");
139 }
140 }
141
David Zeuthenab3e5652019-10-28 13:32:48 -0400142 sp<IWritableIdentityCredential> halWritableCredential;
David Zeuthena6f9fba2020-02-11 22:08:27 -0500143 Status status = hal_->createCredential(docType, false, &halWritableCredential);
144 if (!status.isOk()) {
145 return halStatusToGenericError(status);
David Zeuthenab3e5652019-10-28 13:32:48 -0400146 }
147
Seth Moore81db3782022-01-18 15:58:47 -0800148 if (hwInfo_.isRemoteKeyProvisioningSupported) {
149 status = setRemotelyProvisionedAttestationKey(halWritableCredential.get());
150 if (!status.isOk()) {
151 return halStatusToGenericError(status);
152 }
153 }
154
David Zeuthenab3e5652019-10-28 13:32:48 -0400155 sp<IWritableCredential> writableCredential = new WritableCredential(
David Zeuthen27407a52021-03-04 16:32:43 -0500156 dataPath_, credentialName, docType, false, hwInfo_, halWritableCredential);
David Zeuthenab3e5652019-10-28 13:32:48 -0400157 *_aidl_return = writableCredential;
158 return Status::ok();
159}
160
David Zeuthen045a2c82021-09-11 13:52:17 -0400161Status CredentialStore::getCredentialCommon(const std::string& credentialName, int32_t cipherSuite,
162 sp<IPresentationSession> halSessionBinder,
David Zeuthenab3e5652019-10-28 13:32:48 -0400163 sp<ICredential>* _aidl_return) {
164 *_aidl_return = nullptr;
165
166 uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
167 optional<bool> credentialExists =
168 CredentialData::credentialExists(dataPath_, callingUid, credentialName);
169 if (!credentialExists.has_value()) {
170 return Status::fromServiceSpecificError(
171 ERROR_GENERIC, "Error determining if credential with given name exists");
172 }
173 if (!credentialExists.value()) {
174 return Status::fromServiceSpecificError(ERROR_NO_SUCH_CREDENTIAL,
175 "Credential with given name doesn't exist");
176 }
177
David Zeuthena6f9fba2020-02-11 22:08:27 -0500178 // Note: IdentityCredentialStore.java's CipherSuite enumeration and CipherSuite from the
179 // HAL is manually kept in sync. So this cast is safe.
David Zeuthen045a2c82021-09-11 13:52:17 -0400180 sp<Credential> credential =
181 new Credential(CipherSuite(cipherSuite), dataPath_, credentialName, callingUid, hwInfo_,
182 hal_, halSessionBinder, halApiVersion_);
David Zeuthenab3e5652019-10-28 13:32:48 -0400183
David Zeuthen472e6c82020-10-16 11:50:13 -0400184 Status loadStatus = credential->ensureOrReplaceHalBinder();
David Zeuthenab3e5652019-10-28 13:32:48 -0400185 if (!loadStatus.isOk()) {
186 LOG(ERROR) << "Error loading credential";
187 } else {
188 *_aidl_return = credential;
189 }
190 return loadStatus;
191}
192
David Zeuthen045a2c82021-09-11 13:52:17 -0400193Status CredentialStore::getCredentialByName(const std::string& credentialName, int32_t cipherSuite,
194 sp<ICredential>* _aidl_return) {
195 return getCredentialCommon(credentialName, cipherSuite, nullptr, _aidl_return);
196}
197
198Status CredentialStore::createPresentationSession(int32_t cipherSuite, sp<ISession>* _aidl_return) {
199 sp<IPresentationSession> halPresentationSession;
200 Status status =
201 hal_->createPresentationSession(CipherSuite(cipherSuite), &halPresentationSession);
202 if (!status.isOk()) {
203 return halStatusToGenericError(status);
204 }
205
206 *_aidl_return = new Session(cipherSuite, halPresentationSession, this);
207 return Status::ok();
208}
209
Seth Moore81db3782022-01-18 15:58:47 -0800210Status CredentialStore::setRemotelyProvisionedAttestationKey(
211 IWritableIdentityCredential* halWritableCredential) {
212 std::optional<std::string> rpcId = getRemotelyProvisionedComponentId(hal_);
213 if (!rpcId) {
214 return Status::fromServiceSpecificError(ERROR_GENERIC,
215 "Error getting remotely provisioned component id");
216 }
217
218 uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
219 RemotelyProvisionedKey key;
220 Status status = keyPool_->getAttestationKey(callingUid, *rpcId, &key);
221 if (!status.isOk()) {
222 LOG(WARNING) << "Unable to fetch remotely provisioned attestation key, falling back "
223 << "to the factory-provisioned attestation key.";
224 return Status::ok();
225 }
226
227 status = halWritableCredential->setRemotelyProvisionedAttestationKey(key.keyBlob,
228 key.encodedCertChain);
229 if (!status.isOk()) {
230 LOG(ERROR) << "Error setting remotely provisioned attestation key on credential";
231 return status;
232 }
233
234 return Status::ok();
235}
236
David Zeuthenab3e5652019-10-28 13:32:48 -0400237} // namespace identity
238} // namespace security
239} // namespace android