Skip to content

Commit

Permalink
crypto-common: add SerializableState trait (#1369)
Browse files Browse the repository at this point in the history
This trait is used for saving the internal state of the object and
restoring the object from the serialized state.
  • Loading branch information
rpiasetskyi authored Nov 18, 2023
1 parent dcae306 commit 9fbd4f9
Show file tree
Hide file tree
Showing 6 changed files with 615 additions and 10 deletions.
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

0 comments on commit 9fbd4f9

Please sign in to comment.