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