1use crate::crypto::{self, CanonAeadKey, CanonAeadKeyRef, Crypto, Kdf};
19use crate::error::{Error, ErrorCode};
20use crate::tlv::{FromTLV, ToTLV};
21use crate::utils::init::{init, Init};
22use crate::utils::storage::Vec;
23
24pub const GROUP_MAX_EPOCH_KEYS: usize = 3;
25
26#[derive(Debug, Clone, Default, FromTLV, ToTLV)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))]
29pub struct GroupEpochKeyEntry {
30 pub epoch_key: CanonAeadKey,
31 pub epoch_start_time: u64,
32}
33
34#[derive(Debug, Clone, Default, FromTLV, ToTLV)]
36#[cfg_attr(feature = "defmt", derive(defmt::Format))]
37pub struct GroupKeySet {
38 pub group_key_set_id: u16,
39 pub group_key_security_policy: u8,
40 pub epoch_keys: Vec<GroupEpochKeyEntry, GROUP_MAX_EPOCH_KEYS>,
41}
42
43#[derive(Debug, Default, FromTLV, ToTLV)]
44#[cfg_attr(feature = "defmt", derive(defmt::Format))]
45pub struct KeySet {
46 pub epoch_key: CanonAeadKey,
47 pub op_key: CanonAeadKey,
48}
49
50impl KeySet {
51 pub const fn new() -> Self {
52 Self {
53 epoch_key: crypto::AEAD_KEY_ZEROED,
54 op_key: crypto::AEAD_KEY_ZEROED,
55 }
56 }
57
58 pub fn init() -> impl Init<Self> {
59 init!(Self {
60 epoch_key <- CanonAeadKey::init(),
61 op_key <- CanonAeadKey::init(),
62 })
63 }
64
65 pub fn update<C: Crypto>(
66 &mut self,
67 crypto: C,
68 epoch_key: CanonAeadKeyRef<'_>,
69 compressed_fabric_id: &u64,
70 ) -> Result<(), Error> {
71 const GRP_KEY_INFO: &[u8] = &[
72 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4b, 0x65, 0x79, 0x20, 0x76, 0x31, 0x2e, 0x30,
73 ];
74
75 crypto
76 .kdf()?
77 .expand(
78 &compressed_fabric_id.to_be_bytes(),
79 epoch_key,
80 GRP_KEY_INFO,
81 &mut self.op_key,
82 )
83 .map_err(|_| ErrorCode::InvalidData)?;
84
85 self.epoch_key.load(epoch_key);
86
87 Ok(())
88 }
89
90 pub fn op_key(&self) -> CanonAeadKeyRef<'_> {
91 self.op_key.reference()
92 }
93
94 pub fn epoch_key(&self) -> CanonAeadKeyRef<'_> {
95 self.epoch_key.reference()
96 }
97}