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 "rkpd_client"
18
19 #include <atomic>
20
21 #include <android-base/logging.h>
22 #include <android/security/rkp/BnGetKeyCallback.h>
23 #include <android/security/rkp/BnGetRegistrationCallback.h>
24 #include <android/security/rkp/IGetKeyCallback.h>
25 #include <android/security/rkp/IRemoteProvisioning.h>
26 #include <binder/IServiceManager.h>
27 #include <binder/Status.h>
28 #include <rkp/support/rkpd_client.h>
29 #include <vintf/VintfObject.h>
30
31 namespace android::security::rkp::support {
32 namespace {
33
34 using ::android::binder::Status;
35 using ::android::hardware::security::keymint::IRemotelyProvisionedComponent;
36 using ::android::hardware::security::keymint::RpcHardwareInfo;
37 using ::android::security::rkp::BnGetKeyCallback;
38 using ::android::security::rkp::BnGetRegistrationCallback;
39 using ::android::security::rkp::IGetKeyCallback;
40 using ::android::security::rkp::IRegistration;
41 using ::android::security::rkp::IRemoteProvisioning;
42 using ::android::security::rkp::RemotelyProvisionedKey;
43
44 constexpr const char* kRemoteProvisioningServiceName = "remote_provisioning";
45
getRpcId(const sp<IRemotelyProvisionedComponent> & rpc)46 std::optional<std::string> getRpcId(const sp<IRemotelyProvisionedComponent>& rpc) {
47 RpcHardwareInfo rpcHwInfo;
48 Status status = rpc->getHardwareInfo(&rpcHwInfo);
49 if (!status.isOk()) {
50 LOG(ERROR) << "Error getting remotely provisioned component hardware info: " << status;
51 return std::nullopt;
52 }
53
54 if (!rpcHwInfo.uniqueId) {
55 LOG(ERROR) << "Remotely provisioned component is missing a unique id. "
56 << "This is a bug in the vendor implementation.";
57 return std::nullopt;
58 }
59
60 return *rpcHwInfo.uniqueId;
61 }
62
findRpcNameById(std::string_view targetRpcId)63 std::optional<String16> findRpcNameById(std::string_view targetRpcId) {
64 auto deviceManifest = vintf::VintfObject::GetDeviceHalManifest();
65 auto instances = deviceManifest->getAidlInstances("android.hardware.security.keymint",
66 "IRemotelyProvisionedComponent");
67 for (const std::string& instance : instances) {
68 auto rpcName =
69 IRemotelyProvisionedComponent::descriptor + String16("/") + String16(instance.c_str());
70 sp<IRemotelyProvisionedComponent> rpc =
71 android::waitForService<IRemotelyProvisionedComponent>(rpcName);
72
73 auto rpcId = getRpcId(rpc);
74 if (!rpcId) {
75 continue;
76 }
77 if (*rpcId == targetRpcId) {
78 return rpcName;
79 }
80 }
81
82 LOG(ERROR) << "Remotely provisioned component with given unique ID: " << targetRpcId
83 << " not found";
84 return std::nullopt;
85 }
86
getRpcName(const sp<IRemotelyProvisionedComponent> & rpc)87 std::optional<String16> getRpcName(const sp<IRemotelyProvisionedComponent>& rpc) {
88 std::optional<std::string> targetRpcId = getRpcId(rpc);
89 if (!targetRpcId) {
90 return std::nullopt;
91 }
92 return findRpcNameById(*targetRpcId);
93 }
94
95 class GetKeyCallback : public BnGetKeyCallback {
96 public:
GetKeyCallback(std::promise<std::optional<RemotelyProvisionedKey>> keyPromise)97 GetKeyCallback(std::promise<std::optional<RemotelyProvisionedKey>> keyPromise)
98 : keyPromise_(std::move(keyPromise)), called_() {}
99
onSuccess(const RemotelyProvisionedKey & key)100 Status onSuccess(const RemotelyProvisionedKey& key) override {
101 if (called_.test_and_set()) {
102 return Status::ok();
103 }
104 keyPromise_.set_value(key);
105 return Status::ok();
106 }
onCancel()107 Status onCancel() override {
108 if (called_.test_and_set()) {
109 return Status::ok();
110 }
111 LOG(ERROR) << "GetKeyCallback cancelled";
112 keyPromise_.set_value(std::nullopt);
113 return Status::ok();
114 }
onError(IGetKeyCallback::ErrorCode error,const String16 & description)115 Status onError(IGetKeyCallback::ErrorCode error, const String16& description) override {
116 if (called_.test_and_set()) {
117 return Status::ok();
118 }
119 LOG(ERROR) << "GetKeyCallback failed: " << static_cast<int>(error) << ", " << description;
120 keyPromise_.set_value(std::nullopt);
121 return Status::ok();
122 }
123
124 private:
125 std::promise<std::optional<RemotelyProvisionedKey>> keyPromise_;
126 // This callback can only be called into once
127 std::atomic_flag called_;
128 };
129
130 class GetRegistrationCallback : public BnGetRegistrationCallback {
131 public:
GetRegistrationCallback(std::promise<std::optional<RemotelyProvisionedKey>> keyPromise,uint32_t keyId)132 GetRegistrationCallback(std::promise<std::optional<RemotelyProvisionedKey>> keyPromise,
133 uint32_t keyId)
134 : keyPromise_(std::move(keyPromise)), keyId_(keyId), called_() {}
135
onSuccess(const sp<IRegistration> & registration)136 Status onSuccess(const sp<IRegistration>& registration) override {
137 if (called_.test_and_set()) {
138 return Status::ok();
139 }
140 auto cb = sp<GetKeyCallback>::make(std::move(keyPromise_));
141 auto status = registration->getKey(keyId_, cb);
142 if (!status.isOk()) {
143 cb->onError(IGetKeyCallback::ErrorCode::ERROR_UNKNOWN,
144 String16("Failed to register GetKeyCallback"));
145 }
146 return Status::ok();
147 }
onCancel()148 Status onCancel() override {
149 if (called_.test_and_set()) {
150 return Status::ok();
151 }
152 LOG(ERROR) << "GetRegistrationCallback cancelled";
153 keyPromise_.set_value(std::nullopt);
154 return Status::ok();
155 }
onError(const String16 & error)156 Status onError(const String16& error) override {
157 if (called_.test_and_set()) {
158 return Status::ok();
159 }
160 LOG(ERROR) << "GetRegistrationCallback failed: " << error;
161 keyPromise_.set_value(std::nullopt);
162 return Status::ok();
163 }
164
165 private:
166 std::promise<std::optional<RemotelyProvisionedKey>> keyPromise_;
167 int32_t keyId_;
168 // This callback can only be called into once
169 std::atomic_flag called_;
170 };
171
172 } // namespace
173
174 std::optional<std::future<std::optional<RemotelyProvisionedKey>>>
getRpcKeyFuture(const sp<IRemotelyProvisionedComponent> & rpc,int32_t keyId)175 getRpcKeyFuture(const sp<IRemotelyProvisionedComponent>& rpc, int32_t keyId) {
176 std::promise<std::optional<RemotelyProvisionedKey>> keyPromise;
177 auto keyFuture = keyPromise.get_future();
178
179 auto rpcName = getRpcName(rpc);
180 if (!rpcName) {
181 LOG(ERROR) << "Failed to get IRemotelyProvisionedComponent name";
182 return std::nullopt;
183 }
184
185 sp<IRemoteProvisioning> remoteProvisioning =
186 android::waitForService<IRemoteProvisioning>(String16(kRemoteProvisioningServiceName));
187 if (!remoteProvisioning) {
188 LOG(ERROR) << "Failed to get IRemoteProvisioning HAL";
189 return std::nullopt;
190 }
191
192 auto cb = sp<GetRegistrationCallback>::make(std::move(keyPromise), keyId);
193 Status status = remoteProvisioning->getRegistration(*rpcName, cb);
194 if (!status.isOk()) {
195 LOG(ERROR) << "Failed getRegistration()";
196 return std::nullopt;
197 }
198
199 return keyFuture;
200 }
201
getRpcKey(const sp<IRemotelyProvisionedComponent> & rpc,int32_t keyId,int32_t timeout_sec)202 std::optional<RemotelyProvisionedKey> getRpcKey(const sp<IRemotelyProvisionedComponent>& rpc,
203 int32_t keyId, int32_t timeout_sec) {
204 auto rpcKeyFuture = getRpcKeyFuture(rpc, keyId);
205 if (!rpcKeyFuture) {
206 LOG(ERROR) << "Failed getRpcKeyFuture()";
207 return std::nullopt;
208 }
209
210 auto timeout = std::chrono::seconds(timeout_sec);
211 if (rpcKeyFuture->wait_for(timeout) != std::future_status::ready) {
212 LOG(ERROR) << "Waiting for remotely provisioned attestation key timed out";
213 return std::nullopt;
214 }
215
216 return rpcKeyFuture->get();
217 }
218
219 } // namespace android::security::rkp::support
220