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("Duplicate shard index {index}")]
49 DuplicateShardIndex { index: usize },
50 #[error("Other error")]
51 Other,
52}
53
54#[derive(Clone, Copy, Debug, thiserror::Error, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
55pub enum KeycardIdentifyError {
56 #[error("Invalid data")]
57 InvalidData,
58 #[error("Different device ID")]
59 DifferentDeviceId,
60 #[error("Different seed fingerprint")]
61 DifferentSeedFingerprint,
62 #[error("Unauthenticated shard")]
63 HmacMismatch,
64 #[error("Existing shard")]
65 ExistingShard,
66}
67
68impl From<xous::Error> for KeycardError {
69 fn from(value: xous::Error) -> Self { KeycardError::Xous(value.to_usize()) }
70}
71
72impl From<security::AccessDenied> for KeycardError {
73 fn from(_: security::AccessDenied) -> Self { KeycardError::Security(0) }
74}
75
76impl From<security::GetDeviceIdError> for KeycardError {
77 fn from(_: security::GetDeviceIdError) -> Self { KeycardError::Security(1) }
78}
79
80impl From<crypto::error::ShamirError> for KeycardError {
81 fn from(value: crypto::error::ShamirError) -> Self { Self::Shamir(value) }
82}
83
84impl From<crypto::error::CryptoError> for KeycardError {
85 fn from(value: crypto::error::CryptoError) -> Self { Self::Crypto(value) }
86}
87
88impl From<nfc::error::NfcError> for KeycardError {
89 fn from(value: nfc::error::NfcError) -> Self { Self::Nfc(value) }
90}
91
92impl AsScalar<3> for KeycardError {
93 fn as_scalar(&self) -> [u32; 3] {
94 match self {
95 KeycardError::Xous(e) => [1, *e as u32, 0],
96 KeycardError::Security(e) => [2, *e as u32, 0],
97 KeycardError::Shamir(e) => [3, AsScalar::<1>::as_scalar(e)[0], 0],
98 KeycardError::Crypto(e) => [4, AsScalar::<1>::as_scalar(e)[0], 0],
99 KeycardError::Nfc(e) => [5, AsScalar::<1>::as_scalar(e)[0], 0],
100 KeycardError::Ndef => [6, 0, 0],
101 KeycardError::NoShardLeft => [7, 0, 0],
102 KeycardError::NotMagicBackupShard => [8, 0, 0],
103 KeycardError::InvalidData => [9, 0, 0],
104 KeycardError::DifferentDeviceId => [10, 0, 0],
105 KeycardError::DifferentSeedFingerprint => [11, 0, 0],
106 KeycardError::SeedMissing => [12, 0, 0],
107 KeycardError::NotEnoughShards => [13, 0, 0],
108 KeycardError::HmacMismatch => [14, 0, 0],
109 KeycardError::BlankShard => [15, 0, 0],
110 KeycardError::BlankTag => [16, 0, 0],
111 KeycardError::InvalidScheme => [17, 0, 0],
112 KeycardError::SchemeMismatch => [18, 0, 0],
113 KeycardError::TimestampMismatch { expected, found } => [19, *expected, *found],
114 KeycardError::DuplicateShardIndex { index } => [20, *index as u32, 0],
115 KeycardError::Other => [0, 0, 0],
116 }
117 }
118}
119
120impl FromScalar<3> for KeycardError {
121 fn from_scalar(value: [u32; 3]) -> Self {
122 match value[0] {
123 1 => KeycardError::Xous(value[1] as usize),
124 2 => KeycardError::Security(value[1] as usize),
125 3 => KeycardError::Shamir(crypto::error::ShamirError::from_scalar([value[1]])),
126 4 => KeycardError::Crypto(crypto::error::CryptoError::from_scalar([value[1]])),
127 5 => KeycardError::Nfc(nfc::error::NfcError::from_scalar([value[1]])),
128 6 => KeycardError::Ndef,
129 7 => KeycardError::NoShardLeft,
130 8 => KeycardError::NotMagicBackupShard,
131 9 => KeycardError::InvalidData,
132 10 => KeycardError::DifferentDeviceId,
133 11 => KeycardError::DifferentSeedFingerprint,
134 12 => KeycardError::SeedMissing,
135 13 => KeycardError::NotEnoughShards,
136 14 => KeycardError::HmacMismatch,
137 15 => KeycardError::BlankShard,
138 16 => KeycardError::BlankTag,
139 17 => KeycardError::InvalidScheme,
140 18 => KeycardError::SchemeMismatch,
141 19 => KeycardError::TimestampMismatch { expected: value[1], found: value[2] },
142 20 => KeycardError::DuplicateShardIndex { index: value[1] as usize },
143 _ => KeycardError::Other,
144 }
145 }
146}
147
148impl From<usize> for KeycardError {
149 fn from(value: usize) -> Self { Self::from_scalar([value as u32, 0, 0]) }
150}
151
152impl From<KeycardError> for usize {
153 fn from(value: KeycardError) -> Self { server::AsScalar::<3>::as_scalar(&value)[0] as usize }
154}