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