use std::collections::HashMap;
use sframe::frame::{EncryptedFrameView, MediaFrameView, MonotonicCounter, ReplayAttackProtection};
use sframe::header::KeyId;
use sframe::key::{DecryptionKey, EncryptionKey};
use crate::error::SFrameError;
use crate::header::SFrameHeader;
use crate::kdf::CipherSuite;
const REPLAY_WINDOW: u64 = 1024;
pub struct SFrameEncryptor {
key: EncryptionKey,
counter: MonotonicCounter,
kid: KeyId,
}
impl SFrameEncryptor {
pub(crate) fn new(base_key: &[u8; 32], kid: u64, suite: CipherSuite) -> Self {
let key = EncryptionKey::derive_from(suite.to_sframe(), kid, base_key)
.expect("key derivation from a 32-byte base key never fails");
Self {
key,
counter: MonotonicCounter::default(),
kid,
}
}
pub fn encrypt(&mut self, plaintext: &[u8], extra_aad: &[u8]) -> Result<Vec<u8>, SFrameError> {
let frame = MediaFrameView::with_meta_data(&mut self.counter, plaintext, extra_aad);
let encrypted = frame.encrypt(&self.key).map_err(|_| SFrameError::Encrypt)?;
Ok(encrypted.as_ref()[extra_aad.len()..].to_vec())
}
pub fn counter(&self) -> u64 {
self.counter.current()
}
pub fn kid(&self) -> u64 {
self.kid
}
}
struct SenderState {
key: DecryptionKey,
replay: ReplayAttackProtection,
}
pub struct SFrameDecryptor {
base_key: [u8; 32],
epoch: u64,
suite: CipherSuite,
senders: HashMap<KeyId, SenderState>,
}
impl SFrameDecryptor {
pub(crate) fn new(base_key: [u8; 32], epoch: u64, suite: CipherSuite) -> Self {
Self {
base_key,
epoch,
suite,
senders: HashMap::new(),
}
}
pub fn decrypt(
&mut self,
payload: &[u8],
extra_aad: &[u8],
) -> Result<(Vec<u8>, u32), SFrameError> {
let view = EncryptedFrameView::try_with_meta_data(&payload, &extra_aad)
.map_err(|e| SFrameError::Header(e.to_string()))?;
let kid = view.header().key_id();
let ctr = view.header().counter();
if SFrameHeader::epoch_from_kid(kid) != SFrameHeader::epoch_lsb(self.epoch) {
return Err(SFrameError::UnknownKid(kid));
}
let leaf = SFrameHeader::leaf_from_kid(kid);
let suite = self.suite;
let base_key = self.base_key;
let state = self.senders.entry(kid).or_insert_with(|| SenderState {
key: DecryptionKey::derive_from(suite.to_sframe(), kid, base_key)
.expect("key derivation from a 32-byte base key never fails"),
replay: ReplayAttackProtection::with_tolerance(REPLAY_WINDOW),
});
let view = view
.validate(&state.replay)
.map_err(|_| SFrameError::Replay { kid, ctr })?;
let media = view.decrypt(&state.key).map_err(|_| SFrameError::Decrypt)?;
Ok((media.payload().to_vec(), leaf))
}
pub fn reset(&mut self) {
self.senders.clear();
}
}