Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto-common: add SerializableState trait #1369

Merged
merged 9 commits into from
Nov 18, 2023
17 changes: 16 additions & 1 deletion crypto-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,20 @@ pub use hybrid_array as array;
pub use hybrid_array::typenum;

use core::fmt;
use hybrid_array::{typenum::Unsigned, Array, ArraySize, ByteArray};
use hybrid_array::{
typenum::{Diff, Sum, Unsigned},
Array, ArraySize, ByteArray,
};

#[cfg(feature = "rand_core")]
use rand_core::CryptoRngCore;

mod serializable_state;
pub use serializable_state::{
AddSerializedStateSize, DeserializeStateError, SerializableState, SerializedState,
SubSerializedStateSize,
};

/// Block on which [`BlockSizeUser`] implementors operate.
pub type Block<B> = ByteArray<<B as BlockSizeUser>::BlockSize>;

Expand All @@ -41,6 +50,12 @@ pub type Key<B> = ByteArray<<B as KeySizeUser>::KeySize>;
/// Initialization vector (nonce) used by [`IvSizeUser`] implementors.
pub type Iv<B> = ByteArray<<B as IvSizeUser>::IvSize>;

/// Alias for `AddBlockSize<A, B> = Sum<T, B::BlockSize>`
pub type AddBlockSize<T, B> = Sum<T, <B as BlockSizeUser>::BlockSize>;

/// Alias for `SubBlockSize<A, B> = Diff<T, B::BlockSize>`
pub type SubBlockSize<T, B> = Diff<T, <B as BlockSizeUser>::BlockSize>;

/// Types which process data in blocks.
pub trait BlockSizeUser {
/// Size of the block in bytes.
Expand Down
351 changes: 351 additions & 0 deletions crypto-common/src/serializable_state.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,351 @@
use crate::array::{
self,
typenum::{Diff, Prod, Sum, Unsigned, U1, U16, U2, U4, U8},
ArraySize, ByteArray,
};
use core::{convert::TryInto, default::Default, fmt};

/// Serialized internal state.
pub type SerializedState<T> = ByteArray<<T as SerializableState>::SerializedStateSize>;

/// Alias for `AddSerializedStateSize<T, S> = Sum<T, S::SerializedStateSize>`
pub type AddSerializedStateSize<T, S> = Sum<T, <S as SerializableState>::SerializedStateSize>;

/// Alias for `SubSerializedStateSize<T, S> = Diff<T, S::SerializedStateSize>`
pub type SubSerializedStateSize<T, S> = Diff<T, <S as SerializableState>::SerializedStateSize>;

/// The error type returned when an object cannot be deserialized from the state.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct DeserializeStateError;

impl fmt::Display for DeserializeStateError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.write_str("Deserialization error")
}
}

#[cfg(feature = "std")]
impl std::error::Error for DeserializeStateError {}

/// Types which can serialize the internal state and be restored from it.
///
/// # SECURITY WARNING
///
/// Serialized state may contain sensitive data.
pub trait SerializableState
where
Self: Sized,
{
/// Size of serialized internal state.
type SerializedStateSize: ArraySize;

/// Serialize and return internal state.
fn serialize(&self) -> SerializedState<Self>;
/// Create an object from serialized internal state.
fn deserialize(serialized_state: &SerializedState<Self>)
-> Result<Self, DeserializeStateError>;
}

macro_rules! impl_seializable_state_unsigned {
($type: ty, $type_size: ty) => {
impl SerializableState for $type {
type SerializedStateSize = $type_size;

fn serialize(&self) -> SerializedState<Self> {
self.to_le_bytes().into()
}

fn deserialize(
serialized_state: &SerializedState<Self>,
) -> Result<Self, DeserializeStateError> {
Ok(<$type>::from_le_bytes((*serialized_state).into()))
}
}
};
}

impl_seializable_state_unsigned!(u8, U1);
impl_seializable_state_unsigned!(u16, U2);
impl_seializable_state_unsigned!(u32, U4);
impl_seializable_state_unsigned!(u64, U8);
impl_seializable_state_unsigned!(u128, U16);

macro_rules! impl_serializable_state_u8_array {
($($n: ty),*) => {
$(
impl SerializableState for [u8; <$n>::USIZE] {
type SerializedStateSize = $n;

fn serialize(&self) -> SerializedState<Self> {
(*self).into()
}

fn deserialize(
serialized_state: &SerializedState<Self>,
) -> Result<Self, DeserializeStateError> {
Ok((*serialized_state).into())
}
}
)*
};
}

macro_rules! impl_serializable_state_type_array {
($type: ty, $type_size: ty, $n: ty) => {
impl SerializableState for [$type; <$n>::USIZE] {
type SerializedStateSize = Prod<$n, $type_size>;

fn serialize(&self) -> SerializedState<Self> {
let mut serialized_state = SerializedState::<Self>::default();
for (val, chunk) in self
.iter()
.zip(serialized_state.chunks_exact_mut(<$type_size>::USIZE))
{
chunk.copy_from_slice(&val.to_le_bytes());
}

serialized_state
}

fn deserialize(
serialized_state: &SerializedState<Self>,
) -> Result<Self, DeserializeStateError> {
let mut array = [0; <$n>::USIZE];
for (val, chunk) in array
.iter_mut()
.zip(serialized_state.chunks_exact(<$type_size>::USIZE))
{
*val = <$type>::from_le_bytes(chunk.try_into().unwrap());
}
Ok(array)
}
}
};
}

