1use crate::buffer::CryptoBuffer;
2use crate::parse_buffer::ParseBuffer;
3use crate::TlsError;
4
5#[derive(Debug, Clone, Copy)]
6#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7pub enum AlertLevel {
8 Warning = 1,
9 Fatal = 2,
10}
11
12impl AlertLevel {
13 pub fn of(num: u8) -> Option<Self> {
14 match num {
15 1 => Some(AlertLevel::Warning),
16 2 => Some(AlertLevel::Fatal),
17 _ => None,
18 }
19 }
20}
21
22#[derive(Debug, Clone, Copy)]
23#[cfg_attr(feature = "defmt", derive(defmt::Format))]
24pub enum AlertDescription {
25 CloseNotify = 0,
26 UnexpectedMessage = 10,
27 BadRecordMac = 20,
28 RecordOverflow = 22,
29 HandshakeFailure = 40,
30 BadCertificate = 42,
31 UnsupportedCertificate = 43,
32 CertificateRevoked = 44,
33 CertificateExpired = 45,
34 CertificateUnknown = 46,
35 IllegalParameter = 47,
36 UnknownCa = 48,
37 AccessDenied = 49,
38 DecodeError = 50,
39 DecryptError = 51,
40 ProtocolVersion = 70,
41 InsufficientSecurity = 71,
42 InternalError = 80,
43 InappropriateFallback = 86,
44 UserCanceled = 90,
45 MissingExtension = 109,
46 UnsupportedExtension = 110,
47 UnrecognizedName = 112,
48 BadCertificateStatusResponse = 113,
49 UnknownPskIdentity = 115,
50 CertificateRequired = 116,
51 NoApplicationProtocol = 120,
52}
53
54impl AlertDescription {
55 pub fn of(num: u8) -> Option<Self> {
56 match num {
57 0 => Some(AlertDescription::CloseNotify),
58 10 => Some(AlertDescription::UnexpectedMessage),
59 20 => Some(AlertDescription::BadRecordMac),
60 22 => Some(AlertDescription::RecordOverflow),
61 40 => Some(AlertDescription::HandshakeFailure),
62 42 => Some(AlertDescription::BadCertificate),
63 43 => Some(AlertDescription::UnsupportedCertificate),
64 44 => Some(AlertDescription::CertificateRevoked),
65 45 => Some(AlertDescription::CertificateExpired),
66 46 => Some(AlertDescription::CertificateUnknown),
67 47 => Some(AlertDescription::IllegalParameter),
68 48 => Some(AlertDescription::UnknownCa),
69 49 => Some(AlertDescription::AccessDenied),
70 50 => Some(AlertDescription::DecodeError),
71 51 => Some(AlertDescription::DecryptError),
72 70 => Some(AlertDescription::ProtocolVersion),
73 71 => Some(AlertDescription::InsufficientSecurity),
74 80 => Some(AlertDescription::InternalError),
75 86 => Some(AlertDescription::InappropriateFallback),
76 90 => Some(AlertDescription::UserCanceled),
77 109 => Some(AlertDescription::MissingExtension),
78 110 => Some(AlertDescription::UnsupportedExtension),
79 112 => Some(AlertDescription::UnrecognizedName),
80 113 => Some(AlertDescription::BadCertificateStatusResponse),
81 115 => Some(AlertDescription::UnknownPskIdentity),
82 116 => Some(AlertDescription::CertificateRequired),
83 120 => Some(AlertDescription::NoApplicationProtocol),
84 _ => None,
85 }
86 }
87}
88
89#[derive(Debug)]
90#[cfg_attr(feature = "defmt", derive(defmt::Format))]
91pub struct Alert {
92 pub(crate) level: AlertLevel,
93 pub(crate) description: AlertDescription,
94}
95
96impl Alert {
97 pub fn new(level: AlertLevel, description: AlertDescription) -> Self {
98 Self { level, description }
99 }
100
101 pub fn parse(buf: &mut ParseBuffer<'_>) -> Result<Alert, TlsError> {
102 let level = buf.read_u8()?;
103 let desc = buf.read_u8()?;
104
105 Ok(Self {
106 level: AlertLevel::of(level).ok_or(TlsError::DecodeError)?,
107 description: AlertDescription::of(desc).ok_or(TlsError::DecodeError)?,
108 })
109 }
110
111 pub fn encode(&self, buf: &mut CryptoBuffer<'_>) -> Result<(), TlsError> {
112 buf.push(self.level as u8)
113 .map_err(|_| TlsError::EncodeError)?;
114 buf.push(self.description as u8)
115 .map_err(|_| TlsError::EncodeError)?;
116 Ok(())
117 }
118}