embedded_tls/
alert.rs

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}