1use server::{AsScalar, FromScalar};
5
6#[derive(
7 Debug, Clone, Copy, thiserror::Error, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize, PartialEq,
8)]
9pub enum KeycardError {
10 #[error("OS error: {:?}", xous::Error::from_usize(*.0))]
11 Xous(usize),
12 #[error("Security error: AccessDenied")]
13 Security(usize),
14 #[error("Shamir error: {0:?}")]
15 Shamir(crypto::error::ShamirError),
16 #[error("Crypto error: {0:?}")]
17 Crypto(crypto::error::CryptoError),
18 #[error("Nfc error: {0:?}")]
19 Nfc(nfc::error::NfcError),
20 #[error("Ndef error")]
21 Ndef,
22 #[error("No more shards left")]
23 NoShardLeft,
24 #[error("Not a magic backup shard")]
25 NotMagicBackupShard,
26 #[error("Invalid data")]
27 InvalidData,
28 #[error("Different hardware UID")]
29 DifferentDeviceId,
30 #[error("Seed missing")]
31 SeedMissing,
32 #[error("Different seed fingerprint")]
33 DifferentSeedFingerprint,
34 #[error("Not enough shards")]
35 NotEnoughShards,
36 #[error("HMAC mismatch")]
37 HmacMismatch,
38 #[error("Blank shard")]
39 BlankShard,
40 #[error("Blank tag")]
41 BlankTag,
42 #[error("Invalid shamir scheme")]
43 InvalidScheme,
44 #[error("Shard scheme doesn't match active scheme")]
45 SchemeMismatch,
46 #[error("Shard timestamp {found} doesn't match expected {expected}")]
47 TimestampMismatch { expected: u32, found: u32 },
48 #[error("Other error")]
49 Other,
50}
51
52#[derive(Clone, Copy, Debug, thiserror::Error, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
53pub enum KeycardIdentifyError {
54 #[error("Invalid data")]
55 InvalidData,
56 #[error("Different device ID")]
57 DifferentDeviceId,
58 #[error("Different seed fingerprint")]
59 DifferentSeedFingerprint,
60 #[error("Unauthenticated shard")]
61 HmacMismatch,
62 #[error("Existing shard")]
63 ExistingShard,
64}
65
66impl From<xous::Error> for KeycardError {
67 fn from(value: xous::Error) -> Self { KeycardError::Xous(value.to_usize()) }
68}
69
70impl From<security::AccessDenied> for KeycardError {
71 fn from(_: security::AccessDenied) -> Self { KeycardError::Security(0) }
72}
73
74impl From<security::GetDeviceIdError> for KeycardError {
75 fn from(_: security::GetDeviceIdError) -> Self { KeycardError::Security(1) }
76}
77
78impl From<crypto::error::ShamirError> for KeycardError {
79 fn from(value: crypto::error::ShamirError) -> Self { Self::Shamir(value) }
80}
81
82impl From<crypto::error::CryptoError> for KeycardError {
83 fn from(value: crypto::error::CryptoError) -> Self { Self::Crypto(value) }
84}
85
86impl From<nfc::error::NfcError> for KeycardError {
87 fn from(value: nfc::error::NfcError) -> Self { Self::Nfc(value) }
88}
89
90impl AsScalar<3> for KeycardError {
91 fn as_scalar(&self) -> [u32; 3] {
92 match self {
93 KeycardError::Xous(e) => [1, *e as u32, 0],
94 KeycardError::Security(e) => [2, *e as u32, 0],
95 KeycardError::Shamir(e) => [3, AsScalar::<1>::as_scalar(e)[0], 0],
96 KeycardError::Crypto(e) => [4, AsScalar::<1>::as_scalar(e)[0], 0],
97 KeycardError::Nfc(e) => [5, AsScalar::<1>::as_scalar(e)[0], 0],
98 KeycardError::Ndef => [6, 0, 0],
99 KeycardError::NoShardLeft => [7, 0, 0],
100 KeycardError::NotMagicBackupShard => [8, 0, 0],
101 KeycardError::InvalidData => [9, 0, 0],
102 KeycardError::DifferentDeviceId => [10, 0, 0],
103 KeycardError::DifferentSeedFingerprint => [11, 0, 0],
104 KeycardError::SeedMissing => [12, 0, 0],
105 KeycardError::NotEnoughShards => [13, 0, 0],
106 KeycardError::HmacMismatch => [14, 0, 0],
107 KeycardError::BlankShard => [15, 0, 0],
108 KeycardError::BlankTag => [16, 0, 0],
109 KeycardError::InvalidScheme => [17, 0, 0],
110 KeycardError::SchemeMismatch => [18, 0, 0],
111 KeycardError::TimestampMismatch { expected, found } => [19, *expected, *found],
112 KeycardError::Other => [0, 0, 0],
113 }
114 }
115}
116
117impl FromScalar<3> for KeycardError {
118 fn from_scalar(value: [u32; 3]) -> Self {
119 match value[0] {
120 1 => KeycardError::Xous(value[1] as usize),
121 2 => KeycardError::Security(value[1] as usize),
122 3 => KeycardError::Shamir(crypto::error::ShamirError::from_scalar([value[1]])),
123 4 => KeycardError::Crypto(crypto::error::CryptoError::from_scalar([value[1]])),
124 5 => KeycardError::Nfc(nfc::error::NfcError::from_scalar([value[1]])),
125 6 => KeycardError::Ndef,
126 7 => KeycardError::NoShardLeft,
127 8 => KeycardError::NotMagicBackupShard,
128 9 => KeycardError::InvalidData,
129 10 => KeycardError::DifferentDeviceId,
130 11 => KeycardError::DifferentSeedFingerprint,
131 12 => KeycardError::SeedMissing,
132 13 => KeycardError::NotEnoughShards,
133 14 => KeycardError::HmacMismatch,
134 15 => KeycardError::BlankShard,
135 16 => KeycardError::BlankTag,
136 17 => KeycardError::InvalidScheme,
137 18 => KeycardError::SchemeMismatch,
138 19 => KeycardError::TimestampMismatch { expected: value[1], found: value[2] },
139 _ => KeycardError::Other,
140 }
141 }
142}
143
144impl From<usize> for KeycardError {
145 fn from(value: usize) -> Self { Self::from_scalar([value as u32, 0, 0]) }
146}
147
148impl From<KeycardError> for usize {
149 fn from(value: KeycardError) -> Self { server::AsScalar::<3>::as_scalar(&value)[0] as usize }
150}