fido/
error.rs

1// SPDX-FileCopyrightText: 2025 Foundation Devices, Inc. <hello@foundation.xyz>
2// SPDX-License-Identifier: GPL-3.0-or-later
3
4use server::{AsScalar, FromScalar};
5
6#[derive(Debug, Clone, Copy, thiserror::Error, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
7pub enum FidoError {
8    #[error("OS error: {:?}", xous::Error::from_usize(*.0))]
9    Xous(usize),
10    #[error("Crypto error: {0:?}")]
11    Crypto(crypto::error::CryptoError),
12    #[error("Security Access denied")]
13    AccessDenied,
14    #[error("FS error: {0:?}")]
15    Fs(fs::Error),
16    #[error("ECDSA error")]
17    Ecdsa,
18    #[error("Invalid index")]
19    InvalidIndex,
20    #[error("Security Key not selected")]
21    UnselectedKey,
22    #[error("Key not registered in selected Security Key")]
23    UnRegisteredKey,
24    #[error("IO error")]
25    Io,
26    #[error("Label is empty")]
27    EmptyLabel,
28    #[error("Label already in use")]
29    DuplicateLabel,
30    #[error("Other Fido error")]
31    Other,
32}
33
34impl From<xous::Error> for FidoError {
35    fn from(value: xous::Error) -> Self { FidoError::Xous(value.to_usize()) }
36}
37
38impl From<crypto::error::CryptoError> for FidoError {
39    fn from(value: crypto::error::CryptoError) -> Self { Self::Crypto(value) }
40}
41
42impl From<security::AccessDenied> for FidoError {
43    fn from(_: security::AccessDenied) -> Self { Self::AccessDenied }
44}
45
46impl From<fs::Error> for FidoError {
47    fn from(value: fs::Error) -> Self { Self::Fs(value) }
48}
49
50impl From<std::io::Error> for FidoError {
51    fn from(_value: std::io::Error) -> Self { Self::Io }
52}
53
54impl AsScalar<3> for FidoError {
55    fn as_scalar(&self) -> [u32; 3] {
56        match self {
57            FidoError::Xous(e) => [1, *e as u32, 0],
58            FidoError::Crypto(e) => [3, AsScalar::<1>::as_scalar(e)[0], 0],
59            FidoError::AccessDenied => [4, 0, 0],
60            FidoError::Fs(e) => [5, *e as u32, 0],
61            FidoError::Ecdsa => [6, 0, 0],
62            FidoError::InvalidIndex => [7, 0, 0],
63            FidoError::UnselectedKey => [8, 0, 0],
64            FidoError::UnRegisteredKey => [9, 0, 0],
65            FidoError::Io => [10, 0, 0],
66            FidoError::EmptyLabel => [12, 0, 0],
67            FidoError::DuplicateLabel => [13, 0, 0],
68            FidoError::Other => [11, 0, 0],
69        }
70    }
71}
72
73impl FromScalar<3> for FidoError {
74    fn from_scalar(value: [u32; 3]) -> Self {
75        match value[0] {
76            1 => FidoError::Xous(value[1] as usize),
77            3 => FidoError::Crypto(crypto::error::CryptoError::from_scalar([value[1]])),
78            4 => FidoError::AccessDenied,
79            5 => FidoError::Fs((value[1] as usize).into()),
80            6 => FidoError::Ecdsa,
81            7 => FidoError::InvalidIndex,
82            8 => FidoError::UnselectedKey,
83            9 => FidoError::UnRegisteredKey,
84            10 => FidoError::Io,
85            12 => FidoError::EmptyLabel,
86            13 => FidoError::DuplicateLabel,
87            _ => FidoError::Other,
88        }
89    }
90}
91
92impl From<usize> for FidoError {
93    fn from(value: usize) -> Self { Self::from_scalar([value as u32, 0, 0]) }
94}
95
96impl From<FidoError> for usize {
97    fn from(value: FidoError) -> Self { server::AsScalar::<3>::as_scalar(&value)[0] as usize }
98}