1
//! An error type for [C Tor](crate::keystore::ctor) keystores.
2

            
3
use crate::KeystoreError;
4
use crate::keystore::fs_utils;
5
use tor_error::{ErrorKind, HasKind};
6
use tor_hscrypto::pk::HsIdParseError;
7
use tor_key_forge::KeystoreItemType;
8

            
9
use std::path::PathBuf;
10
use std::sync::Arc;
11

            
12
/// An error returned by a C Tor
13
/// [`Keystore`](crate::Keystore) implementation.
14
#[derive(thiserror::Error, Debug, Clone)]
15
pub(crate) enum CTorKeystoreError {
16
    /// An error that occurred while accessing the filesystem.
17
    #[error("{0}")]
18
    Filesystem(#[from] fs_utils::FilesystemError),
19

            
20
    /// Found a malformed.
21
    #[error("Key {path} is malformed")]
22
    MalformedKey {
23
        /// The path of the key.
24
        path: PathBuf,
25
        /// The underlying error.
26
        #[source]
27
        err: MalformedKeyError,
28
    },
29

            
30
    /// An unsupported operation.
31
    #[error("Operation not supported: {action}")]
32
    NotSupported {
33
        /// The action we were trying to perform.
34
        action: &'static str,
35
    },
36

            
37
    /// Key type and specifier mismatch.
38
    #[error("Invalid item type {item_type:?} for {item}")]
39
    InvalidKeystoreItemType {
40
        /// The item type.
41
        item_type: KeystoreItemType,
42
        /// The item we tried to access.
43
        item: String,
44
    },
45

            
46
    /// An internal error.
47
    #[error("Internal error")]
48
    Bug(#[from] tor_error::Bug),
49
}
50

            
51
/// Encountered a malformed C Tor key.
52
#[derive(thiserror::Error, Debug, Clone)]
53
pub(crate) enum MalformedKeyError {
54
    /// A malformed hidden service key.
55
    #[error("{0}")]
56
    Service(#[from] MalformedServiceKeyError),
57

            
58
    /// A malformed hidden service client key.
59
    #[error("{0}")]
60
    Client(#[from] MalformedClientKeyError),
61
}
62

            
63
/// Encountered a malformed C Tor service key.
64
#[derive(thiserror::Error, Debug, Clone)]
65
pub(crate) enum MalformedServiceKeyError {
66
    /// Found a key with an invalid tag
67
    #[error("invalid key length: {len} (expected {expected_len})")]
68
    InvalidKeyLen {
69
        /// The length of the invalid key.
70
        len: usize,
71
        /// The expected length of this key.
72
        expected_len: usize,
73
    },
74

            
75
    /// Found a key with an invalid tag
76
    #[error("invalid tag: {tag:?} (expected {expected_tag:?})")]
77
    InvalidTag {
78
        /// The invalid tag.
79
        tag: Vec<u8>,
80
        /// The expected value of the tag.
81
        expected_tag: Vec<u8>,
82
    },
83

            
84
    /// Found an entry that cannot be recognized as a key
85
    /// (i.e.: a key that doesn't provide a valid
86
    /// [`CTorPath`](crate::CTorPath))
87
    #[error("unrecognized key")]
88
    NotAKey,
89

            
90
    /// Found an invalid ed25519 public key
91
    #[error("invalid ed25519 public key")]
92
    Ed25519Public(#[from] Arc<signature::Error>),
93

            
94
    /// Found an invalid ed25519 keypair
95
    //
96
    // Note: this error doesn't have any context, because we use
97
    // ed25519::ExpandedKeypair::from_secret_key_bytes to parse the key,
98
    // which returns `None` if the key can't be parsed
99
    // (so we don't have any information about what actually went wrong).
100
    #[error("invalid ed25519 keypair")]
101
    Ed25519Keypair,
102

            
103
    /// An internal error.
104
    #[error("Internal error")]
105
    Bug(#[from] tor_error::Bug),
106
}
107

            
108
/// Encountered a malformed C Tor client key.
109
#[derive(thiserror::Error, Debug, Clone)]
110
pub(crate) enum MalformedClientKeyError {
111
    /// The auth type is not "descriptor".
112
    #[error("Invalid auth type {0}")]
113
    InvalidAuthType(String),
114

            
115
    /// The key type is not "x25519".
116
    #[error("Invalid key type {0}")]
117
    InvalidKeyType(String),
118

            
119
    /// The key is not in the `<auth-type>:x25519:<base32-encoded-public-key>` format.
120
    #[error("Invalid key format")]
121
    InvalidFormat,
122

            
123
    /// The encoded key material is invalid.
124
    #[error("Invalid key material")]
125
    InvalidKeyMaterial,
126

            
127
    /// Base32 decoding failed.
128
    #[error("Invalid base32 in client key")]
129
    InvalidBase32(#[from] data_encoding::DecodeError),
130

            
131
    /// Failed to parse the HsId.
132
    #[error("Invalid HsId client key")]
133
    InvalidHsId(#[from] HsIdParseError),
134
}
135

            
136
impl KeystoreError for CTorKeystoreError {}
137

            
138
impl HasKind for CTorKeystoreError {
139
    fn kind(&self) -> ErrorKind {
140
        use CTorKeystoreError as KE;
141

            
142
        match self {
143
            KE::Filesystem(e) => e.kind(),
144
            KE::MalformedKey { .. } => ErrorKind::KeystoreCorrupted,
145
            KE::NotSupported { .. } => ErrorKind::BadApiUsage,
146
            KE::InvalidKeystoreItemType { .. } => ErrorKind::BadApiUsage,
147
            KE::Bug(e) => e.kind(),
148
        }
149
    }
150
}
151

            
152
impl From<CTorKeystoreError> for crate::Error {
153
12
    fn from(e: CTorKeystoreError) -> Self {
154
12
        crate::Error::Keystore(Arc::new(e))
155
12
    }
156
}