use std::any::Any;
use std::cell::{Cell, RefCell};
use vitaminc_protected::{Controlled, Protected};
use crate::{
cipher::{Cipher, MapCipher, SeqCipher},
decipher::{Decipher, DecipherVisitor, MapAccess},
ContextPiece, Encrypt, IntoAad, Unspecified,
};
pub(crate) struct MockCipher {
captured_aad: RefCell<Vec<u8>>,
array_entry_hits: Cell<usize>,
}
impl MockCipher {
pub(crate) fn new() -> Self {
MockCipher {
captured_aad: RefCell::new(Vec::new()),
array_entry_hits: Cell::new(0),
}
}
pub(crate) fn captured_aad(&self) -> Vec<u8> {
self.captured_aad.borrow().clone()
}
fn capture<'a, A: IntoAad<'a>>(&self, aad: A) {
*self.captured_aad.borrow_mut() = aad.into_aad().as_bytes().to_vec();
}
pub(crate) fn array_entry_hits(&self) -> usize {
self.array_entry_hits.get()
}
}
pub(crate) struct PartsCipher {
captured_piece: RefCell<Option<ContextPiece<'static>>>,
}
impl PartsCipher {
pub(crate) fn new() -> Self {
PartsCipher {
captured_piece: RefCell::new(None),
}
}
pub(crate) fn captured_piece(&self) -> Option<ContextPiece<'static>> {
self.captured_piece.borrow().clone()
}
fn capture<'a, A: IntoAad<'a>>(&self, aad: A) {
*self.captured_piece.borrow_mut() = Some(aad.into_context().into_owned());
}
}
impl Cipher for &PartsCipher {
type Ok = Vec<u8>;
type Error = Unspecified;
type Passthrough = ();
type SeqCipher = UnusedSeq;
type MapCipher = UnusedMap;
fn encrypt_bytes_vec<'a, A>(
self,
data: Protected<Vec<u8>>,
aad: A,
) -> Result<Self::Ok, Self::Error>
where
A: IntoAad<'a>,
{
self.capture(aad);
Ok(data.risky_unwrap())
}
fn encrypt_seq<'a, A>(self, _size_hint: Option<usize>, _aad: A) -> Self::SeqCipher
where
A: IntoAad<'a>,
{
UnusedSeq
}
fn encrypt_map<'a, A>(self, _aad: A) -> Self::MapCipher
where
A: IntoAad<'a>,
{
UnusedMap
}
fn encrypt_none<'a, A>(self, aad: A) -> Result<Self::Ok, Self::Error>
where
A: IntoAad<'a>,
{
self.capture(aad);
Ok(Vec::new())
}
fn passthrough(self, _value: Self::Passthrough) -> Result<Self::Ok, Self::Error> {
Ok(Vec::new())
}
fn passthrough_boxed(
self,
_value: Box<dyn Any + Send + 'static>,
) -> Result<Self::Ok, Self::Error> {
Ok(Vec::new())
}
}
pub(crate) struct UnusedSeq;
pub(crate) struct UnusedMap;
impl Cipher for &MockCipher {
type Ok = Vec<u8>;
type Error = Unspecified;
type Passthrough = ();
type SeqCipher = UnusedSeq;
type MapCipher = UnusedMap;
fn encrypt_bytes_vec<'a, A>(
self,
data: Protected<Vec<u8>>,
aad: A,
) -> Result<Self::Ok, Self::Error>
where
A: IntoAad<'a>,
{
self.capture(aad);
Ok(data.risky_unwrap())
}
fn encrypt_bytes_array<'a, const N: usize, A>(
self,
data: Protected<[u8; N]>,
aad: A,
) -> Result<Self::Ok, Self::Error>
where
A: IntoAad<'a>,
{
self.array_entry_hits.set(self.array_entry_hits.get() + 1);
self.capture(aad);
Ok(data.risky_ref().to_vec())
}
fn encrypt_seq<'a, A>(self, _size_hint: Option<usize>, _aad: A) -> Self::SeqCipher
where
A: IntoAad<'a>,
{
UnusedSeq
}
fn encrypt_map<'a, A>(self, _aad: A) -> Self::MapCipher
where
A: IntoAad<'a>,
{
UnusedMap
}
fn encrypt_none<'a, A>(self, aad: A) -> Result<Self::Ok, Self::Error>
where
A: IntoAad<'a>,
{
self.capture(aad);
Ok(Vec::new())
}
fn passthrough(self, _value: Self::Passthrough) -> Result<Self::Ok, Self::Error> {
Ok(Vec::new())
}
fn passthrough_boxed(
self,
_value: Box<dyn Any + Send + 'static>,
) -> Result<Self::Ok, Self::Error> {
Ok(Vec::new())
}
}
impl SeqCipher for UnusedSeq {
type Ok = Vec<u8>;
type Error = Unspecified;
type Passthrough = ();
fn encrypt_next<T>(self, _data: T) -> Result<Self, Self::Error>
where
T: Encrypt,
{
Ok(self)
}
fn passthrough_next(self, _value: Self::Passthrough) -> Result<Self, Self::Error> {
Ok(self)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Vec::new())
}
}
impl MapCipher for UnusedMap {
type Ok = Vec<u8>;
type Error = Unspecified;
type Passthrough = ();
fn encrypt_key<K>(self, _key: K) -> Result<Self, Self::Error>
where
K: Into<std::borrow::Cow<'static, str>>,
{
Ok(self)
}
fn encrypt_value<T>(self, _value: T) -> Result<Self, Self::Error>
where
T: Encrypt,
{
Ok(self)
}
fn passthrough_entry<K>(self, _key: K, _value: Self::Passthrough) -> Result<Self, Self::Error>
where
K: Into<std::borrow::Cow<'static, str>>,
{
Ok(self)
}
fn passthrough_entry_boxed<K>(
self,
_key: K,
_value: Box<dyn std::any::Any + Send + 'static>,
) -> Result<Self, Self::Error>
where
K: Into<std::borrow::Cow<'static, str>>,
{
Ok(self)
}
fn end(self) -> Result<Self::Ok, Self::Error> {
Ok(Vec::new())
}
}
pub(crate) struct MockDefaultCipher {
captured_aad: RefCell<Vec<u8>>,
}
impl MockDefaultCipher {
pub(crate) fn new() -> Self {
MockDefaultCipher {
captured_aad: RefCell::new(Vec::new()),
}
}
}
impl Cipher for &MockDefaultCipher {
type Ok = Vec<u8>;
type Error = Unspecified;
type Passthrough = ();
type SeqCipher = UnusedSeq;
type MapCipher = UnusedMap;
fn encrypt_bytes_vec<'a, A>(
self,
data: Protected<Vec<u8>>,
aad: A,
) -> Result<Self::Ok, Self::Error>
where
A: IntoAad<'a>,
{
*self.captured_aad.borrow_mut() = aad.into_aad().as_bytes().to_vec();
Ok(data.risky_unwrap())
}
fn encrypt_seq<'a, A>(self, _size_hint: Option<usize>, _aad: A) -> Self::SeqCipher
where
A: IntoAad<'a>,
{
UnusedSeq
}
fn encrypt_map<'a, A>(self, _aad: A) -> Self::MapCipher
where
A: IntoAad<'a>,
{
UnusedMap
}
fn encrypt_none<'a, A>(self, aad: A) -> Result<Self::Ok, Self::Error>
where
A: IntoAad<'a>,
{
*self.captured_aad.borrow_mut() = aad.into_aad().as_bytes().to_vec();
Ok(Vec::new())
}
fn passthrough(self, _value: Self::Passthrough) -> Result<Self::Ok, Self::Error> {
Ok(Vec::new())
}
fn passthrough_boxed(
self,
_value: Box<dyn Any + Send + 'static>,
) -> Result<Self::Ok, Self::Error> {
Ok(Vec::new())
}
}
pub(crate) struct MockDecipher {
payload: Vec<u8>,
captured_aad: RefCell<Vec<u8>>,
}
impl MockDecipher {
pub(crate) fn new(payload: impl Into<Vec<u8>>) -> Self {
MockDecipher {
payload: payload.into(),
captured_aad: RefCell::new(Vec::new()),
}
}
pub(crate) fn captured_aad(&self) -> Vec<u8> {
self.captured_aad.borrow().clone()
}
}
impl<'c> Decipher<'c> for &MockDecipher {
type Ok<T>
= Result<T, Unspecified>
where
T: Send + 'c;
type Passthrough = ();
fn map_ok<T, U, F>(ok: Self::Ok<T>, f: F) -> Self::Ok<U>
where
T: Send + 'c,
U: Send + 'c,
F: FnOnce(T) -> U,
{
ok.map(f)
}
fn decrypt_bytes<'a, V, A>(self, visitor: V, aad: A) -> Self::Ok<V::Value>
where
V: DecipherVisitor<'c> + Send + 'c,
A: IntoAad<'a>,
{
*self.captured_aad.borrow_mut() = aad.into_aad().as_bytes().to_vec();
visitor.visit_bytes_vec(Protected::new(self.payload.clone()))
}
fn decrypt_seq<'a, V, A>(self, _visitor: V, aad: A) -> Self::Ok<V::Value>
where
V: DecipherVisitor<'c> + Send + 'c,
A: IntoAad<'a>,
{
*self.captured_aad.borrow_mut() = aad.into_aad().as_bytes().to_vec();
Err(Unspecified)
}
fn decrypt_map<'a, V, A>(self, _visitor: V, aad: A) -> Self::Ok<V::Value>
where
V: DecipherVisitor<'c> + Send + 'c,
A: IntoAad<'a>,
{
*self.captured_aad.borrow_mut() = aad.into_aad().as_bytes().to_vec();
Err(Unspecified)
}
fn decrypt_any<'a, V, A>(self, _visitor: V, aad: A) -> Self::Ok<V::Value>
where
V: DecipherVisitor<'c> + Send + 'c,
A: IntoAad<'a>,
{
*self.captured_aad.borrow_mut() = aad.into_aad().as_bytes().to_vec();
Err(Unspecified)
}
fn decrypt_passthrough(self) -> Self::Ok<Self::Passthrough> {
Err(Unspecified)
}
fn decrypt_option<'a, T, A>(self, aad: A) -> Self::Ok<Option<T>>
where
T: crate::Decrypt<'c> + 'c,
A: IntoAad<'a>,
{
*self.captured_aad.borrow_mut() = aad.into_aad().as_bytes().to_vec();
Err(Unspecified)
}
}
pub(crate) struct MockMapAccess {
entries: std::vec::IntoIter<(String, Vec<u8>)>,
pending: Option<Vec<u8>>,
}
impl MockMapAccess {
pub(crate) fn new<K, V>(entries: impl IntoIterator<Item = (K, V)>) -> Self
where
K: Into<String>,
V: Into<Vec<u8>>,
{
MockMapAccess {
entries: entries
.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.collect::<Vec<_>>()
.into_iter(),
pending: None,
}
}
}
impl<'c> MapAccess<'c> for MockMapAccess {
type Error = Unspecified;
fn next_key(&mut self) -> Result<Option<String>, Self::Error> {
if self.pending.is_some() {
return Err(Unspecified);
}
match self.entries.next() {
Some((key, payload)) => {
self.pending = Some(payload);
Ok(Some(key))
}
None => Ok(None),
}
}
fn next_value<T: crate::Decrypt<'c> + 'c>(&mut self) -> Result<T, Self::Error> {
let payload = self.pending.take().ok_or(Unspecified)?;
let decipher = MockDecipher::new(payload);
T::decrypt_with_aad(&decipher, crate::Context::empty())
}
}