use std::error;
use std::fmt;
use crate::pkcs11::*;
use asn1;
use ossl;
use serde_json;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
pub struct Error {
kind: ErrorKind,
origin: Option<Box<dyn error::Error>>,
errmsg: Option<String>,
reqsize: usize,
ckrv: CK_RV,
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[non_exhaustive]
pub enum ErrorKind {
CkError,
AttributeNotFound,
BufferTooSmall,
Nested,
}
macro_rules! trace_err {
($err:expr) => {{
let e = $err;
#[cfg(feature = "log")]
if e.ckrv != CKR_OK {
use log::error;
error!("{}", &e);
}
e
}};
}
impl Error {
pub fn ck_rv(ckrv: CK_RV) -> Error {
trace_err!(Error {
kind: ErrorKind::CkError,
origin: None,
errmsg: None,
reqsize: 0,
ckrv: ckrv,
})
}
pub fn ck_rv_from_error<E>(ckrv: CK_RV, error: E) -> Error
where
E: Into<Box<dyn error::Error>> + std::fmt::Display,
{
trace_err!(Error {
kind: ErrorKind::CkError,
origin: Some(error.into()),
errmsg: None,
reqsize: 0,
ckrv: ckrv,
})
}
pub fn ck_rv_with_errmsg(ckrv: CK_RV, errmsg: String) -> Error {
trace_err!(Error {
kind: ErrorKind::CkError,
origin: None,
errmsg: Some(errmsg),
reqsize: 0,
ckrv: ckrv,
})
}
pub fn not_found(errmsg: String) -> Error {
trace_err!(Error {
kind: ErrorKind::AttributeNotFound,
origin: None,
errmsg: Some(errmsg),
reqsize: 0,
ckrv: CKR_GENERAL_ERROR,
})
}
pub fn other_error<E>(error: E) -> Error
where
E: Into<Box<dyn error::Error>> + std::fmt::Display,
{
trace_err!(Error {
kind: ErrorKind::Nested,
origin: Some(error.into()),
errmsg: None,
reqsize: 0,
ckrv: CKR_GENERAL_ERROR,
})
}
pub fn buf_too_small(reqsize: usize) -> Error {
trace_err!(Error {
kind: ErrorKind::BufferTooSmall,
origin: None,
errmsg: None,
reqsize: reqsize,
ckrv: CKR_BUFFER_TOO_SMALL,
})
}
pub fn kind(&self) -> ErrorKind {
self.kind
}
pub fn attr_not_found(&self) -> bool {
return self.kind == ErrorKind::AttributeNotFound;
}
pub fn rv(&self) -> CK_RV {
self.ckrv
}
pub fn reqsize(&self) -> usize {
self.reqsize
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let ret = match self.kind {
ErrorKind::CkError => write!(f, "Generic CK error"),
ErrorKind::AttributeNotFound => write!(f, "Attribute not found"),
ErrorKind::BufferTooSmall => write!(f, "Buffer too small"),
ErrorKind::Nested => write!(f, "Nested error"),
};
if ret.is_err() {
return ret;
}
let ret = write!(f, ", {}", ckrv_to_string(self.ckrv));
if ret.is_err() {
return ret;
}
match &self.origin {
Some(e) => {
let ret = write!(f, " - Error from: {{ {} }}", e);
if ret.is_err() {
return ret;
}
}
None => (),
}
match &self.errmsg {
Some(e) => {
let ret = write!(f, " - With message: {}", e);
if ret.is_err() {
return ret;
}
}
None => (),
}
if self.reqsize != 0 {
let ret = write!(f, " - With reqsize: {}", self.reqsize);
if ret.is_err() {
return ret;
}
}
Ok(())
}
}
impl std::error::Error for Error {}
impl From<std::io::Error> for Error {
fn from(error: std::io::Error) -> Error {
Error::other_error(error)
}
}
impl From<serde_json::Error> for Error {
fn from(error: serde_json::Error) -> Error {
Error::other_error(error)
}
}
impl From<std::num::TryFromIntError> for Error {
fn from(error: std::num::TryFromIntError) -> Error {
Error::other_error(error)
}
}
impl From<std::convert::Infallible> for Error {
fn from(error: std::convert::Infallible) -> Error {
Error::other_error(error)
}
}
impl From<CK_RV> for Error {
fn from(error: CK_RV) -> Error {
Error::ck_rv(error)
}
}
impl From<asn1::ParseError> for Error {
fn from(error: asn1::ParseError) -> Error {
Error::other_error(error)
}
}
impl From<std::num::ParseIntError> for Error {
fn from(error: std::num::ParseIntError) -> Error {
Error::other_error(error)
}
}
impl From<asn1::WriteError> for Error {
fn from(error: asn1::WriteError) -> Error {
Error::other_error(error)
}
}
impl From<Vec<u8>> for Error {
fn from(v: Vec<u8>) -> Error {
Error::buf_too_small(v.len())
}
}
use std::array::TryFromSliceError;
impl From<TryFromSliceError> for Error {
fn from(error: TryFromSliceError) -> Error {
Error::other_error(error)
}
}
impl From<ossl::Error> for Error {
fn from(error: ossl::Error) -> Error {
match error.kind() {
ossl::ErrorKind::KeyError => Error::ck_rv(CKR_KEY_INDIGESTIBLE),
ossl::ErrorKind::WrapperError => Error::ck_rv(CKR_GENERAL_ERROR),
_ => Error::ck_rv(CKR_DEVICE_ERROR),
}
}
}
#[allow(unused_macros)]
macro_rules! some_or_err {
($action:expr) => {
if let Some(ref x) = $action {
x
} else {
return Err(CKR_GENERAL_ERROR)?;
}
};
(mut $action:expr) => {
if let Some(ref mut x) = $action {
x
} else {
return Err(CKR_GENERAL_ERROR)?;
}
};
}
#[allow(unused_imports)]
pub(crate) use some_or_err;
#[allow(dead_code)]
pub fn general_error<E>(error: E) -> Error
where
E: Into<Box<dyn error::Error>> + std::fmt::Display,
{
Error::ck_rv_from_error(CKR_GENERAL_ERROR, error)
}
#[allow(dead_code)]
pub fn device_error<E>(error: E) -> Error
where
E: Into<Box<dyn error::Error>> + std::fmt::Display,
{
Error::ck_rv_from_error(CKR_DEVICE_ERROR, error)
}
pub fn arg_bad<E>(error: E) -> Error
where
E: Into<Box<dyn error::Error>> + std::fmt::Display,
{
Error::ck_rv_from_error(CKR_ARGUMENTS_BAD, error)
}
macro_rules! map_err {
($map:expr, $err:tt) => {{
use crate::error::Error;
$map.map_err(|e| Error::ck_rv_from_error($err, e))
}};
}
pub(crate) use map_err;