blob: f8a4380e68fdf63a2a636df4ebe651874eb81c2d [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
use optee_teec_sys as raw;
use std::fmt;
/// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)
/// type for TEE operations.
///
/// # Examples
///
/// ``` no_run
/// fn main() -> optee_teec::Result<()> {
/// let mut ctx = Context::new()?;
/// }
/// ````
pub type Result<T> = std::result::Result<T, Error>;
/// The error type for TEE operations of [`Context`] and [`Session`].
///
/// [`Context`]: struct.Context.html
/// [`Session`]: struct.Session.html
pub struct Error {
code: u32,
}
/// A list specifying general categories of TEE client error and its
/// corresponding code in OP-TEE client library.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(u32)]
pub enum ErrorKind {
/// Non-specific cause.
Generic = 0xFFFF0000,
/// Access privileges are not sufficient.
AccessDenied = 0xFFFF0001,
/// The operation was canceled.
Cancel = 0xFFFF0002,
/// Concurrent accesses caused conflict.
AccessConflict = 0xFFFF0003,
/// Too much data for the requested operation was passed.
ExcessData = 0xFFFF0004,
/// Input data was of invalid format.
BadFormat = 0xFFFF0005,
/// Input parameters were invalid.
BadParameters = 0xFFFF0006,
/// Operation is not valid in the current state.
BadState = 0xFFFF0007,
/// The requested data item is not found.
ItemNotFound = 0xFFFF0008,
/// The requested operation should exist but is not yet implemented.
NotImplemented = 0xFFFF0009,
/// The requested operation is valid but is not supported in this implementation.
NotSupported = 0xFFFF000A,
/// Expected data was missing.
NoData = 0xFFFF000B,
/// System ran out of resources.
OutOfMemory = 0xFFFF000C,
/// The system is busy working on something else.
Busy = 0xFFFF000D,
/// Communication with a remote party failed.
Communication = 0xFFFF000E,
/// A security fault was detected.
Security = 0xFFFF000F,
/// The supplied buffer is too short for the generated output.
ShortBuffer = 0xFFFF0010,
/// Implementation defined error code.
ExternalCancel = 0xFFFF0011,
/// Implementation defined error code: trusted Application has panicked during the operation.
TargetDead = 0xFFFF3024,
/// Unknown error.
Unknown,
}
impl ErrorKind {
pub(crate) fn as_str(&self) -> &'static str {
match *self {
ErrorKind::Generic => "Non-specific cause.",
ErrorKind::AccessDenied => "Access privileges are not sufficient.",
ErrorKind::Cancel => "The operation was canceled.",
ErrorKind::AccessConflict => "Concurrent accesses caused conflict.",
ErrorKind::ExcessData => "Too much data for the requested operation was passed.",
ErrorKind::BadFormat => "Input data was of invalid format.",
ErrorKind::BadParameters => "Input parameters were invalid.",
ErrorKind::BadState => "Operation is not valid in the current state.",
ErrorKind::ItemNotFound => "The requested data item is not found.",
ErrorKind::NotImplemented => {
"The requested operation should exist but is not yet implemented."
}
ErrorKind::NotSupported => {
"The requested operation is valid but is not supported in this implementation."
}
ErrorKind::NoData => "Expected data was missing.",
ErrorKind::OutOfMemory => "System ran out of resources.",
ErrorKind::Busy => "The system is busy working on something else.",
ErrorKind::Communication => "Communication with a remote party failed.",
ErrorKind::Security => "A security fault was detected.",
ErrorKind::ShortBuffer => "The supplied buffer is too short for the generated output.",
ErrorKind::ExternalCancel => "Undocumented.",
ErrorKind::TargetDead => "Trusted Application has panicked during the operation.",
ErrorKind::Unknown => "Unknown error.",
}
}
}
impl Error {
pub fn new(kind: ErrorKind) -> Error {
Error { code: kind as u32 }
}
/// Creates a new instance of an `Error` from a particular TEE error code.
///
/// # Examples
///
/// ``` no_run
/// use optee_teec;
///
/// let error = optee_teec::Error::from_raw_error(0xFFFF000F);
/// assert_eq!(error.kind(), optee_teec::ErrorKind::Security);
/// ```
pub fn from_raw_error(code: u32) -> Error {
Error { code }
}
/// Returns the corresponding `ErrorKind` for this error.
///
/// # Examples
///
/// ``` no_run
/// use optee_teec;
///
/// let error = optee_teec::Error::new(optee_teec::ErrorKind::Security);
/// ```
pub fn kind(&self) -> ErrorKind {
match self.code {
raw::TEEC_ERROR_GENERIC => ErrorKind::Generic,
raw::TEEC_ERROR_ACCESS_DENIED => ErrorKind::AccessDenied,
raw::TEEC_ERROR_CANCEL => ErrorKind::Cancel,
raw::TEEC_ERROR_ACCESS_CONFLICT => ErrorKind::AccessConflict,
raw::TEEC_ERROR_EXCESS_DATA => ErrorKind::ExcessData,
raw::TEEC_ERROR_BAD_FORMAT => ErrorKind::BadFormat,
raw::TEEC_ERROR_BAD_PARAMETERS => ErrorKind::BadParameters,
raw::TEEC_ERROR_BAD_STATE => ErrorKind::BadState,
raw::TEEC_ERROR_ITEM_NOT_FOUND => ErrorKind::ItemNotFound,
raw::TEEC_ERROR_NOT_IMPLEMENTED => ErrorKind::NotImplemented,
raw::TEEC_ERROR_NOT_SUPPORTED => ErrorKind::NotSupported,
raw::TEEC_ERROR_NO_DATA => ErrorKind::NoData,
raw::TEEC_ERROR_OUT_OF_MEMORY => ErrorKind::OutOfMemory,
raw::TEEC_ERROR_BUSY => ErrorKind::Busy,
raw::TEEC_ERROR_COMMUNICATION => ErrorKind::Communication,
raw::TEEC_ERROR_SECURITY => ErrorKind::Security,
raw::TEEC_ERROR_SHORT_BUFFER => ErrorKind::ShortBuffer,
raw::TEEC_ERROR_EXTERNAL_CANCEL => ErrorKind::ExternalCancel,
raw::TEEC_ERROR_TARGET_DEAD => ErrorKind::TargetDead,
_ => ErrorKind::Unknown,
}
}
/// Returns raw code of this error.
pub fn raw_code(&self) -> u32 {
self.code
}
/// Returns corresponding error message of this error.
pub fn message(&self) -> &str {
self.kind().as_str()
}
}
impl fmt::Debug for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{} (error code 0x{:x})", self.message(), self.code)
}
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{} (error code 0x{:x})", self.message(), self.code)
}
}
impl std::error::Error for Error {
fn description(&self) -> &str {
self.message()
}
}
impl From<ErrorKind> for Error {
#[inline]
fn from(kind: ErrorKind) -> Error {
Error { code: kind as u32 }
}
}