xref: /aosp_15_r20/system/keymint/hal/src/lib.rs (revision 9860b7637a5f185913c70aa0caabe3ecb78441e4)
1*9860b763SAndroid Build Coastguard Worker // Copyright 2022, The Android Open Source Project
2*9860b763SAndroid Build Coastguard Worker //
3*9860b763SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9860b763SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9860b763SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9860b763SAndroid Build Coastguard Worker //
7*9860b763SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*9860b763SAndroid Build Coastguard Worker //
9*9860b763SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9860b763SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9860b763SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9860b763SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9860b763SAndroid Build Coastguard Worker // limitations under the License.
14*9860b763SAndroid Build Coastguard Worker 
15*9860b763SAndroid Build Coastguard Worker //! Implementation of a HAL service for KeyMint.
16*9860b763SAndroid Build Coastguard Worker //!
17*9860b763SAndroid Build Coastguard Worker //! This implementation relies on a `SerializedChannel` abstraction for a communication channel to
18*9860b763SAndroid Build Coastguard Worker //! the trusted application (TA).  Incoming method invocations for the HAL service are converted
19*9860b763SAndroid Build Coastguard Worker //! into corresponding request structures, which are then serialized (using CBOR) and send down the
20*9860b763SAndroid Build Coastguard Worker //! channel.  A serialized response is then read from the channel, which is deserialized into a
21*9860b763SAndroid Build Coastguard Worker //! response structure.  The contents of this response structure are then used to populate the
22*9860b763SAndroid Build Coastguard Worker //! return values of the HAL service method.
23*9860b763SAndroid Build Coastguard Worker 
24*9860b763SAndroid Build Coastguard Worker #![allow(non_snake_case)]
25*9860b763SAndroid Build Coastguard Worker 
26*9860b763SAndroid Build Coastguard Worker use core::{convert::TryInto, fmt::Debug};
27*9860b763SAndroid Build Coastguard Worker use kmr_wire::{
28*9860b763SAndroid Build Coastguard Worker     cbor, cbor_type_error, keymint::ErrorCode, keymint::NEXT_MESSAGE_SIGNAL_TRUE, AsCborValue,
29*9860b763SAndroid Build Coastguard Worker     CborError, Code, KeyMintOperation,
30*9860b763SAndroid Build Coastguard Worker };
31*9860b763SAndroid Build Coastguard Worker use log::{error, info, warn};
32*9860b763SAndroid Build Coastguard Worker use std::{
33*9860b763SAndroid Build Coastguard Worker     ffi::CString,
34*9860b763SAndroid Build Coastguard Worker     io::{Read, Write},
35*9860b763SAndroid Build Coastguard Worker     ops::DerefMut,
36*9860b763SAndroid Build Coastguard Worker     sync::MutexGuard,
37*9860b763SAndroid Build Coastguard Worker };
38*9860b763SAndroid Build Coastguard Worker 
39*9860b763SAndroid Build Coastguard Worker pub use binder;
40*9860b763SAndroid Build Coastguard Worker 
41*9860b763SAndroid Build Coastguard Worker pub mod env;
42*9860b763SAndroid Build Coastguard Worker pub mod hal;
43*9860b763SAndroid Build Coastguard Worker pub mod keymint;
44*9860b763SAndroid Build Coastguard Worker pub mod rpc;
45*9860b763SAndroid Build Coastguard Worker pub mod secureclock;
46*9860b763SAndroid Build Coastguard Worker pub mod sharedsecret;
47*9860b763SAndroid Build Coastguard Worker #[cfg(test)]
48*9860b763SAndroid Build Coastguard Worker mod tests;
49*9860b763SAndroid Build Coastguard Worker 
50*9860b763SAndroid Build Coastguard Worker /// Emit a failure for a failed CBOR conversion.
51*9860b763SAndroid Build Coastguard Worker #[inline]
failed_cbor(err: CborError) -> binder::Status52*9860b763SAndroid Build Coastguard Worker pub fn failed_cbor(err: CborError) -> binder::Status {
53*9860b763SAndroid Build Coastguard Worker     binder::Status::new_service_specific_error(
54*9860b763SAndroid Build Coastguard Worker         ErrorCode::EncodingError as i32,
55*9860b763SAndroid Build Coastguard Worker         Some(&CString::new(format!("CBOR conversion failed: {:?}", err)).unwrap()),
56*9860b763SAndroid Build Coastguard Worker     )
57*9860b763SAndroid Build Coastguard Worker }
58*9860b763SAndroid Build Coastguard Worker 
59*9860b763SAndroid Build Coastguard Worker /// Abstraction of a channel to a secure world TA implementation.
60*9860b763SAndroid Build Coastguard Worker pub trait SerializedChannel: Debug + Send {
61*9860b763SAndroid Build Coastguard Worker     /// Maximum supported size for the channel in bytes.
62*9860b763SAndroid Build Coastguard Worker     const MAX_SIZE: usize;
63*9860b763SAndroid Build Coastguard Worker 
64*9860b763SAndroid Build Coastguard Worker     /// Accepts serialized request messages and returns serialized return values
65*9860b763SAndroid Build Coastguard Worker     /// (or an error if communication via the channel is lost).
execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>>66*9860b763SAndroid Build Coastguard Worker     fn execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>>;
67*9860b763SAndroid Build Coastguard Worker }
68*9860b763SAndroid Build Coastguard Worker 
69*9860b763SAndroid Build Coastguard Worker /// A helper method to be used in the [`execute`] method above, in order to handle
70*9860b763SAndroid Build Coastguard Worker /// responses received from the TA, especially those which are larger than the capacity of the
71*9860b763SAndroid Build Coastguard Worker /// channel between the HAL and the TA.
72*9860b763SAndroid Build Coastguard Worker /// This inspects the message, checks the first byte to see if the response arrives in multiple
73*9860b763SAndroid Build Coastguard Worker /// messages. A boolean indicating whether or not to wait for the next message and the
74*9860b763SAndroid Build Coastguard Worker /// response content (with the first byte stripped off) are returned to
75*9860b763SAndroid Build Coastguard Worker /// the HAL service . Implementation of this method must be in sync with its counterpart
76*9860b763SAndroid Build Coastguard Worker /// in the `kmr-ta` crate.
extract_rsp(rsp: &[u8]) -> binder::Result<(bool, &[u8])>77*9860b763SAndroid Build Coastguard Worker pub fn extract_rsp(rsp: &[u8]) -> binder::Result<(bool, &[u8])> {
78*9860b763SAndroid Build Coastguard Worker     if rsp.len() < 2 {
79*9860b763SAndroid Build Coastguard Worker         return Err(binder::Status::new_exception(
80*9860b763SAndroid Build Coastguard Worker             binder::ExceptionCode::ILLEGAL_ARGUMENT,
81*9860b763SAndroid Build Coastguard Worker             Some(&CString::new("message is too small to extract the response data").unwrap()),
82*9860b763SAndroid Build Coastguard Worker         ));
83*9860b763SAndroid Build Coastguard Worker     }
84*9860b763SAndroid Build Coastguard Worker     Ok((rsp[0] == NEXT_MESSAGE_SIGNAL_TRUE, &rsp[1..]))
85*9860b763SAndroid Build Coastguard Worker }
86*9860b763SAndroid Build Coastguard Worker 
87*9860b763SAndroid Build Coastguard Worker /// Write a message to a stream-oriented [`Write`] item, with length framing.
write_msg<W: Write>(w: &mut W, data: &[u8]) -> binder::Result<()>88*9860b763SAndroid Build Coastguard Worker pub fn write_msg<W: Write>(w: &mut W, data: &[u8]) -> binder::Result<()> {
89*9860b763SAndroid Build Coastguard Worker     // The underlying `Write` item does not guarantee delivery of complete messages.
90*9860b763SAndroid Build Coastguard Worker     // Make this possible by adding framing in the form of a big-endian `u32` holding
91*9860b763SAndroid Build Coastguard Worker     // the message length.
92*9860b763SAndroid Build Coastguard Worker     let data_len: u32 = data.len().try_into().map_err(|_e| {
93*9860b763SAndroid Build Coastguard Worker         binder::Status::new_exception(
94*9860b763SAndroid Build Coastguard Worker             binder::ExceptionCode::BAD_PARCELABLE,
95*9860b763SAndroid Build Coastguard Worker             Some(&CString::new("encoded request message too large").unwrap()),
96*9860b763SAndroid Build Coastguard Worker         )
97*9860b763SAndroid Build Coastguard Worker     })?;
98*9860b763SAndroid Build Coastguard Worker     let data_len_data = data_len.to_be_bytes();
99*9860b763SAndroid Build Coastguard Worker     w.write_all(&data_len_data[..]).map_err(|e| {
100*9860b763SAndroid Build Coastguard Worker         error!("Failed to write length to stream: {}", e);
101*9860b763SAndroid Build Coastguard Worker         binder::Status::new_exception(
102*9860b763SAndroid Build Coastguard Worker             binder::ExceptionCode::BAD_PARCELABLE,
103*9860b763SAndroid Build Coastguard Worker             Some(&CString::new("failed to write framing length").unwrap()),
104*9860b763SAndroid Build Coastguard Worker         )
105*9860b763SAndroid Build Coastguard Worker     })?;
106*9860b763SAndroid Build Coastguard Worker     w.write_all(data).map_err(|e| {
107*9860b763SAndroid Build Coastguard Worker         error!("Failed to write data to stream: {}", e);
108*9860b763SAndroid Build Coastguard Worker         binder::Status::new_exception(
109*9860b763SAndroid Build Coastguard Worker             binder::ExceptionCode::BAD_PARCELABLE,
110*9860b763SAndroid Build Coastguard Worker             Some(&CString::new("failed to write data").unwrap()),
111*9860b763SAndroid Build Coastguard Worker         )
112*9860b763SAndroid Build Coastguard Worker     })?;
113*9860b763SAndroid Build Coastguard Worker     Ok(())
114*9860b763SAndroid Build Coastguard Worker }
115*9860b763SAndroid Build Coastguard Worker 
116*9860b763SAndroid Build Coastguard Worker /// Read a message from a stream-oriented [`Read`] item, with length framing.
read_msg<R: Read>(r: &mut R) -> binder::Result<Vec<u8>>117*9860b763SAndroid Build Coastguard Worker pub fn read_msg<R: Read>(r: &mut R) -> binder::Result<Vec<u8>> {
118*9860b763SAndroid Build Coastguard Worker     // The data read from the `Read` item has a 4-byte big-endian length prefix.
119*9860b763SAndroid Build Coastguard Worker     let mut len_data = [0u8; 4];
120*9860b763SAndroid Build Coastguard Worker     r.read_exact(&mut len_data).map_err(|e| {
121*9860b763SAndroid Build Coastguard Worker         error!("Failed to read length from stream: {}", e);
122*9860b763SAndroid Build Coastguard Worker         binder::Status::new_exception(binder::ExceptionCode::TRANSACTION_FAILED, None)
123*9860b763SAndroid Build Coastguard Worker     })?;
124*9860b763SAndroid Build Coastguard Worker     let len = u32::from_be_bytes(len_data);
125*9860b763SAndroid Build Coastguard Worker     let mut data = vec![0; len as usize];
126*9860b763SAndroid Build Coastguard Worker     r.read_exact(&mut data).map_err(|e| {
127*9860b763SAndroid Build Coastguard Worker         error!("Failed to read data from stream: {}", e);
128*9860b763SAndroid Build Coastguard Worker         binder::Status::new_exception(binder::ExceptionCode::TRANSACTION_FAILED, None)
129*9860b763SAndroid Build Coastguard Worker     })?;
130*9860b763SAndroid Build Coastguard Worker     Ok(data)
131*9860b763SAndroid Build Coastguard Worker }
132*9860b763SAndroid Build Coastguard Worker 
133*9860b763SAndroid Build Coastguard Worker /// Message-oriented wrapper around a pair of stream-oriented channels.  This allows a pair of
134*9860b763SAndroid Build Coastguard Worker /// uni-directional channels that don't necessarily preserve message boundaries to appear as a
135*9860b763SAndroid Build Coastguard Worker /// single bi-directional channel that does preserve message boundaries.
136*9860b763SAndroid Build Coastguard Worker #[derive(Debug)]
137*9860b763SAndroid Build Coastguard Worker pub struct MessageChannel<R: Read, W: Write> {
138*9860b763SAndroid Build Coastguard Worker     r: R,
139*9860b763SAndroid Build Coastguard Worker     w: W,
140*9860b763SAndroid Build Coastguard Worker }
141*9860b763SAndroid Build Coastguard Worker 
142*9860b763SAndroid Build Coastguard Worker impl<R: Read + Debug + Send, W: Write + Debug + Send> SerializedChannel for MessageChannel<R, W> {
143*9860b763SAndroid Build Coastguard Worker     const MAX_SIZE: usize = 4096;
144*9860b763SAndroid Build Coastguard Worker 
execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>>145*9860b763SAndroid Build Coastguard Worker     fn execute(&mut self, serialized_req: &[u8]) -> binder::Result<Vec<u8>> {
146*9860b763SAndroid Build Coastguard Worker         write_msg(&mut self.w, serialized_req)?;
147*9860b763SAndroid Build Coastguard Worker         read_msg(&mut self.r)
148*9860b763SAndroid Build Coastguard Worker     }
149*9860b763SAndroid Build Coastguard Worker }
150*9860b763SAndroid Build Coastguard Worker 
151*9860b763SAndroid Build Coastguard Worker /// Execute an operation by serializing and sending a request structure down a channel, and
152*9860b763SAndroid Build Coastguard Worker /// deserializing and returning the response.
153*9860b763SAndroid Build Coastguard Worker ///
154*9860b763SAndroid Build Coastguard Worker /// This implementation relies on the internal serialization format for `PerformOpReq` and
155*9860b763SAndroid Build Coastguard Worker /// `PerformOpRsp` to allow direct use of the specific request/response types.
channel_execute<T, R, S>(channel: &mut T, req: R) -> binder::Result<S> where T: SerializedChannel, R: AsCborValue + Code<KeyMintOperation>, S: AsCborValue + Code<KeyMintOperation>,156*9860b763SAndroid Build Coastguard Worker fn channel_execute<T, R, S>(channel: &mut T, req: R) -> binder::Result<S>
157*9860b763SAndroid Build Coastguard Worker where
158*9860b763SAndroid Build Coastguard Worker     T: SerializedChannel,
159*9860b763SAndroid Build Coastguard Worker     R: AsCborValue + Code<KeyMintOperation>,
160*9860b763SAndroid Build Coastguard Worker     S: AsCborValue + Code<KeyMintOperation>,
161*9860b763SAndroid Build Coastguard Worker {
162*9860b763SAndroid Build Coastguard Worker     // Manually build an array that includes the opcode and the encoded request and encode it.
163*9860b763SAndroid Build Coastguard Worker     // This is equivalent to `PerformOpReq::to_vec()`.
164*9860b763SAndroid Build Coastguard Worker     let req_arr = cbor::value::Value::Array(vec![
165*9860b763SAndroid Build Coastguard Worker         <R>::CODE.to_cbor_value().map_err(failed_cbor)?,
166*9860b763SAndroid Build Coastguard Worker         req.to_cbor_value().map_err(failed_cbor)?,
167*9860b763SAndroid Build Coastguard Worker     ]);
168*9860b763SAndroid Build Coastguard Worker     let mut req_data = Vec::new();
169*9860b763SAndroid Build Coastguard Worker     cbor::ser::into_writer(&req_arr, &mut req_data).map_err(|e| {
170*9860b763SAndroid Build Coastguard Worker         binder::Status::new_service_specific_error(
171*9860b763SAndroid Build Coastguard Worker             ErrorCode::EncodingError as i32,
172*9860b763SAndroid Build Coastguard Worker             Some(
173*9860b763SAndroid Build Coastguard Worker                 &CString::new(format!("failed to write CBOR request to buffer: {:?}", e)).unwrap(),
174*9860b763SAndroid Build Coastguard Worker             ),
175*9860b763SAndroid Build Coastguard Worker         )
176*9860b763SAndroid Build Coastguard Worker     })?;
177*9860b763SAndroid Build Coastguard Worker 
178*9860b763SAndroid Build Coastguard Worker     if req_data.len() > T::MAX_SIZE {
179*9860b763SAndroid Build Coastguard Worker         error!(
180*9860b763SAndroid Build Coastguard Worker             "HAL operation {:?} encodes bigger {} than max size {}",
181*9860b763SAndroid Build Coastguard Worker             <R>::CODE,
182*9860b763SAndroid Build Coastguard Worker             req_data.len(),
183*9860b763SAndroid Build Coastguard Worker             T::MAX_SIZE
184*9860b763SAndroid Build Coastguard Worker         );
185*9860b763SAndroid Build Coastguard Worker         return Err(binder::Status::new_service_specific_error(
186*9860b763SAndroid Build Coastguard Worker             ErrorCode::InvalidInputLength as i32,
187*9860b763SAndroid Build Coastguard Worker             Some(&CString::new("encoded request message too large").unwrap()),
188*9860b763SAndroid Build Coastguard Worker         ));
189*9860b763SAndroid Build Coastguard Worker     }
190*9860b763SAndroid Build Coastguard Worker 
191*9860b763SAndroid Build Coastguard Worker     // Send in request bytes, get back response bytes.
192*9860b763SAndroid Build Coastguard Worker     let rsp_data = channel.execute(&req_data)?;
193*9860b763SAndroid Build Coastguard Worker 
194*9860b763SAndroid Build Coastguard Worker     // Convert the raw response data to an array of [error code, opt_response].
195*9860b763SAndroid Build Coastguard Worker     let rsp_value = kmr_wire::read_to_value(&rsp_data).map_err(failed_cbor)?;
196*9860b763SAndroid Build Coastguard Worker     let mut rsp_array = match rsp_value {
197*9860b763SAndroid Build Coastguard Worker         cbor::value::Value::Array(a) if a.len() == 2 => a,
198*9860b763SAndroid Build Coastguard Worker         _ => {
199*9860b763SAndroid Build Coastguard Worker             error!("HAL: failed to parse response data 2-array!");
200*9860b763SAndroid Build Coastguard Worker             return cbor_type_error(&rsp_value, "arr of len 2").map_err(failed_cbor);
201*9860b763SAndroid Build Coastguard Worker         }
202*9860b763SAndroid Build Coastguard Worker     };
203*9860b763SAndroid Build Coastguard Worker     let opt_response = rsp_array.remove(1);
204*9860b763SAndroid Build Coastguard Worker     let error_code = <i32>::from_cbor_value(rsp_array.remove(0)).map_err(failed_cbor)?;
205*9860b763SAndroid Build Coastguard Worker     // The error code is in a numbering space that depends on the specific HAL being
206*9860b763SAndroid Build Coastguard Worker     // invoked (IRemotelyProvisionedComponent vs. the rest). However, the OK value is
207*9860b763SAndroid Build Coastguard Worker     // the same in all spaces.
208*9860b763SAndroid Build Coastguard Worker     if error_code != ErrorCode::Ok as i32 {
209*9860b763SAndroid Build Coastguard Worker         warn!("HAL: command {:?} failed: {:?}", <R>::CODE, error_code);
210*9860b763SAndroid Build Coastguard Worker         return Err(binder::Status::new_service_specific_error(error_code, None));
211*9860b763SAndroid Build Coastguard Worker     }
212*9860b763SAndroid Build Coastguard Worker 
213*9860b763SAndroid Build Coastguard Worker     // The optional response should be an array of exactly 1 element (because the 0-element case
214*9860b763SAndroid Build Coastguard Worker     // corresponds to a non-OK error code, which has just been dealt with).
215*9860b763SAndroid Build Coastguard Worker     let rsp = match opt_response {
216*9860b763SAndroid Build Coastguard Worker         cbor::value::Value::Array(mut a) if a.len() == 1 => a.remove(0),
217*9860b763SAndroid Build Coastguard Worker         _ => {
218*9860b763SAndroid Build Coastguard Worker             error!("HAL: failed to parse response data structure!");
219*9860b763SAndroid Build Coastguard Worker             return cbor_type_error(&opt_response, "arr of len 1").map_err(failed_cbor);
220*9860b763SAndroid Build Coastguard Worker         }
221*9860b763SAndroid Build Coastguard Worker     };
222*9860b763SAndroid Build Coastguard Worker 
223*9860b763SAndroid Build Coastguard Worker     // The response is expected to be an array of 2 elements: a op_type code and an encoded response
224*9860b763SAndroid Build Coastguard Worker     // structure.  The op_type code indicates the type of response structure, which should be what
225*9860b763SAndroid Build Coastguard Worker     // we expect.
226*9860b763SAndroid Build Coastguard Worker     let mut inner_rsp_array = match rsp {
227*9860b763SAndroid Build Coastguard Worker         cbor::value::Value::Array(a) if a.len() == 2 => a,
228*9860b763SAndroid Build Coastguard Worker         _ => {
229*9860b763SAndroid Build Coastguard Worker             error!("HAL: failed to parse inner response data structure!");
230*9860b763SAndroid Build Coastguard Worker             return cbor_type_error(&rsp, "arr of len 2").map_err(failed_cbor);
231*9860b763SAndroid Build Coastguard Worker         }
232*9860b763SAndroid Build Coastguard Worker     };
233*9860b763SAndroid Build Coastguard Worker     let inner_rsp = inner_rsp_array.remove(1);
234*9860b763SAndroid Build Coastguard Worker     let op_type =
235*9860b763SAndroid Build Coastguard Worker         <KeyMintOperation>::from_cbor_value(inner_rsp_array.remove(0)).map_err(failed_cbor)?;
236*9860b763SAndroid Build Coastguard Worker     if op_type != <S>::CODE {
237*9860b763SAndroid Build Coastguard Worker         error!("HAL: inner response data for unexpected opcode {:?}!", op_type);
238*9860b763SAndroid Build Coastguard Worker         return Err(failed_cbor(CborError::UnexpectedItem("wrong ret code", "rsp ret code")));
239*9860b763SAndroid Build Coastguard Worker     }
240*9860b763SAndroid Build Coastguard Worker 
241*9860b763SAndroid Build Coastguard Worker     <S>::from_cbor_value(inner_rsp).map_err(failed_cbor)
242*9860b763SAndroid Build Coastguard Worker }
243*9860b763SAndroid Build Coastguard Worker 
244*9860b763SAndroid Build Coastguard Worker /// Abstraction of a HAL service that uses an underlying [`SerializedChannel`] to communicate with
245*9860b763SAndroid Build Coastguard Worker /// an associated TA.
246*9860b763SAndroid Build Coastguard Worker trait ChannelHalService<T: SerializedChannel> {
247*9860b763SAndroid Build Coastguard Worker     /// Return the underlying channel.
channel(&self) -> MutexGuard<T>248*9860b763SAndroid Build Coastguard Worker     fn channel(&self) -> MutexGuard<T>;
249*9860b763SAndroid Build Coastguard Worker 
250*9860b763SAndroid Build Coastguard Worker     /// Execute the given request, by serializing it and sending it down the internal channel.  Then
251*9860b763SAndroid Build Coastguard Worker     /// read and deserialize the response.
execute<R, S>(&self, req: R) -> binder::Result<S> where R: AsCborValue + Code<KeyMintOperation>, S: AsCborValue + Code<KeyMintOperation>,252*9860b763SAndroid Build Coastguard Worker     fn execute<R, S>(&self, req: R) -> binder::Result<S>
253*9860b763SAndroid Build Coastguard Worker     where
254*9860b763SAndroid Build Coastguard Worker         R: AsCborValue + Code<KeyMintOperation>,
255*9860b763SAndroid Build Coastguard Worker         S: AsCborValue + Code<KeyMintOperation>,
256*9860b763SAndroid Build Coastguard Worker     {
257*9860b763SAndroid Build Coastguard Worker         channel_execute(self.channel().deref_mut(), req)
258*9860b763SAndroid Build Coastguard Worker     }
259*9860b763SAndroid Build Coastguard Worker }
260*9860b763SAndroid Build Coastguard Worker 
261*9860b763SAndroid Build Coastguard Worker /// Let the TA know information about the userspace environment.
send_hal_info<T: SerializedChannel>(channel: &mut T) -> binder::Result<()>262*9860b763SAndroid Build Coastguard Worker pub fn send_hal_info<T: SerializedChannel>(channel: &mut T) -> binder::Result<()> {
263*9860b763SAndroid Build Coastguard Worker     let req = env::populate_hal_info().map_err(|e| {
264*9860b763SAndroid Build Coastguard Worker         binder::Status::new_exception(
265*9860b763SAndroid Build Coastguard Worker             binder::ExceptionCode::BAD_PARCELABLE,
266*9860b763SAndroid Build Coastguard Worker             Some(&CString::new(format!("failed to determine HAL environment: {}", e)).unwrap()),
267*9860b763SAndroid Build Coastguard Worker         )
268*9860b763SAndroid Build Coastguard Worker     })?;
269*9860b763SAndroid Build Coastguard Worker     info!("HAL->TA: environment info is {:?}", req);
270*9860b763SAndroid Build Coastguard Worker     let _rsp: kmr_wire::SetHalInfoResponse = channel_execute(channel, req)?;
271*9860b763SAndroid Build Coastguard Worker 
272*9860b763SAndroid Build Coastguard Worker     let aidl_version = if cfg!(feature = "hal_v4") {
273*9860b763SAndroid Build Coastguard Worker         400
274*9860b763SAndroid Build Coastguard Worker     } else if cfg!(feature = "hal_v3") {
275*9860b763SAndroid Build Coastguard Worker         300
276*9860b763SAndroid Build Coastguard Worker     } else if cfg!(feature = "hal_v2") {
277*9860b763SAndroid Build Coastguard Worker         200
278*9860b763SAndroid Build Coastguard Worker     } else {
279*9860b763SAndroid Build Coastguard Worker         100
280*9860b763SAndroid Build Coastguard Worker     };
281*9860b763SAndroid Build Coastguard Worker     let req = kmr_wire::SetHalVersionRequest { aidl_version };
282*9860b763SAndroid Build Coastguard Worker     info!("HAL->TA: setting KeyMint HAL version to {}", aidl_version);
283*9860b763SAndroid Build Coastguard Worker     let result: binder::Result<kmr_wire::SetHalVersionResponse> = channel_execute(channel, req);
284*9860b763SAndroid Build Coastguard Worker     if let Err(e) = result {
285*9860b763SAndroid Build Coastguard Worker         // The SetHalVersionRequest message was added later; an earlier TA may not recognize it.
286*9860b763SAndroid Build Coastguard Worker         warn!("Setting KeyMint HAL version failed: {:?}", e);
287*9860b763SAndroid Build Coastguard Worker     }
288*9860b763SAndroid Build Coastguard Worker     Ok(())
289*9860b763SAndroid Build Coastguard Worker }
290*9860b763SAndroid Build Coastguard Worker 
291*9860b763SAndroid Build Coastguard Worker /// Let the TA know information about the boot environment.
send_boot_info<T: SerializedChannel>( channel: &mut T, req: kmr_wire::SetBootInfoRequest, ) -> binder::Result<()>292*9860b763SAndroid Build Coastguard Worker pub fn send_boot_info<T: SerializedChannel>(
293*9860b763SAndroid Build Coastguard Worker     channel: &mut T,
294*9860b763SAndroid Build Coastguard Worker     req: kmr_wire::SetBootInfoRequest,
295*9860b763SAndroid Build Coastguard Worker ) -> binder::Result<()> {
296*9860b763SAndroid Build Coastguard Worker     info!("boot->TA: boot info is {:?}", req);
297*9860b763SAndroid Build Coastguard Worker     let _rsp: kmr_wire::SetBootInfoResponse = channel_execute(channel, req)?;
298*9860b763SAndroid Build Coastguard Worker     Ok(())
299*9860b763SAndroid Build Coastguard Worker }
300*9860b763SAndroid Build Coastguard Worker 
301*9860b763SAndroid Build Coastguard Worker /// Provision the TA with attestation ID information.
send_attest_ids<T: SerializedChannel>( channel: &mut T, ids: kmr_wire::AttestationIdInfo, ) -> binder::Result<()>302*9860b763SAndroid Build Coastguard Worker pub fn send_attest_ids<T: SerializedChannel>(
303*9860b763SAndroid Build Coastguard Worker     channel: &mut T,
304*9860b763SAndroid Build Coastguard Worker     ids: kmr_wire::AttestationIdInfo,
305*9860b763SAndroid Build Coastguard Worker ) -> binder::Result<()> {
306*9860b763SAndroid Build Coastguard Worker     let req = kmr_wire::SetAttestationIdsRequest { ids };
307*9860b763SAndroid Build Coastguard Worker     info!("provision->attestation IDs are {:?}", req);
308*9860b763SAndroid Build Coastguard Worker     let _rsp: kmr_wire::SetAttestationIdsResponse = channel_execute(channel, req)?;
309*9860b763SAndroid Build Coastguard Worker     Ok(())
310*9860b763SAndroid Build Coastguard Worker }
311*9860b763SAndroid Build Coastguard Worker 
312*9860b763SAndroid Build Coastguard Worker /// Let the TA know that early boot has ended
early_boot_ended<T: SerializedChannel>(channel: &mut T) -> binder::Result<()>313*9860b763SAndroid Build Coastguard Worker pub fn early_boot_ended<T: SerializedChannel>(channel: &mut T) -> binder::Result<()> {
314*9860b763SAndroid Build Coastguard Worker     info!("boot->TA: early boot ended");
315*9860b763SAndroid Build Coastguard Worker     let req = kmr_wire::EarlyBootEndedRequest {};
316*9860b763SAndroid Build Coastguard Worker     let _rsp: kmr_wire::EarlyBootEndedResponse = channel_execute(channel, req)?;
317*9860b763SAndroid Build Coastguard Worker     Ok(())
318*9860b763SAndroid Build Coastguard Worker }
319