1use crate::msgs::enums::{AlertDescription, ContentType, HandshakeType};
2use crate::rand;
3
4use std::error::Error as StdError;
5use std::fmt;
6use std::time::SystemTimeError;
7
8#[derive(Debug, PartialEq, Clone)]
10pub enum Error {
11 InappropriateMessage {
17 expect_types: Vec<ContentType>,
19 got_type: ContentType,
21 },
22
23 InappropriateHandshakeMessage {
27 expect_types: Vec<HandshakeType>,
29 got_type: HandshakeType,
31 },
32
33 CorruptMessage,
35
36 CorruptMessagePayload(ContentType),
38
39 NoCertificatesPresented,
41
42 UnsupportedNameType,
44
45 DecryptError,
47
48 EncryptError,
51
52 PeerIncompatibleError(String),
55
56 PeerMisbehavedError(String),
59
60 AlertReceived(AlertDescription),
62
63 InvalidCertificateEncoding,
65
66 InvalidCertificateSignatureType,
68
69 InvalidCertificateSignature,
71
72 InvalidCertificateData(String),
74
75 InvalidSct(sct::Error),
77
78 General(String),
80
81 FailedToGetCurrentTime,
83
84 FailedToGetRandomBytes,
86
87 HandshakeNotComplete,
90
91 PeerSentOversizedRecord,
93
94 NoApplicationProtocol,
96
97 BadMaxFragmentSize,
100}
101
102fn join<T: fmt::Debug>(items: &[T]) -> String {
103 items
104 .iter()
105 .map(|x| format!("{:?}", x))
106 .collect::<Vec<String>>()
107 .join(" or ")
108}
109
110impl fmt::Display for Error {
111 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112 match *self {
113 Self::InappropriateMessage {
114 ref expect_types,
115 ref got_type,
116 } => write!(
117 f,
118 "received unexpected message: got {:?} when expecting {}",
119 got_type,
120 join::<ContentType>(expect_types)
121 ),
122 Self::InappropriateHandshakeMessage {
123 ref expect_types,
124 ref got_type,
125 } => write!(
126 f,
127 "received unexpected handshake message: got {:?} when expecting {}",
128 got_type,
129 join::<HandshakeType>(expect_types)
130 ),
131 Self::CorruptMessagePayload(ref typ) => {
132 write!(f, "received corrupt message of type {:?}", typ)
133 }
134 Self::PeerIncompatibleError(ref why) => write!(f, "peer is incompatible: {}", why),
135 Self::PeerMisbehavedError(ref why) => write!(f, "peer misbehaved: {}", why),
136 Self::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert),
137 Self::InvalidCertificateEncoding => {
138 write!(f, "invalid peer certificate encoding")
139 }
140 Self::InvalidCertificateSignatureType => {
141 write!(f, "invalid peer certificate signature type")
142 }
143 Self::InvalidCertificateSignature => {
144 write!(f, "invalid peer certificate signature")
145 }
146 Self::InvalidCertificateData(ref reason) => {
147 write!(f, "invalid peer certificate contents: {}", reason)
148 }
149 Self::CorruptMessage => write!(f, "received corrupt message"),
150 Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
151 Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
152 Self::DecryptError => write!(f, "cannot decrypt peer's message"),
153 Self::EncryptError => write!(f, "cannot encrypt message"),
154 Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
155 Self::HandshakeNotComplete => write!(f, "handshake not complete"),
156 Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
157 Self::InvalidSct(ref err) => write!(f, "invalid certificate timestamp: {:?}", err),
158 Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
159 Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
160 Self::BadMaxFragmentSize => {
161 write!(f, "the supplied max_fragment_size was too small or large")
162 }
163 Self::General(ref err) => write!(f, "unexpected error: {}", err),
164 }
165 }
166}
167
168impl From<SystemTimeError> for Error {
169 #[inline]
170 fn from(_: SystemTimeError) -> Self {
171 Self::FailedToGetCurrentTime
172 }
173}
174
175impl StdError for Error {}
176
177impl From<rand::GetRandomFailed> for Error {
178 fn from(_: rand::GetRandomFailed) -> Self {
179 Self::FailedToGetRandomBytes
180 }
181}
182
183#[cfg(test)]
184mod tests {
185 use super::Error;
186
187 #[test]
188 fn smoke() {
189 use crate::msgs::enums::{AlertDescription, ContentType, HandshakeType};
190 use sct;
191
192 let all = vec![
193 Error::InappropriateMessage {
194 expect_types: vec![ContentType::Alert],
195 got_type: ContentType::Handshake,
196 },
197 Error::InappropriateHandshakeMessage {
198 expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
199 got_type: HandshakeType::ServerHello,
200 },
201 Error::CorruptMessage,
202 Error::CorruptMessagePayload(ContentType::Alert),
203 Error::NoCertificatesPresented,
204 Error::DecryptError,
205 Error::PeerIncompatibleError("no tls1.2".to_string()),
206 Error::PeerMisbehavedError("inconsistent something".to_string()),
207 Error::AlertReceived(AlertDescription::ExportRestriction),
208 Error::InvalidCertificateEncoding,
209 Error::InvalidCertificateSignatureType,
210 Error::InvalidCertificateSignature,
211 Error::InvalidCertificateData("Data".into()),
212 Error::InvalidSct(sct::Error::MalformedSct),
213 Error::General("undocumented error".to_string()),
214 Error::FailedToGetCurrentTime,
215 Error::FailedToGetRandomBytes,
216 Error::HandshakeNotComplete,
217 Error::PeerSentOversizedRecord,
218 Error::NoApplicationProtocol,
219 Error::BadMaxFragmentSize,
220 ];
221
222 for err in all {
223 println!("{:?}:", err);
224 println!(" fmt '{}'", err);
225 }
226 }
227
228 #[test]
229 fn rand_error_mapping() {
230 use super::rand;
231 let err: Error = rand::GetRandomFailed.into();
232 assert_eq!(err, Error::FailedToGetRandomBytes);
233 }
234
235 #[test]
236 fn time_error_mapping() {
237 use std::time::SystemTime;
238
239 let time_error = SystemTime::UNIX_EPOCH
240 .duration_since(SystemTime::now())
241 .unwrap_err();
242 let err: Error = time_error.into();
243 assert_eq!(err, Error::FailedToGetCurrentTime);
244 }
245}