1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! Error-like data structures. See `ResponsePacketError` in the CDDL
18 
19 // derive(N) generates a method that is missing a docstring.
20 #![allow(missing_docs)]
21 
22 use crate::cbor_convert::value_to_integer;
23 use crate::data_types::response::Response;
24 use alloc::boxed::Box;
25 use alloc::vec::Vec;
26 use ciborium::Value;
27 use coset::CoseError;
28 use enumn::N;
29 
30 /// 'Error code' corresponding to successful response.
31 pub const ERROR_OK: u16 = 0; // All real errors must have non-zero error_codes
32 
33 /// Errors from Secretkeeper API. Keep in sync with `ErrorCode` defined for Secretkeeper HAL
34 /// at SecretManagement.cddl
35 #[derive(Clone, Copy, Debug, Eq, N, PartialEq)]
36 pub enum SecretkeeperError {
37     // This is the Error code used if no other error codes explains the issue.
38     UnexpectedServerError = 1,
39     // Indicates the Request was malformed & hence couldn't be served.
40     RequestMalformed = 2,
41     /// Requested Entry not found.
42     EntryNotFound = 3,
43     /// Errors originating during serialization or deserialization
44     SerializationError = 4,
45     /// Policy matching did not succeed & hence access not granted.
46     DicePolicyError = 5,
47 }
48 
49 // [`SecretkeeperError`] is a valid [`Response`] type.
50 // For more information see `ErrorCode` in SecretManagement.cddl alongside ISecretkeeper.aidl
51 impl Response for SecretkeeperError {
new(response_cbor: Vec<Value>) -> Result<Box<Self>, Error>52     fn new(response_cbor: Vec<Value>) -> Result<Box<Self>, Error> {
53         // TODO(b/291228655): This method currently discards the second value in response_cbor,
54         // which contains additional human-readable context in error. Include it!
55         if response_cbor.is_empty() || response_cbor.len() > 2 {
56             return Err(Error::ResponseMalformed);
57         }
58         let error_code: u16 = value_to_integer(&response_cbor[0])?.try_into()?;
59         SecretkeeperError::n(error_code)
60             .map_or_else(|| Err(Error::ResponseMalformed), |sk_err| Ok(Box::new(sk_err)))
61     }
62 
error_code(&self) -> u1663     fn error_code(&self) -> u16 {
64         *self as u16
65     }
66 }
67 
68 /// Errors thrown internally by the library.
69 #[derive(Debug, PartialEq)]
70 pub enum Error {
71     /// Request was malformed.
72     RequestMalformed,
73     /// Response received from the server was malformed.
74     ResponseMalformed,
75     /// An error happened when serializing to/from a [`Value`].
76     CborValueError,
77     /// An error happened while casting a type to different type,
78     /// including one [`Value`] type to another.
79     ConversionError,
80     /// These are unexpected errors, which should never really happen.
81     UnexpectedError,
82     /// Sequence number has reached the upper limit.
83     SequenceNumberExhausted,
84 }
85 
86 impl From<ciborium::value::Error> for Error {
from(_e: ciborium::value::Error) -> Self87     fn from(_e: ciborium::value::Error) -> Self {
88         Self::CborValueError
89     }
90 }
91 
92 impl From<ciborium::Value> for Error {
from(_e: ciborium::Value) -> Self93     fn from(_e: ciborium::Value) -> Self {
94         Self::ConversionError
95     }
96 }
97 
98 impl From<core::num::TryFromIntError> for Error {
from(_e: core::num::TryFromIntError) -> Self99     fn from(_e: core::num::TryFromIntError) -> Self {
100         Self::ConversionError
101     }
102 }
103 
104 impl From<coset::CoseError> for Error {
from(e: coset::CoseError) -> Self105     fn from(e: coset::CoseError) -> Self {
106         match e {
107             CoseError::DecodeFailed(_)
108             | CoseError::EncodeFailed
109             | CoseError::UnexpectedItem(_, _) => Self::ConversionError,
110             _ => {
111                 // TODO: Map other COSE errors to precise errors when we use coset more heavily.
112                 Self::UnexpectedError
113             }
114         }
115     }
116 }
117