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