macro_rules! impl_serializable_state_u16_array {
($($n: ty),*) => {
$(
impl_serializable_state_type_array!(u16, U2, $n);
)*
};
}

macro_rules! impl_serializable_state_u32_array {
($($n: ty),*) => {
$(
impl_serializable_state_type_array!(u32, U4, $n);
)*
};
}

macro_rules! impl_serializable_state_u64_array {
($($n: ty),*) => {
$(
impl_serializable_state_type_array!(u64, U8, $n);
)*
};
}

macro_rules! impl_serializable_state_u128_array {
($($n: ty),*) => {
$(
impl_serializable_state_type_array!(u128, U8, $n);
)*
};
}

impl_serializable_state_u8_array! {
array::typenum::U1,
array::typenum::U2,
array::typenum::U3,
array::typenum::U4,
array::typenum::U5,
array::typenum::U6,
array::typenum::U7,
array::typenum::U8,
array::typenum::U9,
array::typenum::U10,
array::typenum::U11,
array::typenum::U12,
array::typenum::U13,
array::typenum::U14,
array::typenum::U15,
array::typenum::U16,
array::typenum::U17,
array::typenum::U18,
array::typenum::U19,
array::typenum::U20,
array::typenum::U21,
array::typenum::U22,
array::typenum::U23,
array::typenum::U24,
array::typenum::U25,
array::typenum::U26,
array::typenum::U27,
array::typenum::U28,
array::typenum::U29,
array::typenum::U30,
array::typenum::U31,
array::typenum::U32,
array::typenum::U33,
array::typenum::U34,
array::typenum::U35,
array::typenum::U36,
array::typenum::U37,
array::typenum::U38,
array::typenum::U39,
array::typenum::U40,
array::typenum::U41,
array::typenum::U42,
array::typenum::U43,
array::typenum::U44,
array::typenum::U45,
array::typenum::U46,
array::typenum::U47,
array::typenum::U48,
array::typenum::U49,
array::typenum::U50,
array::typenum::U51,
array::typenum::U52,
array::typenum::U53,
array::typenum::U54,
array::typenum::U55,
array::typenum::U56,
array::typenum::U57,
array::typenum::U58,
array::typenum::U59,
array::typenum::U60,
array::typenum::U61,
array::typenum::U62,
array::typenum::U63,
array::typenum::U64,
array::typenum::U96,
array::typenum::U128,
array::typenum::U192,
array::typenum::U256,
array::typenum::U384,
array::typenum::U448,
array::typenum::U512,
array::typenum::U768,
array::typenum::U896,
array::typenum::U1024,
array::typenum::U2048,
array::typenum::U4096,
array::typenum::U8192
}

impl_serializable_state_u16_array! {
array::typenum::U1,
array::typenum::U2,
array::typenum::U3,
array::typenum::U4,
array::typenum::U5,
array::typenum::U6,
array::typenum::U7,
array::typenum::U8,
array::typenum::U9,
array::typenum::U10,
array::typenum::U11,
array::typenum::U12,
array::typenum::U13,
array::typenum::U14,
array::typenum::U15,
array::typenum::U16,
array::typenum::U17,
array::typenum::U18,
array::typenum::U19,
array::typenum::U20,
array::typenum::U21,
array::typenum::U22,
array::typenum::U23,
array::typenum::U24,
array::typenum::U25,
array::typenum::U26,
array::typenum::U27,
array::typenum::U28,
array::typenum::U29,
array::typenum::U30,
array::typenum::U31,
array::typenum::U32,
array::typenum::U48,
array::typenum::U96,
array::typenum::U128,
array::typenum::U192,
array::typenum::U256,
array::typenum::U384,
array::typenum::U448,
array::typenum::U512,
array::typenum::U2048,
array::typenum::U4096
}

impl_serializable_state_u32_array! {
array::typenum::U1,
array::typenum::U2,
array::typenum::U3,
array::typenum::U4,
array::typenum::U5,
array::typenum::U6,
array::typenum::U7,
array::typenum::U8,
array::typenum::U9,
array::typenum::U10,
array::typenum::U11,
array::typenum::U12,
array::typenum::U13,
array::typenum::U14,
array::typenum::U15,
array::typenum::U16,
array::typenum::U24,
array::typenum::U32,
array::typenum::U48,
array::typenum::U64,
array::typenum::U96,
array::typenum::U128,
array::typenum::U192,
array::typenum::U256,
array::typenum::U512,
array::typenum::U1024,
array::typenum::U2048
}

impl_serializable_state_u64_array! {
array::typenum::U1,
array::typenum::U2,
array::typenum::U3,
array::typenum::U4,
array::typenum::U5,
array::typenum::U6,
array::typenum::U7,
array::typenum::U8,
array::typenum::U12,
array::typenum::U16,
array::typenum::U24,
array::typenum::U32,
array::typenum::U48,
array::typenum::U64,
array::typenum::U96,
array::typenum::U128,
array::typenum::U256,
array::typenum::U512,
array::typenum::U1024
}

impl_serializable_state_u128_array! {
array::typenum::U1,
array::typenum::U2,
array::typenum::U3,
array::typenum::U4,
array::typenum::U6,
array::typenum::U8,
array::typenum::U12,
array::typenum::U16,
array::typenum::U24,
array::typenum::U32,
array::typenum::U48,
array::typenum::U64,
array::typenum::U128,
array::typenum::U256,
array::typenum::U512
}
Loading