1use std::collections::HashMap;
2
3use sframe::frame::{EncryptedFrameView, MediaFrameView, MonotonicCounter, ReplayAttackProtection};
4use sframe::header::KeyId;
5use sframe::key::{DecryptionKey, EncryptionKey};
6
7use crate::error::SFrameError;
8use crate::header::SFrameHeader;
9use crate::kdf::CipherSuite;
10
11const REPLAY_WINDOW: u64 = 1024;
13
14pub struct SFrameEncryptor {
23 key: EncryptionKey,
24 counter: MonotonicCounter,
25 kid: KeyId,
26}
27
28impl SFrameEncryptor {
29 pub(crate) fn new(base_key: &[u8; 32], kid: u64, suite: CipherSuite) -> Self {
30 let key = EncryptionKey::derive_from(suite.to_sframe(), kid, base_key)
31 .expect("key derivation from a 32-byte base key never fails");
32 Self {
33 key,
34 counter: MonotonicCounter::default(),
35 kid,
36 }
37 }
38
39 pub fn encrypt(&mut self, plaintext: &[u8], extra_aad: &[u8]) -> Result<Vec<u8>, SFrameError> {
46 let frame = MediaFrameView::with_meta_data(&mut self.counter, plaintext, extra_aad);
47 let encrypted = frame.encrypt(&self.key).map_err(|_| SFrameError::Encrypt)?;
48
49 Ok(encrypted.as_ref()[extra_aad.len()..].to_vec())
52 }
53
54 pub fn counter(&self) -> u64 {
56 self.counter.current()
57 }
58
59 pub fn kid(&self) -> u64 {
61 self.kid
62 }
63}
64
65struct SenderState {
73 key: DecryptionKey,
74 replay: ReplayAttackProtection,
75}
76
77pub struct SFrameDecryptor {
84 base_key: [u8; 32],
85 epoch: u64,
86 suite: CipherSuite,
87 senders: HashMap<KeyId, SenderState>,
89}
90
91impl SFrameDecryptor {
92 pub(crate) fn new(base_key: [u8; 32], epoch: u64, suite: CipherSuite) -> Self {
93 Self {
94 base_key,
95 epoch,
96 suite,
97 senders: HashMap::new(),
98 }
99 }
100
101 pub fn decrypt(
105 &mut self,
106 payload: &[u8],
107 extra_aad: &[u8],
108 ) -> Result<(Vec<u8>, u32), SFrameError> {
109 let view = EncryptedFrameView::try_with_meta_data(&payload, &extra_aad)
110 .map_err(|e| SFrameError::Header(e.to_string()))?;
111
112 let kid = view.header().key_id();
113 let ctr = view.header().counter();
114
115 if SFrameHeader::epoch_from_kid(kid) != SFrameHeader::epoch_lsb(self.epoch) {
116 return Err(SFrameError::UnknownKid(kid));
117 }
118 let leaf = SFrameHeader::leaf_from_kid(kid);
119
120 let suite = self.suite;
121 let base_key = self.base_key;
122 let state = self.senders.entry(kid).or_insert_with(|| SenderState {
123 key: DecryptionKey::derive_from(suite.to_sframe(), kid, base_key)
124 .expect("key derivation from a 32-byte base key never fails"),
125 replay: ReplayAttackProtection::with_tolerance(REPLAY_WINDOW),
126 });
127
128 let view = view
130 .validate(&state.replay)
131 .map_err(|_| SFrameError::Replay { kid, ctr })?;
132
133 let media = view.decrypt(&state.key).map_err(|_| SFrameError::Decrypt)?;
134 Ok((media.payload().to_vec(), leaf))
135 }
136
137 pub fn reset(&mut self) {
139 self.senders.clear();
140 }
141}