1use log::error;
9use zeroize::Zeroize;
10
11#[cfg(feature = "std")]
12use std::fmt;
13
14pub type Result<T> = core::result::Result<T, Error>;
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq, Zeroize)]
19pub enum Status {
20 Success,
22 Error(Error),
24}
25
26impl Status {
27 pub fn to_result(self) -> Result<()> {
41 match self {
42 Status::Success => Ok(()),
43 Status::Error(error) => Err(error),
44 }
45 }
46}
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq, Zeroize)]
50pub enum Error {
51 GenericError,
53 NotSupported,
55 NotPermitted,
57 BufferTooSmall,
59 AlreadyExists,
61 DoesNotExist,
63 BadState,
65 InvalidArgument,
67 InsufficientMemory,
69 InsufficientStorage,
71 CommunicationFailure,
73 StorageFailure,
75 DataCorrupt,
77 DataInvalid,
79 HardwareFailure,
81 CorruptionDetected,
83 InsufficientEntropy,
85 InvalidSignature,
87 InvalidPadding,
89 InsufficientData,
91 InvalidHandle,
93}
94
95#[cfg(feature = "std")]
96impl fmt::Display for Error {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 match self {
99 Error::GenericError => write!(
100 f,
101 "An error occurred that does not correspond to any defined failure cause"
102 ),
103 Error::NotSupported => write!(
104 f,
105 "The requested operation or a parameter is not supported by this implementation"
106 ),
107 Error::NotPermitted => write!(f, "The requested action is denied by a policy"),
108 Error::BufferTooSmall => write!(f, "An output buffer is too small"),
109 Error::AlreadyExists => write!(f, "Asking for an item that already exists"),
110 Error::DoesNotExist => write!(f, "Asking for an item that doesn't exist"),
111 Error::BadState => write!(
112 f,
113 "The requested action cannot be performed in the current state"
114 ),
115 Error::InvalidArgument => {
116 write!(f, "The parameters passed to the function are invalid")
117 }
118 Error::InsufficientMemory => write!(f, "There is not enough runtime memory"),
119 Error::InsufficientStorage => write!(f, "There is not enough persistent storage"),
120 Error::CommunicationFailure => write!(
121 f,
122 "There was a communication failure inside the implementation"
123 ),
124 Error::StorageFailure => write!(
125 f,
126 "There was a storage failure that may have led to data loss"
127 ),
128 Error::DataCorrupt => write!(f, "Stored data has been corrupted"),
129 Error::DataInvalid => write!(
130 f,
131 "Data read from storage is not valid for the implementation"
132 ),
133 Error::HardwareFailure => write!(f, "A hardware failure was detected"),
134 Error::CorruptionDetected => write!(f, "A tampering attempt was detected"),
135 Error::InsufficientEntropy => write!(
136 f,
137 "There is not enough entropy to generate random data needed for the requested action"
138 ),
139 Error::InvalidSignature => write!(
140 f,
141 "The signature, MAC or hash is incorrect"
142 ),
143 Error::InvalidPadding => write!(
144 f,
145 "The decrypted padding is incorrect"
146 ),
147 Error::InsufficientData => write!(
148 f,
149 "Insufficient data when attempting to read from a resource"
150 ),
151 Error::InvalidHandle => write!(
152 f,
153 "The key handle is not valid"
154 ),
155 }
156 }
157}
158
159#[cfg(feature = "std")]
160impl std::error::Error for Error {}
161
162impl From<Error> for Status {
163 fn from(error: Error) -> Self {
164 Status::Error(error)
165 }
166}
167
168impl From<psa_crypto_sys::psa_status_t> for Status {
169 fn from(status: psa_crypto_sys::psa_status_t) -> Self {
170 match status {
171 psa_crypto_sys::PSA_SUCCESS => Status::Success,
172 psa_crypto_sys::PSA_ERROR_GENERIC_ERROR => Error::GenericError.into(),
173 psa_crypto_sys::PSA_ERROR_NOT_SUPPORTED => Error::NotSupported.into(),
174 psa_crypto_sys::PSA_ERROR_NOT_PERMITTED => Error::NotPermitted.into(),
175 psa_crypto_sys::PSA_ERROR_BUFFER_TOO_SMALL => Error::BufferTooSmall.into(),
176 psa_crypto_sys::PSA_ERROR_ALREADY_EXISTS => Error::AlreadyExists.into(),
177 psa_crypto_sys::PSA_ERROR_DOES_NOT_EXIST => Error::DoesNotExist.into(),
178 psa_crypto_sys::PSA_ERROR_BAD_STATE => Error::BadState.into(),
179 psa_crypto_sys::PSA_ERROR_INVALID_ARGUMENT => Error::InvalidArgument.into(),
180 psa_crypto_sys::PSA_ERROR_INSUFFICIENT_MEMORY => Error::InsufficientMemory.into(),
181 psa_crypto_sys::PSA_ERROR_INSUFFICIENT_STORAGE => Error::InsufficientStorage.into(),
182 psa_crypto_sys::PSA_ERROR_COMMUNICATION_FAILURE => Error::CommunicationFailure.into(),
183 psa_crypto_sys::PSA_ERROR_STORAGE_FAILURE => Error::StorageFailure.into(),
184 psa_crypto_sys::PSA_ERROR_HARDWARE_FAILURE => Error::HardwareFailure.into(),
185 psa_crypto_sys::PSA_ERROR_INSUFFICIENT_ENTROPY => Error::InsufficientEntropy.into(),
186 psa_crypto_sys::PSA_ERROR_INVALID_SIGNATURE => Error::InvalidSignature.into(),
187 psa_crypto_sys::PSA_ERROR_INVALID_PADDING => Error::InvalidPadding.into(),
188 psa_crypto_sys::PSA_ERROR_INSUFFICIENT_DATA => Error::InsufficientData.into(),
189 psa_crypto_sys::PSA_ERROR_INVALID_HANDLE => Error::InvalidHandle.into(),
190 psa_crypto_sys::PSA_ERROR_CORRUPTION_DETECTED => Error::CorruptionDetected.into(),
191 psa_crypto_sys::PSA_ERROR_DATA_CORRUPT => Error::DataCorrupt.into(),
192 psa_crypto_sys::PSA_ERROR_DATA_INVALID => Error::DataInvalid.into(),
193 s => {
194 error!("{} not recognised as a valid PSA status.", s);
195 Status::Error(Error::GenericError)
196 }
197 }
198 }
199}
200
201impl From<Status> for psa_crypto_sys::psa_status_t {
202 fn from(status: Status) -> psa_crypto_sys::psa_status_t {
203 match status {
204 Status::Success => psa_crypto_sys::PSA_SUCCESS,
205 Status::Error(error) => error.into(),
206 }
207 }
208}
209
210impl From<Error> for psa_crypto_sys::psa_status_t {
211 fn from(error: Error) -> psa_crypto_sys::psa_status_t {
212 match error {
213 Error::GenericError => psa_crypto_sys::PSA_ERROR_GENERIC_ERROR,
214 Error::NotSupported => psa_crypto_sys::PSA_ERROR_NOT_SUPPORTED,
215 Error::NotPermitted => psa_crypto_sys::PSA_ERROR_NOT_PERMITTED,
216 Error::BufferTooSmall => psa_crypto_sys::PSA_ERROR_BUFFER_TOO_SMALL,
217 Error::AlreadyExists => psa_crypto_sys::PSA_ERROR_ALREADY_EXISTS,
218 Error::DoesNotExist => psa_crypto_sys::PSA_ERROR_DOES_NOT_EXIST,
219 Error::BadState => psa_crypto_sys::PSA_ERROR_BAD_STATE,
220 Error::InvalidArgument => psa_crypto_sys::PSA_ERROR_INVALID_ARGUMENT,
221 Error::InsufficientMemory => psa_crypto_sys::PSA_ERROR_INSUFFICIENT_MEMORY,
222 Error::InsufficientStorage => psa_crypto_sys::PSA_ERROR_INSUFFICIENT_STORAGE,
223 Error::CommunicationFailure => psa_crypto_sys::PSA_ERROR_COMMUNICATION_FAILURE,
224 Error::StorageFailure => psa_crypto_sys::PSA_ERROR_STORAGE_FAILURE,
225 Error::DataCorrupt => psa_crypto_sys::PSA_ERROR_DATA_CORRUPT,
226 Error::DataInvalid => psa_crypto_sys::PSA_ERROR_DATA_INVALID,
227 Error::HardwareFailure => psa_crypto_sys::PSA_ERROR_HARDWARE_FAILURE,
228 Error::CorruptionDetected => psa_crypto_sys::PSA_ERROR_CORRUPTION_DETECTED,
229 Error::InsufficientEntropy => psa_crypto_sys::PSA_ERROR_INSUFFICIENT_ENTROPY,
230 Error::InvalidSignature => psa_crypto_sys::PSA_ERROR_INVALID_SIGNATURE,
231 Error::InvalidPadding => psa_crypto_sys::PSA_ERROR_INVALID_PADDING,
232 Error::InsufficientData => psa_crypto_sys::PSA_ERROR_INSUFFICIENT_DATA,
233 Error::InvalidHandle => psa_crypto_sys::PSA_ERROR_INVALID_HANDLE,
234 }
235 }
236}
237
238impl From<Status> for Result<()> {
239 fn from(status: Status) -> Self {
240 status.to_result()
241 }
242}
243
244#[cfg(test)]
245mod test {
246 use crate::types::status::{Error, Status};
247
248 #[test]
249 fn conversion() {
250 assert_eq!(psa_crypto_sys::PSA_SUCCESS, Status::Success.into());
251 assert_eq!(
252 psa_crypto_sys::PSA_ERROR_HARDWARE_FAILURE,
253 Status::Error(Error::HardwareFailure).into()
254 );
255 assert_eq!(
256 Status::Error(Error::HardwareFailure),
257 psa_crypto_sys::PSA_ERROR_HARDWARE_FAILURE.into()
258 );
259 assert_ne!(
260 Status::Error(Error::InsufficientEntropy),
261 psa_crypto_sys::PSA_ERROR_HARDWARE_FAILURE.into()
262 );
263 assert_eq!(Status::Error(Error::GenericError), 0x0EAD_BEEF.into());
264 }
265}