• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <optional>
21 
22 #include <android-base/logging.h>
23 #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>
27 #include <binder/IPCThreadState.h>
28 #include <binder/IServiceManager.h>
29 
30 #include "Credential.h"
31 #include "CredentialData.h"
32 #include "CredentialStore.h"
33 #include "Session.h"
34 #include "Util.h"
35 #include "WritableCredential.h"
36 
37 namespace android {
38 namespace security {
39 namespace identity {
40 namespace {
41 
42 using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
43 using ::android::hardware::security::keymint::RpcHardwareInfo;
44 using ::android::security::remoteprovisioning::IRemotelyProvisionedKeyPool;
45 using ::android::security::remoteprovisioning::RemotelyProvisionedKey;
46 
47 std::optional<std::string>
getRemotelyProvisionedComponentId(const sp<IIdentityCredentialStore> & hal)48 getRemotelyProvisionedComponentId(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
80 
CredentialStore(const std::string & dataPath,sp<IIdentityCredentialStore> hal)81 CredentialStore::CredentialStore(const std::string& dataPath, sp<IIdentityCredentialStore> hal)
82     : dataPath_(dataPath), hal_(hal) {}
83 
init()84 bool CredentialStore::init() {
85     Status status = hal_->getHardwareInformation(&hwInfo_);
86     if (!status.isOk()) {
87         LOG(ERROR) << "Error getting hardware information: " << status.toString8();
88         return false;
89     }
90     halApiVersion_ = hal_->getInterfaceVersion();
91 
92     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 
102     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");
106     return true;
107 }
108 
~CredentialStore()109 CredentialStore::~CredentialStore() {}
110 
getSecurityHardwareInfo(SecurityHardwareInfoParcel * _aidl_return)111 Status CredentialStore::getSecurityHardwareInfo(SecurityHardwareInfoParcel* _aidl_return) {
112     SecurityHardwareInfoParcel info;
113     info.directAccess = hwInfo_.isDirectAccess;
114     info.supportedDocTypes = hwInfo_.supportedDocTypes;
115     *_aidl_return = info;
116     return Status::ok();
117 };
118 
createCredential(const std::string & credentialName,const std::string & docType,sp<IWritableCredential> * _aidl_return)119 Status 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 
134     if (hwInfo_.supportedDocTypes.size() > 0) {
135         if (std::find(hwInfo_.supportedDocTypes.begin(), hwInfo_.supportedDocTypes.end(),
136                       docType) == hwInfo_.supportedDocTypes.end()) {
137             return Status::fromServiceSpecificError(ERROR_DOCUMENT_TYPE_NOT_SUPPORTED,
138                                                     "No support for given document type");
139         }
140     }
141 
142     sp<IWritableIdentityCredential> halWritableCredential;
143     Status status = hal_->createCredential(docType, false, &halWritableCredential);
144     if (!status.isOk()) {
145         return halStatusToGenericError(status);
146     }
147 
148     if (hwInfo_.isRemoteKeyProvisioningSupported) {
149         status = setRemotelyProvisionedAttestationKey(halWritableCredential.get());
150         if (!status.isOk()) {
151             return halStatusToGenericError(status);
152         }
153     }
154 
155     sp<IWritableCredential> writableCredential = new WritableCredential(
156         dataPath_, credentialName, docType, false, hwInfo_, halWritableCredential);
157     *_aidl_return = writableCredential;
158     return Status::ok();
159 }
160 
getCredentialCommon(const std::string & credentialName,int32_t cipherSuite,sp<IPresentationSession> halSessionBinder,sp<ICredential> * _aidl_return)161 Status CredentialStore::getCredentialCommon(const std::string& credentialName, int32_t cipherSuite,
162                                             sp<IPresentationSession> halSessionBinder,
163                                             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 
178     // Note: IdentityCredentialStore.java's CipherSuite enumeration and CipherSuite from the
179     // HAL is manually kept in sync. So this cast is safe.
180     sp<Credential> credential =
181         new Credential(CipherSuite(cipherSuite), dataPath_, credentialName, callingUid, hwInfo_,
182                        hal_, halSessionBinder, halApiVersion_);
183 
184     Status loadStatus = credential->ensureOrReplaceHalBinder();
185     if (!loadStatus.isOk()) {
186         LOG(ERROR) << "Error loading credential";
187     } else {
188         *_aidl_return = credential;
189     }
190     return loadStatus;
191 }
192 
getCredentialByName(const std::string & credentialName,int32_t cipherSuite,sp<ICredential> * _aidl_return)193 Status CredentialStore::getCredentialByName(const std::string& credentialName, int32_t cipherSuite,
194                                             sp<ICredential>* _aidl_return) {
195     return getCredentialCommon(credentialName, cipherSuite, nullptr, _aidl_return);
196 }
197 
createPresentationSession(int32_t cipherSuite,sp<ISession> * _aidl_return)198 Status 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 
setRemotelyProvisionedAttestationKey(IWritableIdentityCredential * halWritableCredential)210 Status 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 
237 }  // namespace identity
238 }  // namespace security
239 }  // namespace android
240