/* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //! HwCrypto error handling code and related structures use alloc::{collections::TryReserveError, ffi::CString}; pub use android_hardware_security_see_hwcrypto::aidl::android::hardware::security::see::hwcrypto::types::HalErrorCode; use android_hardware_security_see_hwcrypto::binder; use core::array::TryFromSliceError; use coset::CoseError; use std::sync::PoisonError; use tipc::TipcError; use vm_memory::VolatileMemoryError; /// Macro used to create a `HwCryptoError::HalError` by providing the AIDL `HalErrorCode` and a /// message: `hwcrypto_err!(UNSUPPORTED, "unsupported operation")` #[macro_export] macro_rules! hwcrypto_err { { $error_code:ident, $($arg:tt)+ } => { $crate::err::HwCryptoError::HalError { code: $crate::err::HalErrorCode::$error_code, file: std::file!(), line: std::line!(), message: alloc::format!("{}",std::format_args!($($arg)+)), } }; } /// Base Error type for HwCrypto library. #[derive(Debug)] pub enum HwCryptoError { /// HwCrypto library native error HalError { code: i32, file: &'static str, line: u32, message: String }, /// Error generated by a keymint library KmError(kmr_common::Error), /// Error when (de)serializing CBOR objects CborError(kmr_wire::CborError), } impl HwCryptoError { pub fn matches_hal_error_code(&self, error_code: i32) -> bool { core::matches!(self, HwCryptoError::HalError { code, .. } if *code == error_code) } } impl From for HwCryptoError { fn from(e: kmr_wire::CborError) -> Self { HwCryptoError::CborError(e) } } impl From for HwCryptoError { fn from(e: TipcError) -> Self { hwcrypto_err!(GENERIC_ERROR, "tipc communication error: {:?}", e) } } impl From for HwCryptoError { fn from(e: kmr_common::Error) -> Self { HwCryptoError::KmError(e) } } impl From for HwCryptoError { fn from(e: CoseError) -> Self { hwcrypto_err!(SERIALIZATION_ERROR, "Deserialization error: {}", e) } } impl From for HwCryptoError { fn from(e: TryReserveError) -> Self { hwcrypto_err!(ALLOCATION_ERROR, "error allocating: {}", e) } } impl From for HwCryptoError { fn from(e: VolatileMemoryError) -> Self { hwcrypto_err!(BAD_PARAMETER, "memory buffer slice error: {}", e) } } impl From for HwCryptoError { fn from(e: TryFromSliceError) -> Self { hwcrypto_err!(ALLOCATION_ERROR, "error allocating from slice: {}", e) } } impl From for binder::Status { fn from(e: HwCryptoError) -> Self { match e { HwCryptoError::KmError(e) => { let msg = CString::new(format!("KM error {:?}", e).as_str()).unwrap(); binder::Status::new_service_specific_error(HalErrorCode::GENERIC_ERROR, Some(&msg)) } HwCryptoError::HalError { code, file, line, message } => { let msg = CString::new( format!("HWCrypto error on {}:{}: {}", file, line, message).as_str(), ) .unwrap(); binder::Status::new_service_specific_error(code, Some(&msg)) } HwCryptoError::CborError(e) => { let msg = CString::new(format!("CBOR serialization error {:?}", e).as_str()).unwrap(); binder::Status::new_service_specific_error( HalErrorCode::SERIALIZATION_ERROR, Some(&msg), ) } } } } impl From> for HwCryptoError { fn from(_: PoisonError) -> Self { hwcrypto_err!( GENERIC_ERROR, "found PoisonError which shouldn't happen, we are single threaded" ) } }