leodos_protocols/misc/sle/
isp1.rs1use super::types::SleError;
9
10pub const ISP1_HEADER_SIZE: usize = 4;
12
13pub struct Isp1Frame;
18
19impl Isp1Frame {
20 pub fn encode(
26 payload: &[u8],
27 buf: &mut [u8],
28 ) -> Result<usize, SleError> {
29 let total = ISP1_HEADER_SIZE + payload.len();
30 if buf.len() < total {
31 return Err(SleError::BufferTooSmall);
32 }
33 let len_bytes =
34 (payload.len() as u32).to_be_bytes();
35 buf[..4].copy_from_slice(&len_bytes);
36 buf[4..total].copy_from_slice(payload);
37 Ok(total)
38 }
39
40 pub fn decode_header(
47 buf: &[u8],
48 ) -> Result<(usize, usize), SleError> {
49 if buf.len() < ISP1_HEADER_SIZE {
50 return Err(SleError::Truncated);
51 }
52 let len = u32::from_be_bytes([
53 buf[0], buf[1], buf[2], buf[3],
54 ]) as usize;
55 Ok((len, ISP1_HEADER_SIZE))
56 }
57
58 pub fn decode(buf: &[u8]) -> Result<&[u8], SleError> {
61 let (payload_len, hdr) = Self::decode_header(buf)?;
62 let total = hdr + payload_len;
63 if buf.len() < total {
64 return Err(SleError::Truncated);
65 }
66 Ok(&buf[hdr..total])
67 }
68}
69
70#[derive(Copy, Clone, Debug, PartialEq, Eq)]
75pub struct Credentials {
76 pub time: [u8; 8],
78 pub random: u32,
80 pub hash: [u8; 20],
82}
83
84impl Credentials {
85 pub const SIZE: usize = 8 + 4 + 20;
87
88 pub fn encode(
91 &self,
92 buf: &mut [u8],
93 ) -> Result<usize, SleError> {
94 if buf.len() < Self::SIZE {
95 return Err(SleError::BufferTooSmall);
96 }
97 buf[..8].copy_from_slice(&self.time);
98 buf[8..12].copy_from_slice(&self.random.to_be_bytes());
99 buf[12..32].copy_from_slice(&self.hash);
100 Ok(Self::SIZE)
101 }
102
103 pub fn decode(buf: &[u8]) -> Result<(Self, usize), SleError> {
105 if buf.len() < Self::SIZE {
106 return Err(SleError::Truncated);
107 }
108 let mut time = [0u8; 8];
109 time.copy_from_slice(&buf[..8]);
110 let random = u32::from_be_bytes([
111 buf[8], buf[9], buf[10], buf[11],
112 ]);
113 let mut hash = [0u8; 20];
114 hash.copy_from_slice(&buf[12..32]);
115 Ok((Self { time, random, hash }, Self::SIZE))
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn isp1_frame_roundtrip() {
125 let payload = b"SLE RAF data";
126 let mut buf = [0u8; 64];
127 let n = Isp1Frame::encode(payload, &mut buf).unwrap();
128 assert_eq!(n, 4 + payload.len());
129
130 let decoded = Isp1Frame::decode(&buf[..n]).unwrap();
131 assert_eq!(decoded, payload);
132 }
133
134 #[test]
135 fn isp1_decode_header() {
136 let mut buf = [0u8; 4];
137 buf.copy_from_slice(&100u32.to_be_bytes());
138 let (len, consumed) =
139 Isp1Frame::decode_header(&buf).unwrap();
140 assert_eq!(len, 100);
141 assert_eq!(consumed, 4);
142 }
143
144 #[test]
145 fn credentials_roundtrip() {
146 let cred = Credentials {
147 time: [1, 2, 3, 4, 5, 6, 7, 8],
148 random: 0xDEADBEEF,
149 hash: [
150 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
151 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
152 0xB0, 0xB1, 0xB2, 0xB3,
153 ],
154 };
155 let mut buf = [0u8; 64];
156 let n = cred.encode(&mut buf).unwrap();
157 assert_eq!(n, Credentials::SIZE);
158
159 let (decoded, consumed) =
160 Credentials::decode(&buf[..n]).unwrap();
161 assert_eq!(consumed, n);
162 assert_eq!(decoded, cred);
163 }
164}