embedded_tls/
alert.rs

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