dvb_simulcrypt/
message.rs1use alloc::vec::Vec;
26
27use broadcast_common::traits::{Parse, Serialize};
28
29use crate::error::{Error, Result};
30use crate::registry::{Interface, MessageType, ParameterType};
31
32pub const HEADER_LEN: usize = 5;
35
36pub const PARAMETER_HEADER_LEN: usize = 4;
39
40#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47#[cfg_attr(feature = "serde", derive(serde::Serialize))]
48pub struct Parameter<'a> {
49 pub ptype: ParameterType,
51 #[cfg_attr(feature = "serde", serde(borrow))]
53 pub value: &'a [u8],
54}
55
56impl<'a> Parameter<'a> {
57 #[must_use]
59 pub const fn new(ptype: ParameterType, value: &'a [u8]) -> Self {
60 Self { ptype, value }
61 }
62
63 #[must_use]
65 pub const fn wire_len(&self) -> usize {
66 PARAMETER_HEADER_LEN + self.value.len()
67 }
68}
69
70#[derive(Debug, Clone, PartialEq, Eq)]
78#[cfg_attr(feature = "serde", derive(serde::Serialize))]
79pub struct SimulcryptMessage<'a> {
80 pub protocol_version: u8,
82 pub message_type: MessageType,
84 #[cfg_attr(feature = "serde", serde(borrow))]
87 pub parameters: Vec<Parameter<'a>>,
88}
89
90impl<'a> SimulcryptMessage<'a> {
91 #[must_use]
93 pub fn new(
94 protocol_version: u8,
95 message_type: MessageType,
96 parameters: Vec<Parameter<'a>>,
97 ) -> Self {
98 Self {
99 protocol_version,
100 message_type,
101 parameters,
102 }
103 }
104
105 #[must_use]
107 pub const fn interface(&self) -> Interface {
108 self.message_type.interface()
109 }
110
111 #[must_use]
114 pub fn body_len(&self) -> usize {
115 self.parameters.iter().map(Parameter::wire_len).sum()
116 }
117
118 #[must_use]
120 pub fn find(&self, ptype: ParameterType) -> Option<&Parameter<'a>> {
121 self.parameters.iter().find(|p| p.ptype == ptype)
122 }
123
124 pub fn parse_on(iface: Interface, bytes: &'a [u8]) -> Result<Self> {
133 if bytes.len() < HEADER_LEN {
134 return Err(Error::BufferTooShort {
135 need: HEADER_LEN,
136 have: bytes.len(),
137 what: "generic_message header",
138 });
139 }
140 let protocol_version = bytes[0];
141 let raw_message_type = u16::from_be_bytes([bytes[1], bytes[2]]);
142 let message_length = u16::from_be_bytes([bytes[3], bytes[4]]) as usize;
143
144 let body = &bytes[HEADER_LEN..];
145 if body.len() < message_length {
146 return Err(Error::InvalidMessageLength {
147 length: message_length as u16,
148 reason: "message_length exceeds available bytes",
149 });
150 }
151 let body = &body[..message_length];
152
153 let message_type = MessageType::from_u16(iface, raw_message_type);
154
155 let mut parameters = Vec::new();
156 let mut off = 0usize;
157 while off < body.len() {
158 if body.len() - off < PARAMETER_HEADER_LEN {
159 return Err(Error::BufferTooShort {
160 need: PARAMETER_HEADER_LEN,
161 have: body.len() - off,
162 what: "parameter TLV header",
163 });
164 }
165 let raw_ptype = u16::from_be_bytes([body[off], body[off + 1]]);
166 let plen = u16::from_be_bytes([body[off + 2], body[off + 3]]) as usize;
167 let vstart = off + PARAMETER_HEADER_LEN;
168 let remaining = body.len() - vstart;
169 if remaining < plen {
170 return Err(Error::TruncatedParameter {
171 ptype: raw_ptype,
172 need: plen,
173 have: remaining,
174 });
175 }
176 let value = &body[vstart..vstart + plen];
177 parameters.push(Parameter::new(
178 ParameterType::from_u16(iface, raw_ptype),
179 value,
180 ));
181 off = vstart + plen;
182 }
183
184 Ok(Self {
185 protocol_version,
186 message_type,
187 parameters,
188 })
189 }
190}
191
192impl<'a> Parse<'a> for SimulcryptMessage<'a> {
193 type Error = Error;
194
195 fn parse(bytes: &'a [u8]) -> Result<Self> {
199 Self::parse_on(Interface::EcmgScs, bytes)
200 }
201}
202
203impl Serialize for SimulcryptMessage<'_> {
204 type Error = Error;
205
206 fn serialized_len(&self) -> usize {
207 HEADER_LEN + self.body_len()
208 }
209
210 fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
211 let total = self.serialized_len();
212 if buf.len() < total {
213 return Err(Error::OutputBufferTooSmall {
214 need: total,
215 have: buf.len(),
216 });
217 }
218
219 let body_len = self.body_len();
220 if body_len > u16::MAX as usize {
221 return Err(Error::FieldTooWide {
222 what: "message_length",
223 value: body_len,
224 bits: 16,
225 });
226 }
227
228 buf[0] = self.protocol_version;
229 buf[1..3].copy_from_slice(&self.message_type.to_u16().to_be_bytes());
230 buf[3..5].copy_from_slice(&(body_len as u16).to_be_bytes());
231
232 let mut off = HEADER_LEN;
233 for p in &self.parameters {
234 let plen = p.value.len();
235 if plen > u16::MAX as usize {
236 return Err(Error::FieldTooWide {
237 what: "parameter_length",
238 value: plen,
239 bits: 16,
240 });
241 }
242 buf[off..off + 2].copy_from_slice(&p.ptype.to_u16().to_be_bytes());
243 buf[off + 2..off + 4].copy_from_slice(&(plen as u16).to_be_bytes());
244 off += PARAMETER_HEADER_LEN;
245 buf[off..off + plen].copy_from_slice(p.value);
246 off += plen;
247 }
248
249 debug_assert_eq!(off, total);
250 Ok(total)
251 }
252}