1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! Helper wrapper around RKPD interface.
16
17 use android_security_rkp_aidl::aidl::android::security::rkp::{
18 IGetKeyCallback::BnGetKeyCallback, IGetKeyCallback::ErrorCode::ErrorCode as GetKeyErrorCode,
19 IGetKeyCallback::IGetKeyCallback, IGetRegistrationCallback::BnGetRegistrationCallback,
20 IGetRegistrationCallback::IGetRegistrationCallback, IRegistration::IRegistration,
21 IRemoteProvisioning::IRemoteProvisioning,
22 IStoreUpgradedKeyCallback::BnStoreUpgradedKeyCallback,
23 IStoreUpgradedKeyCallback::IStoreUpgradedKeyCallback,
24 RemotelyProvisionedKey::RemotelyProvisionedKey,
25 };
26 use anyhow::{Context, Result};
27 use binder::{BinderFeatures, Interface, StatusCode, Strong};
28 use message_macro::source_location_msg;
29 use std::sync::Mutex;
30 use std::time::Duration;
31 use tokio::sync::oneshot;
32 use tokio::time::timeout;
33
34 // Normally, we block indefinitely when making calls outside of keystore and rely on watchdog to
35 // report deadlocks. However, RKPD is mainline updatable. Also, calls to RKPD may wait on network
36 // for certificates. So, we err on the side of caution and timeout instead.
37 static RKPD_TIMEOUT: Duration = Duration::from_secs(10);
38
tokio_rt() -> tokio::runtime::Runtime39 fn tokio_rt() -> tokio::runtime::Runtime {
40 tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap()
41 }
42
43 /// Errors occurred during the interaction with RKPD.
44 #[derive(Debug, Clone, Copy, thiserror::Error, PartialEq, Eq)]
45 pub enum Error {
46 /// An RKPD request gets cancelled.
47 #[error("An RKPD request gets cancelled")]
48 RequestCancelled,
49
50 /// Failed to get registration.
51 #[error("Failed to get registration")]
52 GetRegistrationFailed,
53
54 /// Failed to get key.
55 #[error("Failed to get key: {0:?}")]
56 GetKeyFailed(GetKeyErrorCode),
57
58 /// Failed to store upgraded key.
59 #[error("Failed to store upgraded key")]
60 StoreUpgradedKeyFailed,
61
62 /// Retryable timeout when waiting for a callback.
63 #[error("Retryable timeout when waiting for a callback")]
64 RetryableTimeout,
65
66 /// Timeout when waiting for a callback.
67 #[error("Timeout when waiting for a callback")]
68 Timeout,
69
70 /// Wraps a Binder status code.
71 #[error("Binder transaction error {0:?}")]
72 BinderTransaction(StatusCode),
73 }
74
75 impl From<StatusCode> for Error {
from(s: StatusCode) -> Self76 fn from(s: StatusCode) -> Self {
77 Self::BinderTransaction(s)
78 }
79 }
80
81 /// Thread-safe channel for sending a value once and only once. If a value has
82 /// already been send, subsequent calls to send will noop.
83 struct SafeSender<T> {
84 inner: Mutex<Option<oneshot::Sender<T>>>,
85 }
86
87 impl<T> SafeSender<T> {
new(sender: oneshot::Sender<T>) -> Self88 fn new(sender: oneshot::Sender<T>) -> Self {
89 Self { inner: Mutex::new(Some(sender)) }
90 }
91
send(&self, value: T)92 fn send(&self, value: T) {
93 if let Some(inner) = self.inner.lock().unwrap().take() {
94 // It's possible for the corresponding receiver to time out and be dropped. In this
95 // case send() will fail. This error is not actionable though, so only log the error.
96 if inner.send(value).is_err() {
97 log::error!("SafeSender::send() failed");
98 }
99 }
100 }
101 }
102
103 struct GetRegistrationCallback {
104 registration_tx: SafeSender<Result<binder::Strong<dyn IRegistration>>>,
105 }
106
107 impl GetRegistrationCallback {
new_native_binder( registration_tx: oneshot::Sender<Result<binder::Strong<dyn IRegistration>>>, ) -> Strong<dyn IGetRegistrationCallback>108 pub fn new_native_binder(
109 registration_tx: oneshot::Sender<Result<binder::Strong<dyn IRegistration>>>,
110 ) -> Strong<dyn IGetRegistrationCallback> {
111 let result: Self =
112 GetRegistrationCallback { registration_tx: SafeSender::new(registration_tx) };
113 BnGetRegistrationCallback::new_binder(result, BinderFeatures::default())
114 }
115 }
116
117 impl Interface for GetRegistrationCallback {}
118
119 impl IGetRegistrationCallback for GetRegistrationCallback {
onSuccess(&self, registration: &Strong<dyn IRegistration>) -> binder::Result<()>120 fn onSuccess(&self, registration: &Strong<dyn IRegistration>) -> binder::Result<()> {
121 self.registration_tx.send(Ok(registration.clone()));
122 Ok(())
123 }
onCancel(&self) -> binder::Result<()>124 fn onCancel(&self) -> binder::Result<()> {
125 log::warn!("IGetRegistrationCallback cancelled");
126 self.registration_tx.send(
127 Err(Error::RequestCancelled)
128 .context(source_location_msg!("GetRegistrationCallback cancelled.")),
129 );
130 Ok(())
131 }
onError(&self, description: &str) -> binder::Result<()>132 fn onError(&self, description: &str) -> binder::Result<()> {
133 log::error!("IGetRegistrationCallback failed: '{description}'");
134 self.registration_tx.send(
135 Err(Error::GetRegistrationFailed)
136 .context(source_location_msg!("GetRegistrationCallback failed: {:?}", description)),
137 );
138 Ok(())
139 }
140 }
141
142 /// Make a new connection to a IRegistration service.
get_rkpd_registration(rpc_name: &str) -> Result<binder::Strong<dyn IRegistration>>143 async fn get_rkpd_registration(rpc_name: &str) -> Result<binder::Strong<dyn IRegistration>> {
144 let remote_provisioning: Strong<dyn IRemoteProvisioning> =
145 binder::get_interface("remote_provisioning")
146 .map_err(Error::from)
147 .context(source_location_msg!("Trying to connect to IRemoteProvisioning service."))?;
148
149 let (tx, rx) = oneshot::channel();
150 let cb = GetRegistrationCallback::new_native_binder(tx);
151
152 remote_provisioning
153 .getRegistration(rpc_name, &cb)
154 .context(source_location_msg!("Trying to get registration."))?;
155
156 match timeout(RKPD_TIMEOUT, rx).await {
157 Err(e) => Err(Error::Timeout).context(source_location_msg!("Waiting for RKPD: {:?}", e)),
158 Ok(v) => v.unwrap(),
159 }
160 }
161
162 struct GetKeyCallback {
163 key_tx: SafeSender<Result<RemotelyProvisionedKey>>,
164 }
165
166 impl GetKeyCallback {
new_native_binder( key_tx: oneshot::Sender<Result<RemotelyProvisionedKey>>, ) -> Strong<dyn IGetKeyCallback>167 pub fn new_native_binder(
168 key_tx: oneshot::Sender<Result<RemotelyProvisionedKey>>,
169 ) -> Strong<dyn IGetKeyCallback> {
170 let result: Self = GetKeyCallback { key_tx: SafeSender::new(key_tx) };
171 BnGetKeyCallback::new_binder(result, BinderFeatures::default())
172 }
173 }
174
175 impl Interface for GetKeyCallback {}
176
177 impl IGetKeyCallback for GetKeyCallback {
onSuccess(&self, key: &RemotelyProvisionedKey) -> binder::Result<()>178 fn onSuccess(&self, key: &RemotelyProvisionedKey) -> binder::Result<()> {
179 self.key_tx.send(Ok(RemotelyProvisionedKey {
180 keyBlob: key.keyBlob.clone(),
181 encodedCertChain: key.encodedCertChain.clone(),
182 }));
183 Ok(())
184 }
onCancel(&self) -> binder::Result<()>185 fn onCancel(&self) -> binder::Result<()> {
186 log::warn!("IGetKeyCallback cancelled");
187 self.key_tx.send(
188 Err(Error::RequestCancelled).context(source_location_msg!("GetKeyCallback cancelled.")),
189 );
190 Ok(())
191 }
onError(&self, error: GetKeyErrorCode, description: &str) -> binder::Result<()>192 fn onError(&self, error: GetKeyErrorCode, description: &str) -> binder::Result<()> {
193 log::error!("IGetKeyCallback failed: {description}");
194 self.key_tx.send(Err(Error::GetKeyFailed(error)).context(source_location_msg!(
195 "GetKeyCallback failed: {:?} {:?}",
196 error,
197 description
198 )));
199 Ok(())
200 }
201 }
202
get_rkpd_attestation_key_from_registration_async( registration: &Strong<dyn IRegistration>, caller_uid: u32, ) -> Result<RemotelyProvisionedKey>203 async fn get_rkpd_attestation_key_from_registration_async(
204 registration: &Strong<dyn IRegistration>,
205 caller_uid: u32,
206 ) -> Result<RemotelyProvisionedKey> {
207 let (tx, rx) = oneshot::channel();
208 let cb = GetKeyCallback::new_native_binder(tx);
209
210 registration
211 .getKey(caller_uid.try_into().unwrap(), &cb)
212 .context(source_location_msg!("Trying to get key."))?;
213
214 match timeout(RKPD_TIMEOUT, rx).await {
215 Err(e) => {
216 // Make a best effort attempt to cancel the timed out request.
217 if let Err(e) = registration.cancelGetKey(&cb) {
218 log::error!("IRegistration::cancelGetKey failed: {:?}", e);
219 }
220 Err(Error::RetryableTimeout)
221 .context(source_location_msg!("Waiting for RKPD key timed out: {:?}", e))
222 }
223 Ok(v) => v.unwrap(),
224 }
225 }
226
get_rkpd_attestation_key_async( rpc_name: &str, caller_uid: u32, ) -> Result<RemotelyProvisionedKey>227 async fn get_rkpd_attestation_key_async(
228 rpc_name: &str,
229 caller_uid: u32,
230 ) -> Result<RemotelyProvisionedKey> {
231 let registration = get_rkpd_registration(rpc_name)
232 .await
233 .context(source_location_msg!("Trying to get to IRegistration service."))?;
234 get_rkpd_attestation_key_from_registration_async(®istration, caller_uid).await
235 }
236
237 struct StoreUpgradedKeyCallback {
238 completer: SafeSender<Result<()>>,
239 }
240
241 impl StoreUpgradedKeyCallback {
new_native_binder( completer: oneshot::Sender<Result<()>>, ) -> Strong<dyn IStoreUpgradedKeyCallback>242 pub fn new_native_binder(
243 completer: oneshot::Sender<Result<()>>,
244 ) -> Strong<dyn IStoreUpgradedKeyCallback> {
245 let result: Self = StoreUpgradedKeyCallback { completer: SafeSender::new(completer) };
246 BnStoreUpgradedKeyCallback::new_binder(result, BinderFeatures::default())
247 }
248 }
249
250 impl Interface for StoreUpgradedKeyCallback {}
251
252 impl IStoreUpgradedKeyCallback for StoreUpgradedKeyCallback {
onSuccess(&self) -> binder::Result<()>253 fn onSuccess(&self) -> binder::Result<()> {
254 self.completer.send(Ok(()));
255 Ok(())
256 }
257
onError(&self, error: &str) -> binder::Result<()>258 fn onError(&self, error: &str) -> binder::Result<()> {
259 log::error!("IStoreUpgradedKeyCallback failed: {error}");
260 self.completer.send(
261 Err(Error::StoreUpgradedKeyFailed)
262 .context(source_location_msg!("Failed to store upgraded key: {:?}", error)),
263 );
264 Ok(())
265 }
266 }
267
store_rkpd_attestation_key_with_registration_async( registration: &Strong<dyn IRegistration>, key_blob: &[u8], upgraded_blob: &[u8], ) -> Result<()>268 async fn store_rkpd_attestation_key_with_registration_async(
269 registration: &Strong<dyn IRegistration>,
270 key_blob: &[u8],
271 upgraded_blob: &[u8],
272 ) -> Result<()> {
273 let (tx, rx) = oneshot::channel();
274 let cb = StoreUpgradedKeyCallback::new_native_binder(tx);
275
276 registration
277 .storeUpgradedKeyAsync(key_blob, upgraded_blob, &cb)
278 .context(source_location_msg!("Failed to store upgraded blob with RKPD."))?;
279
280 match timeout(RKPD_TIMEOUT, rx).await {
281 Err(e) => Err(Error::Timeout)
282 .context(source_location_msg!("Waiting for RKPD to complete storing key: {:?}", e)),
283 Ok(v) => v.unwrap(),
284 }
285 }
286
store_rkpd_attestation_key_async( rpc_name: &str, key_blob: &[u8], upgraded_blob: &[u8], ) -> Result<()>287 async fn store_rkpd_attestation_key_async(
288 rpc_name: &str,
289 key_blob: &[u8],
290 upgraded_blob: &[u8],
291 ) -> Result<()> {
292 let registration = get_rkpd_registration(rpc_name)
293 .await
294 .context(source_location_msg!("Trying to get to IRegistration service."))?;
295 store_rkpd_attestation_key_with_registration_async(®istration, key_blob, upgraded_blob).await
296 }
297
298 /// Get attestation key from RKPD.
get_rkpd_attestation_key(rpc_name: &str, caller_uid: u32) -> Result<RemotelyProvisionedKey>299 pub fn get_rkpd_attestation_key(rpc_name: &str, caller_uid: u32) -> Result<RemotelyProvisionedKey> {
300 tokio_rt().block_on(get_rkpd_attestation_key_async(rpc_name, caller_uid))
301 }
302
303 /// Store attestation key in RKPD.
store_rkpd_attestation_key( rpc_name: &str, key_blob: &[u8], upgraded_blob: &[u8], ) -> Result<()>304 pub fn store_rkpd_attestation_key(
305 rpc_name: &str,
306 key_blob: &[u8],
307 upgraded_blob: &[u8],
308 ) -> Result<()> {
309 tokio_rt().block_on(store_rkpd_attestation_key_async(rpc_name, key_blob, upgraded_blob))
310 }
311
312 #[cfg(test)]
313 mod tests;
314