zerodds_security_rtps/
header_aad.rs1use alloc::vec::Vec;
13
14pub const RTPS_HEADER_LEN: usize = 20;
17
18pub fn build_rtps_header_aad(
36 transformation_kind: [u8; 4],
37 transformation_key_id: [u8; 4],
38 session_id: [u8; 4],
39 rtps_header_bytes: &[u8],
40) -> Result<Vec<u8>, &'static str> {
41 if rtps_header_bytes.len() < RTPS_HEADER_LEN {
42 return Err("rtps header < 20 bytes");
43 }
44 let mut out = Vec::with_capacity(16 + RTPS_HEADER_LEN);
45 out.extend_from_slice(&transformation_kind);
46 out.extend_from_slice(&transformation_key_id);
47 out.extend_from_slice(&session_id);
48 out.extend_from_slice(&[0u8; 4]); out.extend_from_slice(&rtps_header_bytes[..RTPS_HEADER_LEN]);
50 Ok(out)
51}
52
53#[must_use]
57pub fn build_submessage_aad(
58 transformation_kind: [u8; 4],
59 transformation_key_id: [u8; 4],
60 session_id: [u8; 4],
61 sec_prefix_header_bytes: &[u8],
62) -> Vec<u8> {
63 let mut out = Vec::with_capacity(16 + sec_prefix_header_bytes.len());
64 out.extend_from_slice(&transformation_kind);
65 out.extend_from_slice(&transformation_key_id);
66 out.extend_from_slice(&session_id);
67 out.extend_from_slice(&[0u8; 4]); out.extend_from_slice(sec_prefix_header_bytes);
69 out
70}
71
72#[cfg(test)]
73#[allow(clippy::expect_used, clippy::unwrap_used, clippy::panic)]
74mod tests {
75 use super::*;
76
77 #[test]
78 fn rtps_header_aad_round_trip() {
79 let kind = [0, 0, 0, 0x02];
80 let key_id = [1, 2, 3, 4];
81 let sid = [10, 20, 30, 40];
82 let aad = build_rtps_header_aad(kind, key_id, sid, &[0xCAu8; 20]).unwrap();
83 assert_eq!(aad.len(), 16 + 20);
84 assert_eq!(&aad[0..4], &kind);
85 assert_eq!(&aad[4..8], &key_id);
86 assert_eq!(&aad[8..12], &sid);
87 assert_eq!(&aad[12..16], &[0, 0, 0, 0]);
88 assert_eq!(&aad[16..36], &[0xCA; 20]);
89 }
90
91 #[test]
92 fn rtps_header_aad_short_buffer_rejected() {
93 assert!(build_rtps_header_aad([0; 4], [0; 4], [0; 4], &[0; 10]).is_err());
94 }
95
96 #[test]
97 fn submessage_aad_includes_prefix_header() {
98 let aad = build_submessage_aad([0, 0, 0, 0x04], [1; 4], [2; 4], &[0xDE, 0xAD, 0xBE, 0xEF]);
99 assert_eq!(aad.len(), 16 + 4);
100 assert_eq!(&aad[16..20], &[0xDE, 0xAD, 0xBE, 0xEF]);
101 }
102
103 #[test]
104 fn rtps_header_len_matches_spec() {
105 assert_eq!(RTPS_HEADER_LEN, 20);
107 }
108
109 #[test]
110 fn aad_changes_with_kind() {
111 let aad1 = build_rtps_header_aad([0, 0, 0, 2], [0; 4], [0; 4], &[0; 20]).unwrap();
112 let aad2 = build_rtps_header_aad([0, 0, 0, 4], [0; 4], [0; 4], &[0; 20]).unwrap();
113 assert_ne!(aad1, aad2);
114 }
115
116 #[test]
117 fn aad_changes_with_session_id() {
118 let aad1 = build_rtps_header_aad([0; 4], [0; 4], [1; 4], &[0; 20]).unwrap();
119 let aad2 = build_rtps_header_aad([0; 4], [0; 4], [2; 4], &[0; 20]).unwrap();
120 assert_ne!(aad1, aad2);
121 }
122
123 #[test]
124 fn aad_changes_with_rtps_header_content() {
125 let aad1 = build_rtps_header_aad([0; 4], [0; 4], [0; 4], &[0xAA; 20]).unwrap();
126 let aad2 = build_rtps_header_aad([0; 4], [0; 4], [0; 4], &[0xBB; 20]).unwrap();
127 assert_ne!(aad1, aad2);
128 }
129}