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