diff options
author | David Drysdale <drysdale@google.com> | 2024-01-22 15:03:14 +0000 |
---|---|---|
committer | David Drysdale <drysdale@google.com> | 2024-01-23 10:24:01 +0000 |
commit | 7171c676c09b378f94cc5b1485d6213fb176c8f3 (patch) | |
tree | c398598f07594be86796c9d04634310aa228715d /trusty | |
parent | 80b2bf16c9f36f85fae650386e305d2b0a581b2b (diff) | |
download | core-7171c676c09b378f94cc5b1485d6213fb176c8f3.tar.gz |
Secretkeeper HAL: support large messages
The TIPC channel between HAL service and TA has a max message size of
around 4K. Cope with larger messages by using fragmentation and
reassembly for all messages.
Test: VtsSecretkeeperTargetTest
Change-Id: I18cc9a9f6e6b90ab66bc3bcf1972e1a5c5112c89
Diffstat (limited to 'trusty')
-rw-r--r-- | trusty/secretkeeper/Android.bp | 5 | ||||
-rw-r--r-- | trusty/secretkeeper/src/hal_main.rs | 66 |
2 files changed, 40 insertions, 31 deletions
diff --git a/trusty/secretkeeper/Android.bp b/trusty/secretkeeper/Android.bp index f6b740a17..6523edaf6 100644 --- a/trusty/secretkeeper/Android.bp +++ b/trusty/secretkeeper/Android.bp @@ -28,12 +28,13 @@ rust_binary { ], rustlibs: [ "libandroid_logger", - "libbinder_rs", "libauthgraph_hal", - "libtrusty-rs", + "libauthgraph_wire", + "libbinder_rs", "liblibc", "liblog_rust", "libsecretkeeper_hal", + "libtrusty-rs", ], defaults: [ "secretkeeper_use_latest_hal_aidl_rust", diff --git a/trusty/secretkeeper/src/hal_main.rs b/trusty/secretkeeper/src/hal_main.rs index 9439c369b..1dc697dfe 100644 --- a/trusty/secretkeeper/src/hal_main.rs +++ b/trusty/secretkeeper/src/hal_main.rs @@ -14,7 +14,8 @@ // limitations under the License. //! This module implements the HAL service for Secretkeeper in Trusty. -use authgraph_hal::{channel::SerializedChannel}; +use authgraph_hal::channel::SerializedChannel; +use authgraph_wire::fragmentation::{Fragmenter, Reassembler}; use secretkeeper_hal::SecretkeeperService; use android_hardware_security_secretkeeper::aidl::android::hardware::security::secretkeeper::ISecretkeeper::{ ISecretkeeper, BpSecretkeeper, @@ -22,6 +23,7 @@ use android_hardware_security_secretkeeper::aidl::android::hardware::security::s use log::{error, info}; use std::{ ffi::CString, + fmt::Debug, panic, sync::{Arc, Mutex}, }; @@ -29,6 +31,7 @@ use trusty::DEFAULT_DEVICE; const SK_TIPC_SERVICE_PORT: &str = "com.android.trusty.secretkeeper"; const AG_TIPC_SERVICE_PORT: &str = "com.android.trusty.secretkeeper.authgraph"; +const TIPC_MAX_SIZE: usize = 4000; static SERVICE_INSTANCE: &str = "default"; @@ -47,38 +50,43 @@ impl TipcChannel { } } +fn binderr<E: Debug>(msg: &str, e: E) -> binder::Status { + binder::Status::new_exception( + binder::ExceptionCode::TRANSACTION_FAILED, + Some(&CString::new(format!("Failed to {msg} via tipc channel: {e:?}",)).unwrap()), + ) +} + impl SerializedChannel for TipcChannel { - const MAX_SIZE: usize = 4000; + // No maximum size for messages passed to `execute()` because it performs fragmentation + // and reassembly internally. + const MAX_SIZE: usize = usize::MAX; + fn execute(&self, req_data: &[u8]) -> binder::Result<Vec<u8>> { // Hold lock across both request and response. let mut channel = self.channel.lock().unwrap(); - channel.send(req_data).map_err(|e| { - binder::Status::new_exception( - binder::ExceptionCode::TRANSACTION_FAILED, - Some( - &CString::new(format!( - "Failed to send the request via tipc channel because of {:?}", - e - )) - .unwrap(), - ), - ) - })?; - // TODO: cope with fragmentation and reassembly - let mut rsp_data = Vec::new(); - channel.recv(&mut rsp_data).map_err(|e| { - binder::Status::new_exception( - binder::ExceptionCode::TRANSACTION_FAILED, - Some( - &CString::new(format!( - "Failed to receive the response via tipc channel because of {:?}", - e - )) - .unwrap(), - ), - ) - })?; - Ok(rsp_data) + let mut pending_rsp = Reassembler::default(); + + // Break request message into fragments to send. + for req_frag in Fragmenter::new(req_data, TIPC_MAX_SIZE) { + channel.send(&req_frag).map_err(|e| binderr("send request", e))?; + + // Every request gets a response. + let mut rsp_frag = Vec::new(); + channel.recv(&mut rsp_frag).map_err(|e| binderr("receive response", e))?; + + if let Some(full_rsp) = pending_rsp.accumulate(&rsp_frag) { + return Ok(full_rsp.to_vec()); + } + } + // There may be additional response fragments to receive. + loop { + let mut rsp_frag = Vec::new(); + channel.recv(&mut rsp_frag).map_err(|e| binderr("receive response", e))?; + if let Some(full_rsp) = pending_rsp.accumulate(&rsp_frag) { + return Ok(full_rsp.to_vec()); + } + } } } |