leodos_protocols/datalink/security/
mod.rs1use core::convert::Infallible;
8
9use sdls::{CryptoProvider, SecurityAssociation};
10
11pub mod sdls;
13
14pub trait SecurityProcessor {
16 type Error;
18 fn apply(
20 &mut self,
21 frame: &mut [u8],
22 ) -> Result<usize, Self::Error>;
23 fn process(
25 &mut self,
26 frame: &mut [u8],
27 ) -> Result<usize, Self::Error>;
28}
29
30pub struct SdlsProcessor<C> {
40 sa: SecurityAssociation,
41 crypto: C,
42 header_end: usize,
43}
44
45impl<C: CryptoProvider> SdlsProcessor<C> {
46 pub fn new(
51 sa: SecurityAssociation,
52 crypto: C,
53 header_end: usize,
54 ) -> Self {
55 Self {
56 sa,
57 crypto,
58 header_end,
59 }
60 }
61
62 pub fn sa(&self) -> &SecurityAssociation {
64 &self.sa
65 }
66
67 pub fn sa_mut(&mut self) -> &mut SecurityAssociation {
69 &mut self.sa
70 }
71}
72
73impl<C: CryptoProvider> SecurityProcessor for SdlsProcessor<C> {
74 type Error = sdls::Error;
75
76 fn apply(
77 &mut self,
78 frame: &mut [u8],
79 ) -> Result<usize, Self::Error> {
80 let data_start = self.header_end + self.sa.header_size();
81 let data_end = frame.len() - self.sa.trailer_size();
82 sdls::apply_security(
83 &mut self.sa,
84 &self.crypto,
85 frame,
86 self.header_end,
87 data_start,
88 data_end,
89 )?;
90 Ok(frame.len())
91 }
92
93 fn process(
94 &mut self,
95 frame: &mut [u8],
96 ) -> Result<usize, Self::Error> {
97 let data_start = self.header_end + self.sa.header_size();
98 let data_end = frame.len() - self.sa.trailer_size();
99 sdls::process_security(
100 &mut self.sa,
101 &self.crypto,
102 frame,
103 self.header_end,
104 data_start,
105 data_end,
106 )?;
107 Ok(frame.len())
108 }
109}
110
111pub struct NoSecurity;
115
116impl SecurityProcessor for NoSecurity {
117 type Error = Infallible;
118
119 fn apply(
120 &mut self,
121 frame: &mut [u8],
122 ) -> Result<usize, Self::Error> {
123 Ok(frame.len())
124 }
125
126 fn process(
127 &mut self,
128 frame: &mut [u8],
129 ) -> Result<usize, Self::Error> {
130 Ok(frame.len())
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137 use sdls::{
138 AesGcmCrypto, ClearModeCrypto, SecurityAssociation,
139 ServiceType,
140 };
141
142 fn auth_sa() -> SecurityAssociation {
143 SecurityAssociation {
144 spi: 1,
145 service_type: ServiceType::Authentication,
146 iv_len: 4,
147 sn_len: 4,
148 pl_len: 0,
149 mac_len: 16,
150 sequence_number: 0,
151 sequence_window: 100,
152 auth_mask: heapless::Vec::new(),
153 }
154 }
155
156 fn aead_sa() -> SecurityAssociation {
157 SecurityAssociation {
158 spi: 5,
159 service_type: ServiceType::AuthenticatedEncryption,
160 iv_len: 12,
161 sn_len: 0,
162 pl_len: 0,
163 mac_len: 16,
164 sequence_number: 1,
165 sequence_window: 100,
166 auth_mask: heapless::Vec::new(),
167 }
168 }
169
170 #[test]
171 fn no_security_passthrough() {
172 let mut processor = NoSecurity;
173 let mut frame = [0xAA; 32];
174 let len = processor.apply(&mut frame).unwrap();
175 assert_eq!(len, 32);
176 assert!(frame.iter().all(|&b| b == 0xAA));
177 }
178
179 #[test]
180 fn sdls_clear_mode_roundtrip() {
181 let sa = auth_sa();
182 let header_end = 5;
183 let data_start = header_end + sa.header_size();
184 let data_end = data_start + 10;
185 let total = data_end + sa.trailer_size();
186
187 let mut send =
188 SdlsProcessor::new(sa.clone(), ClearModeCrypto, header_end);
189 let mut recv =
190 SdlsProcessor::new(sa, ClearModeCrypto, header_end);
191
192 let mut frame = [0u8; 64];
193 frame[0..5].copy_from_slice(&[0xC0, 0x00, 0x2A, 0x00, 0x28]);
194 frame[data_start..data_end]
195 .copy_from_slice(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
196
197 let len = send.apply(&mut frame[..total]).unwrap();
198 assert_eq!(len, total);
199
200 let len = recv.process(&mut frame[..total]).unwrap();
201 assert_eq!(len, total);
202 assert_eq!(
203 &frame[data_start..data_end],
204 &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
205 );
206 }
207
208 #[test]
209 fn sdls_aes_gcm_roundtrip() {
210 let sa = aead_sa();
211 let header_end = 5;
212 let data_start = header_end + sa.header_size();
213 let data_end = data_start + 8;
214 let total = data_end + sa.trailer_size();
215
216 let key = [0xABu8; 16];
217
218 let mut send = SdlsProcessor::new(
219 sa.clone(),
220 AesGcmCrypto::new_128(&key),
221 header_end,
222 );
223 let mut recv = SdlsProcessor::new(
224 sa,
225 AesGcmCrypto::new_128(&key),
226 header_end,
227 );
228
229 let mut frame = [0u8; 64];
230 frame[0..5].copy_from_slice(&[0xC0, 0x00, 0x2A, 0x00, 0x28]);
231 let original = [1u8, 2, 3, 4, 5, 6, 7, 8];
232 frame[data_start..data_end].copy_from_slice(&original);
233
234 send.apply(&mut frame[..total]).unwrap();
235 assert_ne!(&frame[data_start..data_end], &original);
236
237 recv.process(&mut frame[..total]).unwrap();
238 assert_eq!(&frame[data_start..data_end], &original);
239 }
240}