#![cfg(crypto_backend)]
use std::convert::Infallible;
use mockall::{Sequence, mock};
use pretty_assertions::assert_eq;
use sframe::{
error::SframeError,
frame::validation::{
FrameValidation, NoValidation, ReplayAttackProtection, Tolerance, UnvalidatedFrame,
},
header::KeyId,
};
mod common;
use common::{KEY_ID, PAYLOAD, encrypt_once, keys_of_sender, tamper_with};
mock! {
Validation {}
impl FrameValidation for Validation {
type Token = ();
type Error = Infallible;
fn screen<'a>(&self, unvalidated: UnvalidatedFrame<'a>) -> Result<(), Infallible>;
fn record(&mut self, token: ());
}
}
#[test]
fn decrypts_a_frame_a_validator_accepts() {
let (enc_key, dec_key) = keys_of_sender(KEY_ID);
let (media_frame, encrypted_frame) = encrypt_once(PAYLOAD, &enc_key);
let mut validator = NoValidation;
let decrypted_media_frame = encrypted_frame
.validated_decrypt(&dec_key, &mut validator)
.expect("Expected to decrypt and validate");
assert_eq!(decrypted_media_frame, media_frame);
}
#[test]
fn screens_a_frame_before_decryption_and_records_it_after() {
let (enc_key, dec_key) = keys_of_sender(KEY_ID);
let (_, encrypted_frame) = encrypt_once(PAYLOAD, &enc_key);
let mut order = Sequence::new();
let mut validator = MockValidation::new();
validator
.expect_screen()
.once()
.in_sequence(&mut order)
.returning(|_| Ok(()));
validator
.expect_record()
.once()
.in_sequence(&mut order)
.return_const(());
encrypted_frame
.validated_decrypt(&dec_key, &mut validator)
.expect("Expected to decrypt and validate");
}
#[test]
fn does_not_record_a_frame_which_did_not_decrypt() {
let (enc_key, dec_key) = keys_of_sender(KEY_ID);
let (_, encrypted_frame) = encrypt_once(PAYLOAD, &enc_key);
let tampered_frame = tamper_with(&encrypted_frame);
let mut validator = MockValidation::new();
validator.expect_screen().once().returning(|_| Ok(()));
validator.expect_record().never();
tampered_frame
.validated_decrypt(&dec_key, &mut validator)
.unwrap_err();
}
#[test]
fn a_frame_which_does_not_decrypt_leaves_the_replay_window_untouched() {
let (enc_key, dec_key) = keys_of_sender(KEY_ID);
let (media_frame, genuine_frame) = encrypt_once(PAYLOAD, &enc_key);
let tampered_frame = tamper_with(&genuine_frame);
let mut validator = ReplayAttackProtection::new(KeyId::from(KEY_ID), Tolerance::new(128));
let error = tampered_frame
.validated_decrypt(&dec_key, &mut validator)
.unwrap_err();
assert!(matches!(error, SframeError::DecryptionFailure));
let decrypted = genuine_frame
.validated_decrypt(&dec_key, &mut validator)
.expect("Expected the genuine frame to still decrypt");
assert_eq!(decrypted, media_frame);
}