1use crate::error::Error;
8use crate::payload_util::require_exact_len;
9use alloc::vec::Vec;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub struct CCrypt {
14 pub cuid: [u8; 8],
16 pub rnd_b: [u8; 8],
18 pub client_cryptogram: [u8; 16],
20}
21
22impl CCrypt {
23 pub fn encode(&self) -> Result<Vec<u8>, Error> {
25 let mut out = Vec::with_capacity(32);
26 out.extend_from_slice(&self.cuid);
27 out.extend_from_slice(&self.rnd_b);
28 out.extend_from_slice(&self.client_cryptogram);
29 Ok(out)
30 }
31
32 pub fn decode(data: &[u8]) -> Result<Self, Error> {
34 require_exact_len(data, 32, 0x76)?;
35 let mut cuid = [0u8; 8];
36 cuid.copy_from_slice(&data[..8]);
37 let mut rnd_b = [0u8; 8];
38 rnd_b.copy_from_slice(&data[8..16]);
39 let mut client_cryptogram = [0u8; 16];
40 client_cryptogram.copy_from_slice(&data[16..32]);
41 Ok(Self {
42 cuid,
43 rnd_b,
44 client_cryptogram,
45 })
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn roundtrip() {
55 let body = CCrypt {
56 cuid: [0xAA; 8],
57 rnd_b: [0xBB; 8],
58 client_cryptogram: [0xCC; 16],
59 };
60 let bytes = body.encode().unwrap();
61 assert_eq!(bytes.len(), 32);
62 assert_eq!(&bytes[..8], &[0xAA; 8]);
63 assert_eq!(&bytes[8..16], &[0xBB; 8]);
64 assert_eq!(&bytes[16..32], &[0xCC; 16]);
65 assert_eq!(CCrypt::decode(&bytes).unwrap(), body);
66 }
67
68 #[test]
69 fn decode_rejects_wrong_length() {
70 assert!(matches!(
71 CCrypt::decode(&[0; 31]),
72 Err(Error::PayloadLength { code: 0x76, .. })
73 ));
74 }
75}