leodos_protocols/datalink/security/sdls/
key.rs1use super::CryptoProvider;
10use super::Error;
11
12pub const MAX_KEY_LEN: usize = 32;
14
15pub const MAX_KEYS: usize = 128;
17
18#[derive(Debug, Copy, Clone, Eq, PartialEq)]
20pub enum KeyState {
21 Preactive,
23 Active,
25 Deactivated,
27 Destroyed,
29}
30
31#[derive(Clone)]
33pub struct ManagedKey {
34 pub key_id: u16,
36 pub state: KeyState,
38 pub material: [u8; MAX_KEY_LEN],
40 pub key_len: u8,
42}
43
44impl ManagedKey {
45 pub fn new(key_id: u16, material: &[u8]) -> Result<Self, Error> {
47 if material.is_empty() || material.len() > MAX_KEY_LEN {
48 return Err(Error::InvalidKeyLength);
49 }
50 let mut key = Self {
51 key_id,
52 state: KeyState::Preactive,
53 material: [0u8; MAX_KEY_LEN],
54 key_len: material.len() as u8,
55 };
56 key.material[..material.len()].copy_from_slice(material);
57 Ok(key)
58 }
59
60 pub fn activate(&mut self) -> Result<(), Error> {
62 (self.state == KeyState::Preactive)
63 .then(|| self.state = KeyState::Active)
64 .ok_or(Error::InvalidKeyState)
65 }
66
67 pub fn deactivate(&mut self) -> Result<(), Error> {
69 (self.state == KeyState::Active)
70 .then(|| self.state = KeyState::Deactivated)
71 .ok_or(Error::InvalidKeyState)
72 }
73
74 pub fn destroy(&mut self) {
76 self.material = [0u8; MAX_KEY_LEN];
77 self.key_len = 0;
78 self.state = KeyState::Destroyed;
79 }
80
81 pub fn material(&self) -> &[u8] {
83 &self.material[..self.key_len as usize]
84 }
85}
86
87pub struct KeyRing {
89 keys: heapless::Vec<ManagedKey, MAX_KEYS>,
90}
91
92impl KeyRing {
93 pub fn new() -> Self {
95 Self {
96 keys: heapless::Vec::new(),
97 }
98 }
99
100 pub fn load(&mut self, key_id: u16, material: &[u8]) -> Result<(), Error> {
102 if self.find(key_id).is_some() {
103 return Err(Error::DuplicateKeyId);
104 }
105 let key = ManagedKey::new(key_id, material)?;
106 self.keys.push(key).map_err(|_| Error::KeyRingFull)
107 }
108
109 pub fn find(&self, key_id: u16) -> Option<&ManagedKey> {
111 self.keys.iter().find(|k| k.key_id == key_id)
112 }
113
114 pub fn find_mut(&mut self, key_id: u16) -> Option<&mut ManagedKey> {
116 self.keys.iter_mut().find(|k| k.key_id == key_id)
117 }
118
119 pub fn activate(&mut self, key_id: u16) -> Result<(), Error> {
121 self.find_mut(key_id)
122 .ok_or(Error::UnknownKeyId(key_id))?
123 .activate()
124 }
125
126 pub fn deactivate(&mut self, key_id: u16) -> Result<(), Error> {
128 self.find_mut(key_id)
129 .ok_or(Error::UnknownKeyId(key_id))?
130 .deactivate()
131 }
132
133 pub fn destroy(&mut self, key_id: u16) -> Result<(), Error> {
135 self.find_mut(key_id)
136 .ok_or(Error::UnknownKeyId(key_id))?
137 .destroy();
138 Ok(())
139 }
140
141 pub fn otar(
150 &mut self,
151 master_key_id: u16,
152 iv: &[u8],
153 encrypted_block: &mut [u8],
154 tag: &[u8],
155 crypto: &impl CryptoProvider,
156 sa: &super::SecurityAssociation,
157 ) -> Result<usize, Error> {
158 let master = self
159 .find(master_key_id)
160 .ok_or(Error::UnknownKeyId(master_key_id))?;
161 if master.state != KeyState::Active {
162 return Err(Error::InvalidKeyState);
163 }
164
165 crypto.decrypt(sa, iv, &[], encrypted_block, tag)?;
166
167 let mut pos = 0;
168 let mut count = 0;
169 while pos + 4 <= encrypted_block.len() {
170 let key_id = u16::from_be_bytes([encrypted_block[pos], encrypted_block[pos + 1]]);
171 let key_len = u16::from_be_bytes([encrypted_block[pos + 2], encrypted_block[pos + 3]])
172 as usize;
173 pos += 4;
174 if pos + key_len > encrypted_block.len() {
175 break;
176 }
177 let material = &encrypted_block[pos..pos + key_len];
178 self.load(key_id, material)?;
179 pos += key_len;
180 count += 1;
181 }
182
183 Ok(count)
184 }
185
186 pub fn inventory(&self) -> impl Iterator<Item = (u16, KeyState)> + '_ {
188 self.keys.iter().map(|k| (k.key_id, k.state))
189 }
190
191 pub fn verify(
196 &self,
197 key_id: u16,
198 iv: &[u8],
199 challenge: &[u8],
200 response_out: &mut [u8],
201 tag_out: &mut [u8],
202 crypto: &impl CryptoProvider,
203 sa: &super::SecurityAssociation,
204 ) -> Result<(), Error> {
205 let key = self.find(key_id).ok_or(Error::UnknownKeyId(key_id))?;
206 if key.state != KeyState::Active {
207 return Err(Error::InvalidKeyState);
208 }
209 let len = challenge.len().min(response_out.len());
210 response_out[..len].copy_from_slice(&challenge[..len]);
211 crypto.encrypt(sa, iv, &[], &mut response_out[..len], tag_out)
212 .map(|_| ())
213 }
214}
215
216#[cfg(test)]
217mod tests {
218 use super::*;
219
220 #[test]
221 fn key_lifecycle() {
222 let mut key = ManagedKey::new(1, &[0xAA; 16]).unwrap();
223 assert_eq!(key.state, KeyState::Preactive);
224 assert_eq!(key.material(), &[0xAA; 16]);
225
226 assert!(key.deactivate().is_err());
227 key.activate().unwrap();
228 assert_eq!(key.state, KeyState::Active);
229
230 assert!(key.activate().is_err());
231 key.deactivate().unwrap();
232 assert_eq!(key.state, KeyState::Deactivated);
233
234 key.destroy();
235 assert_eq!(key.state, KeyState::Destroyed);
236 assert_eq!(key.key_len, 0);
237 }
238
239 #[test]
240 fn keyring_load_activate() {
241 let mut ring = KeyRing::new();
242 ring.load(1, &[0x42; 16]).unwrap();
243 ring.load(2, &[0x7F; 32]).unwrap();
244
245 assert!(ring.load(1, &[0x00; 16]).is_err());
246
247 ring.activate(1).unwrap();
248 assert_eq!(ring.find(1).unwrap().state, KeyState::Active);
249
250 assert!(ring.activate(99).is_err());
251 }
252
253 #[test]
254 fn keyring_destroy() {
255 let mut ring = KeyRing::new();
256 ring.load(5, &[0xFF; 16]).unwrap();
257 ring.destroy(5).unwrap();
258 assert_eq!(ring.find(5).unwrap().state, KeyState::Destroyed);
259 }
260
261 #[test]
262 fn keyring_inventory() {
263 let mut ring = KeyRing::new();
264 ring.load(1, &[0x11; 16]).unwrap();
265 ring.load(2, &[0x22; 16]).unwrap();
266 ring.activate(1).unwrap();
267
268 let inv: heapless::Vec<(u16, KeyState), MAX_KEYS> = ring.inventory().collect();
269 assert_eq!(inv.len(), 2);
270 assert_eq!(inv[0], (1, KeyState::Active));
271 assert_eq!(inv[1], (2, KeyState::Preactive));
272 }
273
274 #[test]
275 fn invalid_key_length() {
276 assert!(ManagedKey::new(1, &[]).is_err());
277 assert!(ManagedKey::new(1, &[0u8; 33]).is_err());
278 }
279}