1use crate::layer::field::{FieldError, read_u32_le, read_u64_le};
10
11use super::types;
12
13#[derive(Debug, Clone, PartialEq, Eq, Default)]
20pub struct AuxSecurityHeader {
21 pub security_level: u8,
23 pub key_id_mode: u8,
25 pub reserved: u8,
27 pub frame_counter: u32,
29 pub key_source: u64,
31 pub key_index: Option<u8>,
33}
34
35impl AuxSecurityHeader {
36 #[must_use]
38 pub fn len(&self) -> usize {
39 1 + 4 + types::key_id_len(self.key_id_mode)
41 }
42
43 #[must_use]
46 pub fn compute_len(security_control: u8) -> usize {
47 let key_id_mode = (security_control >> 3) & 0x03;
48 1 + 4 + types::key_id_len(key_id_mode)
49 }
50
51 pub fn parse(buf: &[u8], offset: usize) -> Result<(Self, usize), FieldError> {
54 if buf.len() < offset + 5 {
56 return Err(FieldError::BufferTooShort {
57 offset,
58 need: 5,
59 have: buf.len().saturating_sub(offset),
60 });
61 }
62
63 let sc = buf[offset];
64 let security_level = sc & 0x07;
65 let key_id_mode = (sc >> 3) & 0x03;
66 let reserved = (sc >> 5) & 0x07;
67
68 let frame_counter = read_u32_le(buf, offset + 1)?;
69
70 let ki_len = types::key_id_len(key_id_mode);
71 let total_len = 1 + 4 + ki_len;
72
73 if buf.len() < offset + total_len {
74 return Err(FieldError::BufferTooShort {
75 offset,
76 need: total_len,
77 have: buf.len().saturating_sub(offset),
78 });
79 }
80
81 let mut key_source: u64 = 0;
82 let key_index: Option<u8>;
83
84 match key_id_mode {
85 0 => {
86 key_index = None;
88 },
89 1 => {
90 key_index = Some(buf[offset + 5]);
92 },
93 2 => {
94 key_source = u64::from(read_u32_le(buf, offset + 5)?);
96 key_index = Some(buf[offset + 9]);
97 },
98 3 => {
99 key_source = read_u64_le(buf, offset + 5)?;
101 key_index = Some(buf[offset + 13]);
102 },
103 _ => {
104 key_index = None;
105 },
106 }
107
108 Ok((
109 Self {
110 security_level,
111 key_id_mode,
112 reserved,
113 frame_counter,
114 key_source,
115 key_index,
116 },
117 total_len,
118 ))
119 }
120
121 #[must_use]
123 pub fn build(&self) -> Vec<u8> {
124 let mut out = Vec::with_capacity(self.len());
125
126 let sc = (self.security_level & 0x07)
128 | ((self.key_id_mode & 0x03) << 3)
129 | ((self.reserved & 0x07) << 5);
130 out.push(sc);
131
132 out.extend_from_slice(&self.frame_counter.to_le_bytes());
134
135 match self.key_id_mode {
137 0 => {
138 },
140 1 => {
141 out.push(self.key_index.unwrap_or(0xFF));
143 },
144 2 => {
145 out.extend_from_slice(&(self.key_source as u32).to_le_bytes());
147 out.push(self.key_index.unwrap_or(0xFF));
148 },
149 3 => {
150 out.extend_from_slice(&self.key_source.to_le_bytes());
152 out.push(self.key_index.unwrap_or(0xFF));
153 },
154 _ => {},
155 }
156
157 out
158 }
159
160 pub fn write_into(&self, buf: &mut [u8], offset: usize) -> Result<usize, FieldError> {
163 let bytes = self.build();
164 if buf.len() < offset + bytes.len() {
165 return Err(FieldError::BufferTooShort {
166 offset,
167 need: bytes.len(),
168 have: buf.len().saturating_sub(offset),
169 });
170 }
171 buf[offset..offset + bytes.len()].copy_from_slice(&bytes);
172 Ok(bytes.len())
173 }
174}
175
176#[inline]
178#[must_use]
179pub fn read_security_level(sc: u8) -> u8 {
180 sc & 0x07
181}
182
183#[inline]
185#[must_use]
186pub fn read_key_id_mode(sc: u8) -> u8 {
187 (sc >> 3) & 0x03
188}
189
190#[cfg(test)]
191mod tests {
192 use super::*;
193
194 #[test]
195 fn test_parse_implicit_key() {
196 let buf = [0x00, 0x00, 0x00, 0x00, 0x00];
199 let (hdr, consumed) = AuxSecurityHeader::parse(&buf, 0).unwrap();
200 assert_eq!(hdr.security_level, 0);
201 assert_eq!(hdr.key_id_mode, 0);
202 assert_eq!(hdr.reserved, 0);
203 assert_eq!(hdr.frame_counter, 0);
204 assert_eq!(hdr.key_index, None);
205 assert_eq!(consumed, 5);
206 }
207
208 #[test]
209 fn test_parse_key_index_mode() {
210 let buf = [0x09, 0x78, 0x56, 0x34, 0x12, 0x42];
215 let (hdr, consumed) = AuxSecurityHeader::parse(&buf, 0).unwrap();
216 assert_eq!(hdr.security_level, 1);
217 assert_eq!(hdr.key_id_mode, 1);
218 assert_eq!(hdr.frame_counter, 0x12345678);
219 assert_eq!(hdr.key_index, Some(0x42));
220 assert_eq!(consumed, 6);
221 }
222
223 #[test]
224 fn test_parse_key_source_4() {
225 let buf = [0x15, 0x01, 0x00, 0x00, 0x00, 0xDD, 0xCC, 0xBB, 0xAA, 0x01];
231 let (hdr, consumed) = AuxSecurityHeader::parse(&buf, 0).unwrap();
232 assert_eq!(hdr.security_level, 5);
233 assert_eq!(hdr.key_id_mode, 2);
234 assert_eq!(hdr.frame_counter, 1);
235 assert_eq!(hdr.key_source, 0xAABBCCDD);
236 assert_eq!(hdr.key_index, Some(0x01));
237 assert_eq!(consumed, 10);
238 }
239
240 #[test]
241 fn test_parse_key_source_8() {
242 let buf = [
248 0x1F, 0x02, 0x00, 0x00, 0x00, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0xFF,
249 ];
250 let (hdr, consumed) = AuxSecurityHeader::parse(&buf, 0).unwrap();
251 assert_eq!(hdr.security_level, 7);
252 assert_eq!(hdr.key_id_mode, 3);
253 assert_eq!(hdr.frame_counter, 2);
254 assert_eq!(hdr.key_source, 0x0102030405060708);
255 assert_eq!(hdr.key_index, Some(0xFF));
256 assert_eq!(consumed, 14);
257 }
258
259 #[test]
260 fn test_build_roundtrip_implicit() {
261 let hdr = AuxSecurityHeader {
262 security_level: 0,
263 key_id_mode: 0,
264 reserved: 0,
265 frame_counter: 0,
266 key_source: 0,
267 key_index: None,
268 };
269 let bytes = hdr.build();
270 assert_eq!(bytes.len(), 5);
271 let (parsed, consumed) = AuxSecurityHeader::parse(&bytes, 0).unwrap();
272 assert_eq!(consumed, 5);
273 assert_eq!(parsed, hdr);
274 }
275
276 #[test]
277 fn test_build_roundtrip_key_index() {
278 let hdr = AuxSecurityHeader {
279 security_level: 1,
280 key_id_mode: 1,
281 reserved: 0,
282 frame_counter: 0x12345678,
283 key_source: 0,
284 key_index: Some(0x42),
285 };
286 let bytes = hdr.build();
287 assert_eq!(bytes.len(), 6);
288 let (parsed, _) = AuxSecurityHeader::parse(&bytes, 0).unwrap();
289 assert_eq!(parsed, hdr);
290 }
291
292 #[test]
293 fn test_build_roundtrip_key_source_4() {
294 let hdr = AuxSecurityHeader {
295 security_level: 5,
296 key_id_mode: 2,
297 reserved: 0,
298 frame_counter: 1,
299 key_source: 0xAABBCCDD,
300 key_index: Some(0x01),
301 };
302 let bytes = hdr.build();
303 assert_eq!(bytes.len(), 10);
304 let (parsed, _) = AuxSecurityHeader::parse(&bytes, 0).unwrap();
305 assert_eq!(parsed, hdr);
306 }
307
308 #[test]
309 fn test_build_roundtrip_key_source_8() {
310 let hdr = AuxSecurityHeader {
311 security_level: 7,
312 key_id_mode: 3,
313 reserved: 0,
314 frame_counter: 2,
315 key_source: 0x0102030405060708,
316 key_index: Some(0xFF),
317 };
318 let bytes = hdr.build();
319 assert_eq!(bytes.len(), 14);
320 let (parsed, _) = AuxSecurityHeader::parse(&bytes, 0).unwrap();
321 assert_eq!(parsed, hdr);
322 }
323
324 #[test]
325 fn test_parse_with_offset() {
326 let mut buf = vec![0xAA, 0xBB, 0xCC];
328 let hdr = AuxSecurityHeader {
329 security_level: 4,
330 key_id_mode: 1,
331 reserved: 0,
332 frame_counter: 100,
333 key_source: 0,
334 key_index: Some(0x05),
335 };
336 buf.extend_from_slice(&hdr.build());
337 let (parsed, consumed) = AuxSecurityHeader::parse(&buf, 3).unwrap();
338 assert_eq!(parsed, hdr);
339 assert_eq!(consumed, 6);
340 }
341
342 #[test]
343 fn test_parse_buffer_too_short() {
344 let buf = [0x00, 0x00]; let result = AuxSecurityHeader::parse(&buf, 0);
346 assert!(result.is_err());
347 }
348
349 #[test]
350 fn test_compute_len() {
351 assert_eq!(AuxSecurityHeader::compute_len(0x00), 5); assert_eq!(AuxSecurityHeader::compute_len(0x08), 6); assert_eq!(AuxSecurityHeader::compute_len(0x10), 10); assert_eq!(AuxSecurityHeader::compute_len(0x18), 14); }
356
357 #[test]
358 fn test_write_into() {
359 let hdr = AuxSecurityHeader {
360 security_level: 1,
361 key_id_mode: 1,
362 reserved: 0,
363 frame_counter: 42,
364 key_source: 0,
365 key_index: Some(0x10),
366 };
367 let mut buf = vec![0u8; 20];
368 let written = hdr.write_into(&mut buf, 2).unwrap();
369 assert_eq!(written, 6);
370 let (parsed, _) = AuxSecurityHeader::parse(&buf, 2).unwrap();
371 assert_eq!(parsed, hdr);
372 }
373
374 #[test]
375 fn test_read_security_level() {
376 assert_eq!(read_security_level(0x00), 0);
377 assert_eq!(read_security_level(0x07), 7);
378 assert_eq!(read_security_level(0xFF), 7);
379 }
380
381 #[test]
382 fn test_read_key_id_mode() {
383 assert_eq!(read_key_id_mode(0x00), 0);
384 assert_eq!(read_key_id_mode(0x08), 1);
385 assert_eq!(read_key_id_mode(0x10), 2);
386 assert_eq!(read_key_id_mode(0x18), 3);
387 }
388}