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 //! Functionality for KeyMint implementation that is common across HAL and TA.
16*9860b763SAndroid Build Coastguard Worker
17*9860b763SAndroid Build Coastguard Worker #![no_std]
18*9860b763SAndroid Build Coastguard Worker extern crate alloc;
19*9860b763SAndroid Build Coastguard Worker
20*9860b763SAndroid Build Coastguard Worker use alloc::{
21*9860b763SAndroid Build Coastguard Worker string::{String, ToString},
22*9860b763SAndroid Build Coastguard Worker vec::Vec,
23*9860b763SAndroid Build Coastguard Worker };
24*9860b763SAndroid Build Coastguard Worker use core::convert::From;
25*9860b763SAndroid Build Coastguard Worker use der::ErrorKind;
26*9860b763SAndroid Build Coastguard Worker use kmr_wire::{cbor, keymint::ErrorCode, rpc, CborError};
27*9860b763SAndroid Build Coastguard Worker
28*9860b763SAndroid Build Coastguard Worker pub use kmr_wire as wire;
29*9860b763SAndroid Build Coastguard Worker
30*9860b763SAndroid Build Coastguard Worker pub mod crypto;
31*9860b763SAndroid Build Coastguard Worker pub mod keyblob;
32*9860b763SAndroid Build Coastguard Worker pub mod tag;
33*9860b763SAndroid Build Coastguard Worker
34*9860b763SAndroid Build Coastguard Worker /// General error type.
35*9860b763SAndroid Build Coastguard Worker #[derive(Debug)]
36*9860b763SAndroid Build Coastguard Worker pub enum Error {
37*9860b763SAndroid Build Coastguard Worker /// Error from CBOR conversion.
38*9860b763SAndroid Build Coastguard Worker Cbor(CborError),
39*9860b763SAndroid Build Coastguard Worker /// Error from ASN.1 DER conversion.
40*9860b763SAndroid Build Coastguard Worker Der(ErrorKind),
41*9860b763SAndroid Build Coastguard Worker /// Error as reported on the HAL interface.
42*9860b763SAndroid Build Coastguard Worker ///
43*9860b763SAndroid Build Coastguard Worker /// The `IKeyMintDevice`, `ISharedSecret` and `ISecureClock` HALs all share the same numbering
44*9860b763SAndroid Build Coastguard Worker /// space for error codes, encoded here as [`kmr_wire::keymint::ErrorCode`].
45*9860b763SAndroid Build Coastguard Worker Hal(ErrorCode, String),
46*9860b763SAndroid Build Coastguard Worker /// Error as reported on the `IRemotelyProvisionedComponent` HAL, which uses its own error
47*9860b763SAndroid Build Coastguard Worker /// codes.
48*9860b763SAndroid Build Coastguard Worker Rpc(rpc::ErrorCode, String),
49*9860b763SAndroid Build Coastguard Worker /// Memory allocation error.
50*9860b763SAndroid Build Coastguard Worker ///
51*9860b763SAndroid Build Coastguard Worker /// This holds a string literal rather than an allocated `String` to avoid allocating in an
52*9860b763SAndroid Build Coastguard Worker /// allocation error path.
53*9860b763SAndroid Build Coastguard Worker Alloc(&'static str),
54*9860b763SAndroid Build Coastguard Worker }
55*9860b763SAndroid Build Coastguard Worker
56*9860b763SAndroid Build Coastguard Worker // The following macros for error generation allow the message portion to be automatically
57*9860b763SAndroid Build Coastguard Worker // compiled out in future, avoiding potential information leakage and allocation.
58*9860b763SAndroid Build Coastguard Worker
59*9860b763SAndroid Build Coastguard Worker /// Macro to build an [`Error::Hal`] instance for a specific [`ErrorCode`] value known at compile
60*9860b763SAndroid Build Coastguard Worker /// time: `km_err!(InvalidTag, "some {} format", arg)`.
61*9860b763SAndroid Build Coastguard Worker #[macro_export]
62*9860b763SAndroid Build Coastguard Worker macro_rules! km_err {
63*9860b763SAndroid Build Coastguard Worker { $error_code:ident, $($arg:tt)+ } => {
64*9860b763SAndroid Build Coastguard Worker $crate::Error::Hal(kmr_wire::keymint::ErrorCode::$error_code,
65*9860b763SAndroid Build Coastguard Worker alloc::format!("{}:{}: {}", file!(), line!(), format_args!($($arg)+))) };
66*9860b763SAndroid Build Coastguard Worker }
67*9860b763SAndroid Build Coastguard Worker
68*9860b763SAndroid Build Coastguard Worker /// Macro to build an [`Error::Hal`] instance:
69*9860b763SAndroid Build Coastguard Worker /// `km_verr!(rc, "some {} format", arg)`.
70*9860b763SAndroid Build Coastguard Worker #[macro_export]
71*9860b763SAndroid Build Coastguard Worker macro_rules! km_verr {
72*9860b763SAndroid Build Coastguard Worker { $error_code:expr, $($arg:tt)+ } => {
73*9860b763SAndroid Build Coastguard Worker $crate::Error::Hal($error_code,
74*9860b763SAndroid Build Coastguard Worker alloc::format!("{}:{}: {}", file!(), line!(), format_args!($($arg)+))) };
75*9860b763SAndroid Build Coastguard Worker }
76*9860b763SAndroid Build Coastguard Worker
77*9860b763SAndroid Build Coastguard Worker /// Macro to build an [`Error::Alloc`] instance. Note that this builds a `&'static str` at compile
78*9860b763SAndroid Build Coastguard Worker /// time, so there is no allocation needed for the message (which would be failure-prone when
79*9860b763SAndroid Build Coastguard Worker /// dealing with an allocation failure).
80*9860b763SAndroid Build Coastguard Worker #[macro_export]
81*9860b763SAndroid Build Coastguard Worker macro_rules! alloc_err {
82*9860b763SAndroid Build Coastguard Worker { $len:expr } => {
83*9860b763SAndroid Build Coastguard Worker $crate::Error::Alloc(
84*9860b763SAndroid Build Coastguard Worker concat!(file!(), ":", line!(), ": failed allocation of size ", stringify!($len))
85*9860b763SAndroid Build Coastguard Worker )
86*9860b763SAndroid Build Coastguard Worker }
87*9860b763SAndroid Build Coastguard Worker }
88*9860b763SAndroid Build Coastguard Worker
89*9860b763SAndroid Build Coastguard Worker /// Macro to build an [`Error::Der`] instance from a [`der::Error`].
90*9860b763SAndroid Build Coastguard Worker #[macro_export]
91*9860b763SAndroid Build Coastguard Worker macro_rules! der_err {
92*9860b763SAndroid Build Coastguard Worker { $err:expr, $($arg:tt)+ } => {
93*9860b763SAndroid Build Coastguard Worker {
94*9860b763SAndroid Build Coastguard Worker log::warn!("{}: {:?} at {:?}", format_args!($($arg)+), $err, $err.position());
95*9860b763SAndroid Build Coastguard Worker $crate::Error::Der($err.kind())
96*9860b763SAndroid Build Coastguard Worker }
97*9860b763SAndroid Build Coastguard Worker }
98*9860b763SAndroid Build Coastguard Worker }
99*9860b763SAndroid Build Coastguard Worker
100*9860b763SAndroid Build Coastguard Worker /// Macro to build an [`Error::Rpc`] instance for a specific [`rpc::ErrorCode`] value known at
101*9860b763SAndroid Build Coastguard Worker /// compile time: `rpc_err!(Removed, "some {} format", arg)`.
102*9860b763SAndroid Build Coastguard Worker #[macro_export]
103*9860b763SAndroid Build Coastguard Worker macro_rules! rpc_err {
104*9860b763SAndroid Build Coastguard Worker { $error_code:ident, $($arg:tt)+ } => {
105*9860b763SAndroid Build Coastguard Worker $crate::Error::Rpc(kmr_wire::rpc::ErrorCode::$error_code,
106*9860b763SAndroid Build Coastguard Worker alloc::format!("{}:{}: {}", file!(), line!(), format_args!($($arg)+))) };
107*9860b763SAndroid Build Coastguard Worker }
108*9860b763SAndroid Build Coastguard Worker
109*9860b763SAndroid Build Coastguard Worker /// Macro to allocate a `Vec<T>` with the given length reserved, detecting allocation failure.
110*9860b763SAndroid Build Coastguard Worker #[macro_export]
111*9860b763SAndroid Build Coastguard Worker macro_rules! vec_try_with_capacity {
112*9860b763SAndroid Build Coastguard Worker { $len:expr} => {
113*9860b763SAndroid Build Coastguard Worker {
114*9860b763SAndroid Build Coastguard Worker let mut v = alloc::vec::Vec::new();
115*9860b763SAndroid Build Coastguard Worker match v.try_reserve($len) {
116*9860b763SAndroid Build Coastguard Worker Err(_e) => Err($crate::alloc_err!($len)),
117*9860b763SAndroid Build Coastguard Worker Ok(_) => Ok(v),
118*9860b763SAndroid Build Coastguard Worker }
119*9860b763SAndroid Build Coastguard Worker }
120*9860b763SAndroid Build Coastguard Worker }
121*9860b763SAndroid Build Coastguard Worker }
122*9860b763SAndroid Build Coastguard Worker
123*9860b763SAndroid Build Coastguard Worker /// Macro that mimics `vec!` but which detects allocation failure.
124*9860b763SAndroid Build Coastguard Worker #[macro_export]
125*9860b763SAndroid Build Coastguard Worker macro_rules! vec_try {
126*9860b763SAndroid Build Coastguard Worker { $elem:expr ; $len:expr } => {
127*9860b763SAndroid Build Coastguard Worker kmr_wire::vec_try_fill_with_alloc_err($elem, $len, || $crate::alloc_err!($len))
128*9860b763SAndroid Build Coastguard Worker };
129*9860b763SAndroid Build Coastguard Worker { $x1:expr, $x2:expr, $x3:expr, $x4:expr $(,)? } => {
130*9860b763SAndroid Build Coastguard Worker kmr_wire::vec_try4_with_alloc_err($x1, $x2, $x3, $x4, || $crate::alloc_err!(4))
131*9860b763SAndroid Build Coastguard Worker };
132*9860b763SAndroid Build Coastguard Worker { $x1:expr, $x2:expr, $x3:expr $(,)? } => {
133*9860b763SAndroid Build Coastguard Worker kmr_wire::vec_try3_with_alloc_err($x1, $x2, $x3, || $crate::alloc_err!(3))
134*9860b763SAndroid Build Coastguard Worker };
135*9860b763SAndroid Build Coastguard Worker { $x1:expr, $x2:expr $(,)? } => {
136*9860b763SAndroid Build Coastguard Worker kmr_wire::vec_try2_with_alloc_err($x1, $x2, || $crate::alloc_err!(2))
137*9860b763SAndroid Build Coastguard Worker };
138*9860b763SAndroid Build Coastguard Worker { $x1:expr $(,)? } => {
139*9860b763SAndroid Build Coastguard Worker kmr_wire::vec_try1_with_alloc_err($x1, || $crate::alloc_err!(1))
140*9860b763SAndroid Build Coastguard Worker };
141*9860b763SAndroid Build Coastguard Worker }
142*9860b763SAndroid Build Coastguard Worker
143*9860b763SAndroid Build Coastguard Worker /// Function that mimics `slice.to_vec()` but which detects allocation failures.
144*9860b763SAndroid Build Coastguard Worker #[inline]
try_to_vec<T: Clone>(s: &[T]) -> Result<Vec<T>, Error>145*9860b763SAndroid Build Coastguard Worker pub fn try_to_vec<T: Clone>(s: &[T]) -> Result<Vec<T>, Error> {
146*9860b763SAndroid Build Coastguard Worker let mut v = vec_try_with_capacity!(s.len())?;
147*9860b763SAndroid Build Coastguard Worker v.extend_from_slice(s);
148*9860b763SAndroid Build Coastguard Worker Ok(v)
149*9860b763SAndroid Build Coastguard Worker }
150*9860b763SAndroid Build Coastguard Worker
151*9860b763SAndroid Build Coastguard Worker /// Extension trait to provide fallible-allocation variants of `Vec` methods.
152*9860b763SAndroid Build Coastguard Worker pub trait FallibleAllocExt<T> {
153*9860b763SAndroid Build Coastguard Worker /// Try to add the `value` to the collection, failing on memory exhaustion.
try_push(&mut self, value: T) -> Result<(), alloc::collections::TryReserveError>154*9860b763SAndroid Build Coastguard Worker fn try_push(&mut self, value: T) -> Result<(), alloc::collections::TryReserveError>;
155*9860b763SAndroid Build Coastguard Worker /// Try to extend the collection with the contents of `other`, failing on memory exhaustion.
try_extend_from_slice( &mut self, other: &[T], ) -> Result<(), alloc::collections::TryReserveError> where T: Clone156*9860b763SAndroid Build Coastguard Worker fn try_extend_from_slice(
157*9860b763SAndroid Build Coastguard Worker &mut self,
158*9860b763SAndroid Build Coastguard Worker other: &[T],
159*9860b763SAndroid Build Coastguard Worker ) -> Result<(), alloc::collections::TryReserveError>
160*9860b763SAndroid Build Coastguard Worker where
161*9860b763SAndroid Build Coastguard Worker T: Clone;
162*9860b763SAndroid Build Coastguard Worker }
163*9860b763SAndroid Build Coastguard Worker
164*9860b763SAndroid Build Coastguard Worker impl<T> FallibleAllocExt<T> for Vec<T> {
try_push(&mut self, value: T) -> Result<(), alloc::collections::TryReserveError>165*9860b763SAndroid Build Coastguard Worker fn try_push(&mut self, value: T) -> Result<(), alloc::collections::TryReserveError> {
166*9860b763SAndroid Build Coastguard Worker self.try_reserve(1)?;
167*9860b763SAndroid Build Coastguard Worker self.push(value);
168*9860b763SAndroid Build Coastguard Worker Ok(())
169*9860b763SAndroid Build Coastguard Worker }
try_extend_from_slice( &mut self, other: &[T], ) -> Result<(), alloc::collections::TryReserveError> where T: Clone,170*9860b763SAndroid Build Coastguard Worker fn try_extend_from_slice(
171*9860b763SAndroid Build Coastguard Worker &mut self,
172*9860b763SAndroid Build Coastguard Worker other: &[T],
173*9860b763SAndroid Build Coastguard Worker ) -> Result<(), alloc::collections::TryReserveError>
174*9860b763SAndroid Build Coastguard Worker where
175*9860b763SAndroid Build Coastguard Worker T: Clone,
176*9860b763SAndroid Build Coastguard Worker {
177*9860b763SAndroid Build Coastguard Worker self.try_reserve(other.len())?;
178*9860b763SAndroid Build Coastguard Worker self.extend_from_slice(other);
179*9860b763SAndroid Build Coastguard Worker Ok(())
180*9860b763SAndroid Build Coastguard Worker }
181*9860b763SAndroid Build Coastguard Worker }
182*9860b763SAndroid Build Coastguard Worker
183*9860b763SAndroid Build Coastguard Worker impl From<alloc::collections::TryReserveError> for Error {
from(_e: alloc::collections::TryReserveError) -> Self184*9860b763SAndroid Build Coastguard Worker fn from(_e: alloc::collections::TryReserveError) -> Self {
185*9860b763SAndroid Build Coastguard Worker Error::Hal(
186*9860b763SAndroid Build Coastguard Worker kmr_wire::keymint::ErrorCode::MemoryAllocationFailed,
187*9860b763SAndroid Build Coastguard Worker "allocation of Vec failed".to_string(),
188*9860b763SAndroid Build Coastguard Worker )
189*9860b763SAndroid Build Coastguard Worker }
190*9860b763SAndroid Build Coastguard Worker }
191*9860b763SAndroid Build Coastguard Worker
192*9860b763SAndroid Build Coastguard Worker impl From<CborError> for Error {
from(e: CborError) -> Self193*9860b763SAndroid Build Coastguard Worker fn from(e: CborError) -> Self {
194*9860b763SAndroid Build Coastguard Worker Error::Cbor(e)
195*9860b763SAndroid Build Coastguard Worker }
196*9860b763SAndroid Build Coastguard Worker }
197*9860b763SAndroid Build Coastguard Worker
198*9860b763SAndroid Build Coastguard Worker impl From<cbor::value::Error> for Error {
from(e: cbor::value::Error) -> Self199*9860b763SAndroid Build Coastguard Worker fn from(e: cbor::value::Error) -> Self {
200*9860b763SAndroid Build Coastguard Worker Self::Cbor(e.into())
201*9860b763SAndroid Build Coastguard Worker }
202*9860b763SAndroid Build Coastguard Worker }
203*9860b763SAndroid Build Coastguard Worker
204*9860b763SAndroid Build Coastguard Worker /// Check for an expected error.
205*9860b763SAndroid Build Coastguard Worker #[macro_export]
206*9860b763SAndroid Build Coastguard Worker macro_rules! expect_err {
207*9860b763SAndroid Build Coastguard Worker ($result:expr, $err_msg:expr) => {
208*9860b763SAndroid Build Coastguard Worker assert!(
209*9860b763SAndroid Build Coastguard Worker $result.is_err(),
210*9860b763SAndroid Build Coastguard Worker "Expected error containing '{}', got success {:?}",
211*9860b763SAndroid Build Coastguard Worker $err_msg,
212*9860b763SAndroid Build Coastguard Worker $result
213*9860b763SAndroid Build Coastguard Worker );
214*9860b763SAndroid Build Coastguard Worker let err = $result.err();
215*9860b763SAndroid Build Coastguard Worker assert!(
216*9860b763SAndroid Build Coastguard Worker alloc::format!("{:?}", err).contains($err_msg),
217*9860b763SAndroid Build Coastguard Worker "Unexpected error {:?}, doesn't contain '{}'",
218*9860b763SAndroid Build Coastguard Worker err,
219*9860b763SAndroid Build Coastguard Worker $err_msg
220*9860b763SAndroid Build Coastguard Worker );
221*9860b763SAndroid Build Coastguard Worker };
222*9860b763SAndroid Build Coastguard Worker }
223