1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! HwCrypto error handling code and related structures
18 
19 use alloc::{collections::TryReserveError, ffi::CString};
20 pub use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::types::HalErrorCode;
21 use android_hardware_security_see_hwcrypto::binder;
22 use core::array::TryFromSliceError;
23 use coset::CoseError;
24 use std::sync::PoisonError;
25 use tipc::TipcError;
26 use vm_memory::VolatileMemoryError;
27 
28 /// Macro used to create a `HwCryptoError::HalError` by providing the AIDL `HalErrorCode` and a
29 /// message: `hwcrypto_err!(UNSUPPORTED, "unsupported operation")`
30 #[macro_export]
31 macro_rules! hwcrypto_err {
32     { $error_code:ident, $($arg:tt)+ } => {
33         $crate::err::HwCryptoError::HalError {
34                 code: $crate::err::HalErrorCode::$error_code,
35                 file: std::file!(),
36                 line: std::line!(),
37                 message: alloc::format!("{}",std::format_args!($($arg)+)),
38         }
39     };
40 }
41 
42 /// Base Error type for HwCrypto library.
43 #[derive(Debug)]
44 pub enum HwCryptoError {
45     /// HwCrypto library native error
46     HalError { code: i32, file: &'static str, line: u32, message: String },
47     /// Error generated by a keymint library
48     KmError(kmr_common::Error),
49     /// Error when (de)serializing CBOR objects
50     CborError(kmr_wire::CborError),
51 }
52 
53 impl HwCryptoError {
matches_hal_error_code(&self, error_code: i32) -> bool54     pub fn matches_hal_error_code(&self, error_code: i32) -> bool {
55         core::matches!(self, HwCryptoError::HalError { code, .. } if *code == error_code)
56     }
57 }
58 
59 impl From<kmr_wire::CborError> for HwCryptoError {
from(e: kmr_wire::CborError) -> Self60     fn from(e: kmr_wire::CborError) -> Self {
61         HwCryptoError::CborError(e)
62     }
63 }
64 
65 impl From<TipcError> for HwCryptoError {
from(e: TipcError) -> Self66     fn from(e: TipcError) -> Self {
67         hwcrypto_err!(GENERIC_ERROR, "tipc communication error: {:?}", e)
68     }
69 }
70 
71 impl From<kmr_common::Error> for HwCryptoError {
from(e: kmr_common::Error) -> Self72     fn from(e: kmr_common::Error) -> Self {
73         HwCryptoError::KmError(e)
74     }
75 }
76 
77 impl From<CoseError> for HwCryptoError {
from(e: CoseError) -> Self78     fn from(e: CoseError) -> Self {
79         hwcrypto_err!(SERIALIZATION_ERROR, "Deserialization error: {}", e)
80     }
81 }
82 
83 impl From<TryReserveError> for HwCryptoError {
from(e: TryReserveError) -> Self84     fn from(e: TryReserveError) -> Self {
85         hwcrypto_err!(ALLOCATION_ERROR, "error allocating: {}", e)
86     }
87 }
88 
89 impl From<VolatileMemoryError> for HwCryptoError {
from(e: VolatileMemoryError) -> Self90     fn from(e: VolatileMemoryError) -> Self {
91         hwcrypto_err!(BAD_PARAMETER, "memory buffer slice error: {}", e)
92     }
93 }
94 
95 impl From<TryFromSliceError> for HwCryptoError {
from(e: TryFromSliceError) -> Self96     fn from(e: TryFromSliceError) -> Self {
97         hwcrypto_err!(ALLOCATION_ERROR, "error allocating from slice: {}", e)
98     }
99 }
100 
101 impl From<HwCryptoError> for binder::Status {
from(e: HwCryptoError) -> Self102     fn from(e: HwCryptoError) -> Self {
103         match e {
104             HwCryptoError::KmError(e) => {
105                 let msg = CString::new(format!("KM error {:?}", e).as_str()).unwrap();
106                 binder::Status::new_service_specific_error(HalErrorCode::GENERIC_ERROR, Some(&msg))
107             }
108             HwCryptoError::HalError { code, file, line, message } => {
109                 let msg = CString::new(
110                     format!("HWCrypto error on {}:{}: {}", file, line, message).as_str(),
111                 )
112                 .unwrap();
113                 binder::Status::new_service_specific_error(code, Some(&msg))
114             }
115             HwCryptoError::CborError(e) => {
116                 let msg =
117                     CString::new(format!("CBOR serialization error {:?}", e).as_str()).unwrap();
118                 binder::Status::new_service_specific_error(
119                     HalErrorCode::SERIALIZATION_ERROR,
120                     Some(&msg),
121                 )
122             }
123         }
124     }
125 }
126 
127 impl<T> From<PoisonError<T>> for HwCryptoError {
from(_: PoisonError<T>) -> Self128     fn from(_: PoisonError<T>) -> Self {
129         hwcrypto_err!(
130             GENERIC_ERROR,
131             "found PoisonError which shouldn't happen, we are single threaded"
132         )
133     }
134 }
135