parsec_interface/requests/
response_status.rs

1// Copyright 2019 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use log::{error, warn};
4use num_derive::FromPrimitive;
5use std::convert::TryFrom;
6use std::error::Error as ErrorTrait;
7use std::fmt;
8
9/// C-like enum mapping response status options to their code.
10///
11/// See the [status
12/// code](https://parallaxsecond.github.io/parsec-book/parsec_client/status_codes.html) page for a
13/// broader description of these codes.
14#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive)]
15#[repr(u16)]
16pub enum ResponseStatus {
17    /// Successful operation
18    Success = 0,
19    /// Requested provider ID does not match that of the backend
20    WrongProviderId = 1,
21    /// Requested content type is not supported by the backend
22    ContentTypeNotSupported = 2,
23    /// Requested accept type is not supported by the backend
24    AcceptTypeNotSupported = 3,
25    /// Requested version is not supported by the backend
26    WireProtocolVersionNotSupported = 4,
27    /// No provider registered for the requested provider ID
28    ProviderNotRegistered = 5,
29    /// No provider defined for requested provider ID
30    ProviderDoesNotExist = 6,
31    /// Failed to deserialize the body of the message
32    DeserializingBodyFailed = 7,
33    /// Failed to serialize the body of the message
34    SerializingBodyFailed = 8,
35    /// Requested operation is not defined
36    OpcodeDoesNotExist = 9,
37    /// Response size exceeds allowed limits
38    ResponseTooLarge = 10,
39    /// Authentication failed
40    AuthenticationError = 11,
41    /// Authenticator not supported
42    AuthenticatorDoesNotExist = 12,
43    /// Authenticator not supported
44    AuthenticatorNotRegistered = 13,
45    /// Internal error in the Key Info Manager
46    KeyInfoManagerError = 14,
47    /// Generic input/output error
48    ConnectionError = 15,
49    /// Invalid value for this data type
50    InvalidEncoding = 16,
51    /// Constant fields in header are invalid
52    InvalidHeader = 17,
53    /// The UUID vector needs to only contain 16 bytes
54    WrongProviderUuid = 18,
55    /// Request did not provide a required authentication
56    NotAuthenticated = 19,
57    /// Request length specified in the header is above defined limit
58    BodySizeExceedsLimit = 20,
59    /// The operation requires admin privilege
60    AdminOperation = 21,
61    /// The key template contains a deprecated type or algorithm
62    DeprecatedPrimitive = 22,
63    /// An error occurred that does not correspond to any defined failure cause
64    PsaErrorGenericError = 1132,
65    /// The requested operation or a parameter is not supported by this implementation
66    PsaErrorNotSupported = 1134,
67    /// The requested action is denied by a policy
68    PsaErrorNotPermitted = 1133,
69    /// An output buffer is too small
70    PsaErrorBufferTooSmall = 1138,
71    /// Asking for an item that already exists
72    PsaErrorAlreadyExists = 1139,
73    /// Asking for an item that doesn't exist
74    PsaErrorDoesNotExist = 1140,
75    /// The requested action cannot be performed in the current state
76    PsaErrorBadState = 1137,
77    /// The parameters passed to the function are invalid
78    PsaErrorInvalidArgument = 1135,
79    /// There is not enough runtime memory
80    PsaErrorInsufficientMemory = 1141,
81    /// There is not enough persistent storage
82    PsaErrorInsufficientStorage = 1142,
83    /// There was a communication failure inside the implementation
84    PsaErrorCommunicationFailure = 1145,
85    /// There was a storage failure that may have led to data loss
86    PsaErrorStorageFailure = 1146,
87    /// Stored data has been corrupted
88    PsaErrorDataCorrupt = 1152,
89    /// Data read from storage is not valid for the implementation
90    PsaErrorDataInvalid = 1153,
91    /// A hardware failure was detected
92    PsaErrorHardwareFailure = 1147,
93    /// A tampering attempt was detected
94    PsaErrorCorruptionDetected = 1151,
95    /// There is not enough entropy to generate random data needed for the requested action
96    PsaErrorInsufficientEntropy = 1148,
97    /// The signature, MAC or hash is incorrect
98    PsaErrorInvalidSignature = 1149,
99    /// The decrypted padding is incorrect
100    PsaErrorInvalidPadding = 1150,
101    /// Insufficient data when attempting to read from a resource
102    PsaErrorInsufficientData = 1143,
103    /// The key handle is not valid
104    PsaErrorInvalidHandle = 1136,
105}
106
107impl TryFrom<u16> for ResponseStatus {
108    type Error = ResponseStatus;
109
110    fn try_from(value: u16) -> Result<Self> {
111        num::FromPrimitive::from_u16(value).ok_or_else(|| {
112            error!(
113                "Value {} does not correspond to a valid ResponseStatus.",
114                value
115            );
116            ResponseStatus::InvalidEncoding
117        })
118    }
119}
120
121impl fmt::Display for ResponseStatus {
122    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123        match self {
124            ResponseStatus::Success => write!(f, "successful operation"),
125            ResponseStatus::WrongProviderId => write!(
126                f,
127                "requested provider ID does not match that of the backend"
128            ),
129            ResponseStatus::ContentTypeNotSupported => {
130                write!(f, "requested content type is not supported by the backend")
131            }
132            ResponseStatus::AcceptTypeNotSupported => {
133                write!(f, "requested accept type is not supported by the backend")
134            }
135            ResponseStatus::WireProtocolVersionNotSupported => {
136                write!(f, "requested version is not supported by the backend")
137            }
138            ResponseStatus::ProviderNotRegistered => {
139                write!(f, "no provider registered for the requested provider ID")
140            }
141            ResponseStatus::ProviderDoesNotExist => {
142                write!(f, "no provider defined for requested provider ID")
143            }
144            ResponseStatus::DeserializingBodyFailed => {
145                write!(f, "failed to deserialize the body of the message")
146            }
147            ResponseStatus::SerializingBodyFailed => {
148                write!(f, "failed to serialize the body of the message")
149            }
150            ResponseStatus::OpcodeDoesNotExist => write!(f, "requested operation is not defined"),
151            ResponseStatus::ResponseTooLarge => write!(f, "response size exceeds allowed limits"),
152            ResponseStatus::AuthenticationError => {
153                write!(f, "authentication failed")
154            }
155            ResponseStatus::AuthenticatorDoesNotExist => {
156                write!(f, "authenticator not supported")
157            }
158            ResponseStatus::AuthenticatorNotRegistered => {
159                write!(f, "authenticator not supported")
160            }
161            ResponseStatus::KeyInfoManagerError => {
162                write!(f, "internal error in the Key Info Manager")
163            }
164            ResponseStatus::ConnectionError => {
165                write!(f, "generic input/output error")
166            }
167            ResponseStatus::InvalidEncoding => {
168                write!(f, "invalid value for this data type")
169            }
170            ResponseStatus::InvalidHeader => {
171                write!(f, "constant fields in header are invalid")
172            }
173            ResponseStatus::WrongProviderUuid => {
174                write!(f, "the UUID vector needs to only contain 16 bytes")
175            }
176            ResponseStatus::NotAuthenticated => {
177                write!(f, "request did not provide a required authentication")
178            }
179            ResponseStatus::BodySizeExceedsLimit => {
180                write!(
181                    f,
182                    "request length specified in the header is above defined limit"
183                )
184            }
185            ResponseStatus::AdminOperation => {
186                write!(f, "the operation requires admin privilege")
187            }
188            ResponseStatus::DeprecatedPrimitive => {
189                write!(
190                    f,
191                    "the key template contains a deprecated type or algorithm"
192                )
193            }
194            ResponseStatus::PsaErrorGenericError => {
195                write!(
196                    f,
197                    "an error occurred that does not correspond to any defined failure cause"
198                )
199            }
200            ResponseStatus::PsaErrorNotPermitted => {
201                write!(f, "the requested action is denied by a policy")
202            }
203            ResponseStatus::PsaErrorNotSupported => {
204                write!(f, "the requested operation or a parameter is not supported by this implementation")
205            }
206            ResponseStatus::PsaErrorInvalidArgument => {
207                write!(f, "the parameters passed to the function are invalid")
208            }
209            ResponseStatus::PsaErrorInvalidHandle => {
210                write!(f, "the key handle is not valid")
211            }
212            ResponseStatus::PsaErrorBadState => {
213                write!(
214                    f,
215                    "the requested action cannot be performed in the current state"
216                )
217            }
218            ResponseStatus::PsaErrorBufferTooSmall => {
219                write!(f, "an output buffer is too small")
220            }
221            ResponseStatus::PsaErrorAlreadyExists => {
222                write!(f, "asking for an item that already exists")
223            }
224            ResponseStatus::PsaErrorDoesNotExist => {
225                write!(f, "asking for an item that doesn't exist")
226            }
227            ResponseStatus::PsaErrorInsufficientMemory => {
228                write!(f, "there is not enough runtime memory")
229            }
230            ResponseStatus::PsaErrorInsufficientStorage => {
231                write!(f, "there is not enough persistent storage")
232            }
233            ResponseStatus::PsaErrorInsufficientData => {
234                write!(
235                    f,
236                    "insufficient data when attempting to read from a resource"
237                )
238            }
239            ResponseStatus::PsaErrorCommunicationFailure => {
240                write!(
241                    f,
242                    "there was a communication failure inside the implementation"
243                )
244            }
245            ResponseStatus::PsaErrorStorageFailure => {
246                write!(
247                    f,
248                    "there was a storage failure that may have led to data loss"
249                )
250            }
251            ResponseStatus::PsaErrorDataCorrupt => {
252                write!(f, "stored data has been corrupted")
253            }
254            ResponseStatus::PsaErrorDataInvalid => {
255                write!(
256                    f,
257                    "data read from storage is not valid for the implementation"
258                )
259            }
260            ResponseStatus::PsaErrorHardwareFailure => {
261                write!(f, "a hardware failure was detected")
262            }
263            ResponseStatus::PsaErrorCorruptionDetected => {
264                write!(f, "a tampering attempt was detected")
265            }
266            ResponseStatus::PsaErrorInsufficientEntropy => {
267                write!(f, "there is not enough entropy to generate random data needed for the requested action")
268            }
269            ResponseStatus::PsaErrorInvalidSignature => {
270                write!(f, "the signature, MAC or hash is incorrect")
271            }
272            ResponseStatus::PsaErrorInvalidPadding => {
273                write!(f, "the decrypted padding is incorrect")
274            }
275        }
276    }
277}
278
279impl ErrorTrait for ResponseStatus {}
280
281/// Conversion from a std::io::Error to a ResponseStatus
282///
283/// It allows to easily return a ResponseStatus in case of error when using functions from the
284/// standard library.
285impl From<std::io::Error> for ResponseStatus {
286    fn from(err: std::io::Error) -> Self {
287        warn!(
288            "Conversion from {:?} to ResponseStatus::ConnectionError.",
289            err
290        );
291        if err.kind() == std::io::ErrorKind::WouldBlock {
292            warn!("The WouldBlock error might mean that the connection timed out. Try in increase the timeout length.");
293        }
294        ResponseStatus::ConnectionError
295    }
296}
297
298impl From<bincode::Error> for ResponseStatus {
299    fn from(err: bincode::Error) -> Self {
300        warn!(
301            "Conversion from {} to ResponseStatus::InvalidEncoding.",
302            err
303        );
304        ResponseStatus::InvalidEncoding
305    }
306}
307
308impl From<uuid::Error> for ResponseStatus {
309    fn from(err: uuid::Error) -> Self {
310        warn!(
311            "Conversion from {} to ResponseStatus::InvalidEncoding.",
312            err
313        );
314        ResponseStatus::InvalidEncoding
315    }
316}
317
318impl From<std::num::TryFromIntError> for ResponseStatus {
319    fn from(err: std::num::TryFromIntError) -> Self {
320        warn!(
321            "Conversion from {} to ResponseStatus::InvalidEncoding.",
322            err
323        );
324        ResponseStatus::InvalidEncoding
325    }
326}
327
328impl From<std::array::TryFromSliceError> for ResponseStatus {
329    fn from(err: std::array::TryFromSliceError) -> Self {
330        warn!(
331            "Conversion from {} to ResponseStatus::InvalidEncoding.",
332            err
333        );
334        ResponseStatus::InvalidEncoding
335    }
336}
337
338impl From<std::ffi::NulError> for ResponseStatus {
339    fn from(err: std::ffi::NulError) -> Self {
340        warn!(
341            "Conversion from {} to ResponseStatus::InvalidEncoding.",
342            err
343        );
344        ResponseStatus::InvalidEncoding
345    }
346}
347
348impl From<std::convert::Infallible> for ResponseStatus {
349    fn from(_err: std::convert::Infallible) -> Self {
350        unreachable!();
351    }
352}
353
354use psa_crypto::types::status::Error;
355
356impl From<Error> for ResponseStatus {
357    fn from(err: Error) -> ResponseStatus {
358        match err {
359            Error::GenericError => ResponseStatus::PsaErrorGenericError,
360            Error::NotSupported => ResponseStatus::PsaErrorNotSupported,
361            Error::NotPermitted => ResponseStatus::PsaErrorNotPermitted,
362            Error::BufferTooSmall => ResponseStatus::PsaErrorBufferTooSmall,
363            Error::AlreadyExists => ResponseStatus::PsaErrorAlreadyExists,
364            Error::DoesNotExist => ResponseStatus::PsaErrorDoesNotExist,
365            Error::BadState => ResponseStatus::PsaErrorBadState,
366            Error::InvalidArgument => ResponseStatus::PsaErrorInvalidArgument,
367            Error::InsufficientMemory => ResponseStatus::PsaErrorInsufficientMemory,
368            Error::InsufficientStorage => ResponseStatus::PsaErrorInsufficientStorage,
369            Error::CommunicationFailure => ResponseStatus::PsaErrorCommunicationFailure,
370            Error::StorageFailure => ResponseStatus::PsaErrorStorageFailure,
371            Error::DataCorrupt => ResponseStatus::PsaErrorDataCorrupt,
372            Error::DataInvalid => ResponseStatus::PsaErrorDataInvalid,
373            Error::HardwareFailure => ResponseStatus::PsaErrorHardwareFailure,
374            Error::CorruptionDetected => ResponseStatus::PsaErrorCorruptionDetected,
375            Error::InsufficientEntropy => ResponseStatus::PsaErrorInsufficientEntropy,
376            Error::InvalidSignature => ResponseStatus::PsaErrorInvalidSignature,
377            Error::InvalidPadding => ResponseStatus::PsaErrorInvalidPadding,
378            Error::InsufficientData => ResponseStatus::PsaErrorInsufficientData,
379            Error::InvalidHandle => ResponseStatus::PsaErrorInvalidHandle,
380        }
381    }
382}
383
384/// A Result type with the Err variant set as a ResponseStatus
385pub type Result<T> = std::result::Result<T, ResponseStatus>;