Skip to main content

osdp/command/
chlng.rs

1//! `osdp_CHLNG` (`0x76`) โ€” initiate Secure Channel session.
2//!
3//! # Spec: ยง6.17, Annex D.4
4//!
5//! Body is `RND.A` โ€” an 8-byte random challenge generated by the ACU.
6//! The packet must carry an SCB of type `SCS_11`.
7
8use crate::error::Error;
9use crate::payload_util::require_exact_len;
10use alloc::vec::Vec;
11
12/// `osdp_CHLNG` body.
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub struct Chlng {
15    /// `RND.A` โ€” 8 random bytes from the ACU.
16    pub rnd_a: [u8; 8],
17}
18
19impl Chlng {
20    /// New with the given `RND.A`.
21    pub const fn new(rnd_a: [u8; 8]) -> Self {
22        Self { rnd_a }
23    }
24
25    /// Encode.
26    pub fn encode(&self) -> Result<Vec<u8>, Error> {
27        Ok(self.rnd_a.to_vec())
28    }
29
30    /// Decode.
31    pub fn decode(data: &[u8]) -> Result<Self, Error> {
32        require_exact_len(data, 8, 0x76)?;
33        let mut rnd_a = [0u8; 8];
34        rnd_a.copy_from_slice(data);
35        Ok(Self { rnd_a })
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn roundtrip() {
45        let body = Chlng::new([0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88]);
46        let bytes = body.encode().unwrap();
47        assert_eq!(bytes.len(), 8);
48        assert_eq!(Chlng::decode(&bytes).unwrap(), body);
49    }
50
51    #[test]
52    fn decode_rejects_wrong_length() {
53        assert!(matches!(
54            Chlng::decode(&[0; 7]),
55            Err(Error::PayloadLength { code: 0x76, .. })
56        ));
57        assert!(matches!(
58            Chlng::decode(&[0; 9]),
59            Err(Error::PayloadLength { code: 0x76, .. })
60        ));
61    }
62}