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::aidl::android::hardware::security::see::hwcrypto::types::HalErrorCode;
21 use android_hardware_security_see::binder;
22 use core::array::TryFromSliceError;
23 use coset::CoseError;
24 use tipc::TipcError;
25 
26 /// Macro used to create a `HwCryptoError::HalError` by providing the AIDL `HalErrorCode` and a
27 /// message: `hwcrypto_err!(UNSUPPORTED, "unsupported operation")`
28 #[macro_export]
29 macro_rules! hwcrypto_err {
30     { $error_code:ident, $($arg:tt)+ } => {
31         $crate::err::HwCryptoError::HalError {
32                 code: $crate::err::HalErrorCode::$error_code,
33                 file: std::file!(),
34                 line: std::line!(),
35                 message: alloc::format!("{}",std::format_args!($($arg)+)),
36         }
37     };
38 }
39 
40 /// Base Error type for HwCrypto library.
41 #[derive(Debug)]
42 pub enum HwCryptoError {
43     /// HwCrypto library native error
44     HalError { code: i32, file: &'static str, line: u32, message: String },
45     /// Error generated by a keymint library
46     KmError(kmr_common::Error),
47     /// Error when (de)serializing CBOR objects
48     CborError(kmr_wire::CborError),
49 }
50 
51 impl From<kmr_wire::CborError> for HwCryptoError {
from(e: kmr_wire::CborError) -> Self52     fn from(e: kmr_wire::CborError) -> Self {
53         HwCryptoError::CborError(e)
54     }
55 }
56 
57 impl From<TipcError> for HwCryptoError {
from(e: TipcError) -> Self58     fn from(e: TipcError) -> Self {
59         hwcrypto_err!(GENERIC_ERROR, "tipc communication error: {:?}", e)
60     }
61 }
62 
63 impl From<kmr_common::Error> for HwCryptoError {
from(e: kmr_common::Error) -> Self64     fn from(e: kmr_common::Error) -> Self {
65         HwCryptoError::KmError(e)
66     }
67 }
68 
69 impl From<CoseError> for HwCryptoError {
from(e: CoseError) -> Self70     fn from(e: CoseError) -> Self {
71         hwcrypto_err!(SERIALIZATION_ERROR, "Deserialization error: {}", e)
72     }
73 }
74 
75 impl From<TryReserveError> for HwCryptoError {
from(e: TryReserveError) -> Self76     fn from(e: TryReserveError) -> Self {
77         hwcrypto_err!(ALLOCATION_ERROR, "error allocating: {}", e)
78     }
79 }
80 
81 impl From<TryFromSliceError> for HwCryptoError {
from(e: TryFromSliceError) -> Self82     fn from(e: TryFromSliceError) -> Self {
83         hwcrypto_err!(ALLOCATION_ERROR, "error allocating from slice: {}", e)
84     }
85 }
86 
87 impl From<HwCryptoError> for binder::Status {
from(e: HwCryptoError) -> Self88     fn from(e: HwCryptoError) -> Self {
89         match e {
90             HwCryptoError::KmError(e) => {
91                 let msg = CString::new(format!("KM error {:?}", e).as_str()).unwrap();
92                 binder::Status::new_service_specific_error(HalErrorCode::GENERIC_ERROR, Some(&msg))
93             }
94             HwCryptoError::HalError { code, file, line, message } => {
95                 let msg = CString::new(
96                     format!("HWCrypto error on {}:{}: {}", file, line, message).as_str(),
97                 )
98                 .unwrap();
99                 binder::Status::new_service_specific_error(code, Some(&msg))
100             }
101             HwCryptoError::CborError(e) => {
102                 let msg =
103                     CString::new(format!("CBOR serialization error {:?}", e).as_str()).unwrap();
104                 binder::Status::new_service_specific_error(
105                     HalErrorCode::SERIALIZATION_ERROR,
106                     Some(&msg),
107                 )
108             }
109         }
110     }
111 }
112