xref: /aosp_15_r20/system/authgraph/hal/src/channel.rs (revision 4185b0660fbe514985fdcf75410317caad8afad1)
1 // Copyright 2023 Google LLC
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 ////////////////////////////////////////////////////////////////////////////////
16 
17 //! Channel-related functionality and helpers.
18 
19 use log::error;
20 use std::ffi::CString;
21 use std::io::{Read, Write};
22 
23 /// Abstraction of a channel to a secure world TA implementation.
24 /// Required to be [`Sync`] to support multi-threaded use by the HAL service.
25 pub trait SerializedChannel: Send + Sync {
26     /// Maximum supported size for the channel in bytes.
27     const MAX_SIZE: usize;
28 
29     /// Accepts serialized request messages and returns serialized response messages
30     /// (or an error if communication via the channel is lost).
execute(&self, serialized_req: &[u8]) -> binder::Result<Vec<u8>>31     fn execute(&self, serialized_req: &[u8]) -> binder::Result<Vec<u8>>;
32 }
33 
34 /// Write a message to a stream-oriented [`Write`] item, with length framing.
write_msg<W: Write>(w: &mut W, data: &[u8]) -> binder::Result<()>35 pub fn write_msg<W: Write>(w: &mut W, data: &[u8]) -> binder::Result<()> {
36     // The underlying `Write` item does not guarantee delivery of complete messages.
37     // Make this possible by adding framing in the form of a big-endian `u32` holding
38     // the message length.
39     let data_len: u32 = data.len().try_into().map_err(|_e| {
40         binder::Status::new_exception(
41             binder::ExceptionCode::BAD_PARCELABLE,
42             Some(&CString::new("encoded request message too large").unwrap()),
43         )
44     })?;
45     let data_len_data = data_len.to_be_bytes();
46     w.write_all(&data_len_data[..]).map_err(|e| {
47         error!("Failed to write length to stream: {}", e);
48         binder::Status::new_exception(
49             binder::ExceptionCode::BAD_PARCELABLE,
50             Some(&CString::new("failed to write framing length").unwrap()),
51         )
52     })?;
53     w.write_all(data).map_err(|e| {
54         error!("Failed to write data to stream: {}", e);
55         binder::Status::new_exception(
56             binder::ExceptionCode::BAD_PARCELABLE,
57             Some(&CString::new("failed to write data").unwrap()),
58         )
59     })?;
60     Ok(())
61 }
62 
63 /// Read a message from a stream-oriented [`Read`] item, with length framing.
read_msg<R: Read>(r: &mut R) -> binder::Result<Vec<u8>>64 pub fn read_msg<R: Read>(r: &mut R) -> binder::Result<Vec<u8>> {
65     // The data read from the `Read` item has a 4-byte big-endian length prefix.
66     let mut len_data = [0u8; 4];
67     r.read_exact(&mut len_data).map_err(|e| {
68         error!("Failed to read length from stream: {}", e);
69         binder::Status::new_exception(binder::ExceptionCode::TRANSACTION_FAILED, None)
70     })?;
71     let len = u32::from_be_bytes(len_data);
72     let mut data = vec![0; len as usize];
73     r.read_exact(&mut data).map_err(|e| {
74         error!("Failed to read data from stream: {}", e);
75         binder::Status::new_exception(binder::ExceptionCode::TRANSACTION_FAILED, None)
76     })?;
77     Ok(data)
78 }
79