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 <algorithm>
20*e1997b9aSAndroid Build Coastguard Worker #include <optional>
21*e1997b9aSAndroid Build Coastguard Worker
22*e1997b9aSAndroid Build Coastguard Worker #include <android-base/logging.h>
23*e1997b9aSAndroid Build Coastguard Worker #include <android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
24*e1997b9aSAndroid Build Coastguard Worker #include <android/hardware/security/keymint/RpcHardwareInfo.h>
25*e1997b9aSAndroid Build Coastguard Worker #include <binder/IPCThreadState.h>
26*e1997b9aSAndroid Build Coastguard Worker #include <binder/IServiceManager.h>
27*e1997b9aSAndroid Build Coastguard Worker #include <rkp/support/rkpd_client.h>
28*e1997b9aSAndroid Build Coastguard Worker
29*e1997b9aSAndroid Build Coastguard Worker #include "Credential.h"
30*e1997b9aSAndroid Build Coastguard Worker #include "CredentialData.h"
31*e1997b9aSAndroid Build Coastguard Worker #include "CredentialStore.h"
32*e1997b9aSAndroid Build Coastguard Worker #include "Session.h"
33*e1997b9aSAndroid Build Coastguard Worker #include "Util.h"
34*e1997b9aSAndroid Build Coastguard Worker #include "WritableCredential.h"
35*e1997b9aSAndroid Build Coastguard Worker
36*e1997b9aSAndroid Build Coastguard Worker namespace android {
37*e1997b9aSAndroid Build Coastguard Worker namespace security {
38*e1997b9aSAndroid Build Coastguard Worker namespace identity {
39*e1997b9aSAndroid Build Coastguard Worker namespace {
40*e1997b9aSAndroid Build Coastguard Worker
41*e1997b9aSAndroid Build Coastguard Worker using ::android::security::rkp::RemotelyProvisionedKey;
42*e1997b9aSAndroid Build Coastguard Worker using ::android::security::rkp::support::getRpcKey;
43*e1997b9aSAndroid Build Coastguard Worker
44*e1997b9aSAndroid Build Coastguard Worker } // namespace
45*e1997b9aSAndroid Build Coastguard Worker
CredentialStore(const std::string & dataPath,sp<IIdentityCredentialStore> hal)46*e1997b9aSAndroid Build Coastguard Worker CredentialStore::CredentialStore(const std::string& dataPath, sp<IIdentityCredentialStore> hal)
47*e1997b9aSAndroid Build Coastguard Worker : dataPath_(dataPath), hal_(hal) {}
48*e1997b9aSAndroid Build Coastguard Worker
init()49*e1997b9aSAndroid Build Coastguard Worker bool CredentialStore::init() {
50*e1997b9aSAndroid Build Coastguard Worker Status status = hal_->getHardwareInformation(&hwInfo_);
51*e1997b9aSAndroid Build Coastguard Worker if (!status.isOk()) {
52*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "Error getting hardware information: " << status.toString8();
53*e1997b9aSAndroid Build Coastguard Worker return false;
54*e1997b9aSAndroid Build Coastguard Worker }
55*e1997b9aSAndroid Build Coastguard Worker halApiVersion_ = hal_->getInterfaceVersion();
56*e1997b9aSAndroid Build Coastguard Worker
57*e1997b9aSAndroid Build Coastguard Worker if (hwInfo_.isRemoteKeyProvisioningSupported) {
58*e1997b9aSAndroid Build Coastguard Worker status = hal_->getRemotelyProvisionedComponent(&rpc_);
59*e1997b9aSAndroid Build Coastguard Worker if (!status.isOk()) {
60*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "Error getting remotely provisioned component: " << status;
61*e1997b9aSAndroid Build Coastguard Worker return false;
62*e1997b9aSAndroid Build Coastguard Worker }
63*e1997b9aSAndroid Build Coastguard Worker }
64*e1997b9aSAndroid Build Coastguard Worker
65*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "Connected to Identity Credential HAL with API version " << halApiVersion_
66*e1997b9aSAndroid Build Coastguard Worker << " and name '" << hwInfo_.credentialStoreName << "' authored by '"
67*e1997b9aSAndroid Build Coastguard Worker << hwInfo_.credentialStoreAuthorName << "' with chunk size " << hwInfo_.dataChunkSize
68*e1997b9aSAndroid Build Coastguard Worker << " directoAccess set to " << (hwInfo_.isDirectAccess ? "true" : "false")
69*e1997b9aSAndroid Build Coastguard Worker << " and remote key provisioning support "
70*e1997b9aSAndroid Build Coastguard Worker << (hwInfo_.isRemoteKeyProvisioningSupported ? "enabled" : "disabled");
71*e1997b9aSAndroid Build Coastguard Worker return true;
72*e1997b9aSAndroid Build Coastguard Worker }
73*e1997b9aSAndroid Build Coastguard Worker
~CredentialStore()74*e1997b9aSAndroid Build Coastguard Worker CredentialStore::~CredentialStore() {}
75*e1997b9aSAndroid Build Coastguard Worker
getSecurityHardwareInfo(SecurityHardwareInfoParcel * _aidl_return)76*e1997b9aSAndroid Build Coastguard Worker Status CredentialStore::getSecurityHardwareInfo(SecurityHardwareInfoParcel* _aidl_return) {
77*e1997b9aSAndroid Build Coastguard Worker SecurityHardwareInfoParcel info;
78*e1997b9aSAndroid Build Coastguard Worker info.directAccess = hwInfo_.isDirectAccess;
79*e1997b9aSAndroid Build Coastguard Worker info.supportedDocTypes = hwInfo_.supportedDocTypes;
80*e1997b9aSAndroid Build Coastguard Worker *_aidl_return = info;
81*e1997b9aSAndroid Build Coastguard Worker return Status::ok();
82*e1997b9aSAndroid Build Coastguard Worker };
83*e1997b9aSAndroid Build Coastguard Worker
createCredential(const std::string & credentialName,const std::string & docType,sp<IWritableCredential> * _aidl_return)84*e1997b9aSAndroid Build Coastguard Worker Status CredentialStore::createCredential(const std::string& credentialName,
85*e1997b9aSAndroid Build Coastguard Worker const std::string& docType,
86*e1997b9aSAndroid Build Coastguard Worker sp<IWritableCredential>* _aidl_return) {
87*e1997b9aSAndroid Build Coastguard Worker uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
88*e1997b9aSAndroid Build Coastguard Worker optional<bool> credentialExists =
89*e1997b9aSAndroid Build Coastguard Worker CredentialData::credentialExists(dataPath_, callingUid, credentialName);
90*e1997b9aSAndroid Build Coastguard Worker if (!credentialExists.has_value()) {
91*e1997b9aSAndroid Build Coastguard Worker return Status::fromServiceSpecificError(
92*e1997b9aSAndroid Build Coastguard Worker ERROR_GENERIC, "Error determining if credential with given name exists");
93*e1997b9aSAndroid Build Coastguard Worker }
94*e1997b9aSAndroid Build Coastguard Worker if (credentialExists.value()) {
95*e1997b9aSAndroid Build Coastguard Worker return Status::fromServiceSpecificError(ERROR_ALREADY_PERSONALIZED,
96*e1997b9aSAndroid Build Coastguard Worker "Credential with given name already exists");
97*e1997b9aSAndroid Build Coastguard Worker }
98*e1997b9aSAndroid Build Coastguard Worker
99*e1997b9aSAndroid Build Coastguard Worker if (hwInfo_.supportedDocTypes.size() > 0) {
100*e1997b9aSAndroid Build Coastguard Worker if (std::find(hwInfo_.supportedDocTypes.begin(), hwInfo_.supportedDocTypes.end(),
101*e1997b9aSAndroid Build Coastguard Worker docType) == hwInfo_.supportedDocTypes.end()) {
102*e1997b9aSAndroid Build Coastguard Worker return Status::fromServiceSpecificError(ERROR_DOCUMENT_TYPE_NOT_SUPPORTED,
103*e1997b9aSAndroid Build Coastguard Worker "No support for given document type");
104*e1997b9aSAndroid Build Coastguard Worker }
105*e1997b9aSAndroid Build Coastguard Worker }
106*e1997b9aSAndroid Build Coastguard Worker
107*e1997b9aSAndroid Build Coastguard Worker sp<IWritableIdentityCredential> halWritableCredential;
108*e1997b9aSAndroid Build Coastguard Worker Status status = hal_->createCredential(docType, false, &halWritableCredential);
109*e1997b9aSAndroid Build Coastguard Worker if (!status.isOk()) {
110*e1997b9aSAndroid Build Coastguard Worker return halStatusToGenericError(status);
111*e1997b9aSAndroid Build Coastguard Worker }
112*e1997b9aSAndroid Build Coastguard Worker
113*e1997b9aSAndroid Build Coastguard Worker if (hwInfo_.isRemoteKeyProvisioningSupported) {
114*e1997b9aSAndroid Build Coastguard Worker status = setRemotelyProvisionedAttestationKey(halWritableCredential.get());
115*e1997b9aSAndroid Build Coastguard Worker if (!status.isOk()) {
116*e1997b9aSAndroid Build Coastguard Worker LOG(WARNING) << status.toString8()
117*e1997b9aSAndroid Build Coastguard Worker << "\nUnable to fetch remotely provisioned attestation key, falling back "
118*e1997b9aSAndroid Build Coastguard Worker << "to the factory-provisioned attestation key.";
119*e1997b9aSAndroid Build Coastguard Worker }
120*e1997b9aSAndroid Build Coastguard Worker }
121*e1997b9aSAndroid Build Coastguard Worker
122*e1997b9aSAndroid Build Coastguard Worker sp<IWritableCredential> writableCredential = new WritableCredential(
123*e1997b9aSAndroid Build Coastguard Worker dataPath_, credentialName, docType, false, hwInfo_, halWritableCredential);
124*e1997b9aSAndroid Build Coastguard Worker *_aidl_return = writableCredential;
125*e1997b9aSAndroid Build Coastguard Worker return Status::ok();
126*e1997b9aSAndroid Build Coastguard Worker }
127*e1997b9aSAndroid Build Coastguard Worker
getCredentialCommon(const std::string & credentialName,int32_t cipherSuite,sp<IPresentationSession> halSessionBinder,sp<ICredential> * _aidl_return)128*e1997b9aSAndroid Build Coastguard Worker Status CredentialStore::getCredentialCommon(const std::string& credentialName, int32_t cipherSuite,
129*e1997b9aSAndroid Build Coastguard Worker sp<IPresentationSession> halSessionBinder,
130*e1997b9aSAndroid Build Coastguard Worker sp<ICredential>* _aidl_return) {
131*e1997b9aSAndroid Build Coastguard Worker *_aidl_return = nullptr;
132*e1997b9aSAndroid Build Coastguard Worker
133*e1997b9aSAndroid Build Coastguard Worker uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
134*e1997b9aSAndroid Build Coastguard Worker optional<bool> credentialExists =
135*e1997b9aSAndroid Build Coastguard Worker CredentialData::credentialExists(dataPath_, callingUid, credentialName);
136*e1997b9aSAndroid Build Coastguard Worker if (!credentialExists.has_value()) {
137*e1997b9aSAndroid Build Coastguard Worker return Status::fromServiceSpecificError(
138*e1997b9aSAndroid Build Coastguard Worker ERROR_GENERIC, "Error determining if credential with given name exists");
139*e1997b9aSAndroid Build Coastguard Worker }
140*e1997b9aSAndroid Build Coastguard Worker if (!credentialExists.value()) {
141*e1997b9aSAndroid Build Coastguard Worker return Status::fromServiceSpecificError(ERROR_NO_SUCH_CREDENTIAL,
142*e1997b9aSAndroid Build Coastguard Worker "Credential with given name doesn't exist");
143*e1997b9aSAndroid Build Coastguard Worker }
144*e1997b9aSAndroid Build Coastguard Worker
145*e1997b9aSAndroid Build Coastguard Worker // Note: IdentityCredentialStore.java's CipherSuite enumeration and CipherSuite from the
146*e1997b9aSAndroid Build Coastguard Worker // HAL is manually kept in sync. So this cast is safe.
147*e1997b9aSAndroid Build Coastguard Worker sp<Credential> credential =
148*e1997b9aSAndroid Build Coastguard Worker new Credential(CipherSuite(cipherSuite), dataPath_, credentialName, callingUid, hwInfo_,
149*e1997b9aSAndroid Build Coastguard Worker hal_, halSessionBinder, halApiVersion_);
150*e1997b9aSAndroid Build Coastguard Worker
151*e1997b9aSAndroid Build Coastguard Worker Status loadStatus = credential->ensureOrReplaceHalBinder();
152*e1997b9aSAndroid Build Coastguard Worker if (!loadStatus.isOk()) {
153*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "Error loading credential";
154*e1997b9aSAndroid Build Coastguard Worker } else {
155*e1997b9aSAndroid Build Coastguard Worker *_aidl_return = credential;
156*e1997b9aSAndroid Build Coastguard Worker }
157*e1997b9aSAndroid Build Coastguard Worker return loadStatus;
158*e1997b9aSAndroid Build Coastguard Worker }
159*e1997b9aSAndroid Build Coastguard Worker
getCredentialByName(const std::string & credentialName,int32_t cipherSuite,sp<ICredential> * _aidl_return)160*e1997b9aSAndroid Build Coastguard Worker Status CredentialStore::getCredentialByName(const std::string& credentialName, int32_t cipherSuite,
161*e1997b9aSAndroid Build Coastguard Worker sp<ICredential>* _aidl_return) {
162*e1997b9aSAndroid Build Coastguard Worker return getCredentialCommon(credentialName, cipherSuite, nullptr, _aidl_return);
163*e1997b9aSAndroid Build Coastguard Worker }
164*e1997b9aSAndroid Build Coastguard Worker
createPresentationSession(int32_t cipherSuite,sp<ISession> * _aidl_return)165*e1997b9aSAndroid Build Coastguard Worker Status CredentialStore::createPresentationSession(int32_t cipherSuite, sp<ISession>* _aidl_return) {
166*e1997b9aSAndroid Build Coastguard Worker sp<IPresentationSession> halPresentationSession;
167*e1997b9aSAndroid Build Coastguard Worker Status status =
168*e1997b9aSAndroid Build Coastguard Worker hal_->createPresentationSession(CipherSuite(cipherSuite), &halPresentationSession);
169*e1997b9aSAndroid Build Coastguard Worker if (!status.isOk()) {
170*e1997b9aSAndroid Build Coastguard Worker return halStatusToGenericError(status);
171*e1997b9aSAndroid Build Coastguard Worker }
172*e1997b9aSAndroid Build Coastguard Worker
173*e1997b9aSAndroid Build Coastguard Worker *_aidl_return = new Session(cipherSuite, halPresentationSession, this);
174*e1997b9aSAndroid Build Coastguard Worker return Status::ok();
175*e1997b9aSAndroid Build Coastguard Worker }
176*e1997b9aSAndroid Build Coastguard Worker
setRemotelyProvisionedAttestationKey(IWritableIdentityCredential * halWritableCredential)177*e1997b9aSAndroid Build Coastguard Worker Status CredentialStore::setRemotelyProvisionedAttestationKey(
178*e1997b9aSAndroid Build Coastguard Worker IWritableIdentityCredential* halWritableCredential) {
179*e1997b9aSAndroid Build Coastguard Worker std::vector<uint8_t> keyBlob;
180*e1997b9aSAndroid Build Coastguard Worker std::vector<uint8_t> encodedCertChain;
181*e1997b9aSAndroid Build Coastguard Worker Status status;
182*e1997b9aSAndroid Build Coastguard Worker
183*e1997b9aSAndroid Build Coastguard Worker LOG(INFO) << "Fetching attestation key from RKPD";
184*e1997b9aSAndroid Build Coastguard Worker
185*e1997b9aSAndroid Build Coastguard Worker uid_t callingUid = android::IPCThreadState::self()->getCallingUid();
186*e1997b9aSAndroid Build Coastguard Worker std::optional<RemotelyProvisionedKey> key = getRpcKey(rpc_, callingUid);
187*e1997b9aSAndroid Build Coastguard Worker if (!key) {
188*e1997b9aSAndroid Build Coastguard Worker return Status::fromServiceSpecificError(
189*e1997b9aSAndroid Build Coastguard Worker ERROR_GENERIC, "Failed to get remotely provisioned attestation key");
190*e1997b9aSAndroid Build Coastguard Worker }
191*e1997b9aSAndroid Build Coastguard Worker
192*e1997b9aSAndroid Build Coastguard Worker if (key->keyBlob.empty()) {
193*e1997b9aSAndroid Build Coastguard Worker return Status::fromServiceSpecificError(
194*e1997b9aSAndroid Build Coastguard Worker ERROR_GENERIC, "Remotely provisioned attestation key blob is empty");
195*e1997b9aSAndroid Build Coastguard Worker }
196*e1997b9aSAndroid Build Coastguard Worker
197*e1997b9aSAndroid Build Coastguard Worker keyBlob = std::move(key->keyBlob);
198*e1997b9aSAndroid Build Coastguard Worker encodedCertChain = std::move(key->encodedCertChain);
199*e1997b9aSAndroid Build Coastguard Worker
200*e1997b9aSAndroid Build Coastguard Worker status = halWritableCredential->setRemotelyProvisionedAttestationKey(keyBlob, encodedCertChain);
201*e1997b9aSAndroid Build Coastguard Worker if (!status.isOk()) {
202*e1997b9aSAndroid Build Coastguard Worker LOG(ERROR) << "Error setting remotely provisioned attestation key on credential";
203*e1997b9aSAndroid Build Coastguard Worker return status;
204*e1997b9aSAndroid Build Coastguard Worker }
205*e1997b9aSAndroid Build Coastguard Worker return Status::ok();
206*e1997b9aSAndroid Build Coastguard Worker }
207*e1997b9aSAndroid Build Coastguard Worker
208*e1997b9aSAndroid Build Coastguard Worker } // namespace identity
209*e1997b9aSAndroid Build Coastguard Worker } // namespace security
210*e1997b9aSAndroid Build Coastguard Worker } // namespace android
211