use std::mem;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::signing_block::algorithms::Algorithms;
use crate::utils::{add_space, print_hexe, print_string};
use crate::{
MyReader,
common::{AdditionalAttributes, Certificates, Digests, PubKey, Signatures},
};
pub const SIGNATURE_SCHEME_V3_BLOCK_ID: u32 = 0xf05368c0;
pub const PROOF_OF_ROTATION_BLOCK_ID: u32 = 0x3ba06f8c;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SignatureSchemeV3 {
pub size: usize,
pub id: u32,
pub signers: Signers,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Signers {
pub size: usize,
pub signers_data: Vec<Signer>,
}
impl Signers {
pub fn parse(data: &mut MyReader) -> Result<Self, String> {
let size_signers = data.read_size()?;
let mut signers = Self {
size: size_signers,
signers_data: Vec::new(),
};
add_space!(4);
#[cfg(feature = "directprint")]
print_string!("size_signers: {}", size_signers);
while data.get_pos() < data.len() {
signers.signers_data.push(Signer::parse(data)?);
}
Ok(signers)
}
pub fn to_u8(&self) -> Vec<u8> {
let content = self
.signers_data
.iter()
.map(|signer| signer.to_u8())
.collect::<Vec<Vec<u8>>>()
.concat();
[(self.size as u32).to_le_bytes().to_vec(), content].concat()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Signer {
pub size: usize,
pub signed_data: SignedData,
pub min_sdk: u32,
pub max_sdk: u32,
pub signatures: Signatures,
pub pub_key: PubKey,
}
impl Signer {
pub fn parse(data: &mut MyReader) -> Result<Self, String> {
let size = data.read_size()?;
add_space!(8);
print_string!("size: {}", size);
let signed_data = SignedData::parse(data)?;
let min_sdk = data.read_u32()?;
add_space!(8);
print_string!("min_sdk: {}", min_sdk);
let max_sdk = data.read_u32()?;
add_space!(8);
print_string!("max_sdk: {}", max_sdk);
let signatures = Signatures::parse(data)?;
let pub_key = PubKey::parse(data)?;
Ok(Self {
size,
signed_data,
min_sdk,
max_sdk,
signatures,
pub_key,
})
}
pub fn to_u8(&self) -> Vec<u8> {
let content = [
self.signed_data.to_u8(),
self.min_sdk.to_le_bytes().to_vec(),
self.max_sdk.to_le_bytes().to_vec(),
self.signatures.to_u8(),
self.pub_key.to_u8(),
]
.concat();
let padding = self
.size
.checked_sub(content.len())
.map_or_else(std::vec::Vec::new, |calculated_size| {
vec![0; calculated_size]
});
[(self.size as u32).to_le_bytes().to_vec(), content, padding].concat()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SignedData {
pub size: usize,
pub digests: Digests,
pub certificates: Certificates,
pub min_sdk: u32,
pub max_sdk: u32,
pub additional_attributes: AdditionalAttributes,
}
impl SignedData {
pub fn parse(data: &mut MyReader) -> Result<Self, String> {
let size_signed_data = data.read_size()?;
add_space!(8);
print_string!("size_signed_data: {}", size_signed_data);
let digests = Digests::parse(data)?;
let certificates = Certificates::parse(data)?;
let min_sdk = data.read_u32()?;
add_space!(12);
print_string!("min_sdk: {}", min_sdk);
let max_sdk = data.read_u32()?;
add_space!(12);
print_string!("max_sdk: {}", max_sdk);
let additional_attributes = AdditionalAttributes::parse(data)?;
Ok(Self {
size: size_signed_data,
digests,
certificates,
min_sdk,
max_sdk,
additional_attributes,
})
}
pub fn to_u8(&self) -> Vec<u8> {
let content = [
self.digests.to_u8(),
self.certificates.to_u8(),
self.min_sdk.to_le_bytes().to_vec(),
self.max_sdk.to_le_bytes().to_vec(),
self.additional_attributes.to_u8(),
]
.concat();
let padding = self
.size
.checked_sub(content.len())
.map_or_else(std::vec::Vec::new, |calculated_size| {
vec![0; calculated_size]
});
[(self.size as u32).to_le_bytes().to_vec(), content, padding].concat()
}
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ProofOfRotation {
pub levels: Vec<Level>,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Level {
pub size: usize,
pub level: SignedDataLevels,
pub flags: u32,
pub signature_algorithm_id: u32,
pub signature: Vec<u8>,
}
#[derive(Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SignedDataLevels {
pub certificate: Vec<u8>,
pub signature_algorithm_id: Algorithms,
}
impl SignatureSchemeV3 {
pub const fn new(signers: Signers) -> Self {
let size = mem::size_of::<u32>() + signers.size;
Self {
size,
id: SIGNATURE_SCHEME_V3_BLOCK_ID,
signers,
}
}
pub fn parse(size: usize, id: u32, data: &mut MyReader) -> Result<Self, String> {
Ok(Self {
size,
id,
signers: Signers::parse(data)?,
})
}
pub fn parse_proof_of_rotation(data: &mut MyReader) -> Result<ProofOfRotation, String> {
let levels_size = data.read_size()?;
add_space!(4);
print_string!("levels_size: {}", levels_size);
let mut levels = Vec::new();
let max_pos_levels = data.get_pos() + levels_size;
while data.get_pos() < max_pos_levels {
let level_size = data.read_size()?;
add_space!(8);
print_string!("level_size: {}", level_size);
let certificate_size = data.read_size()?;
add_space!(8);
print_string!("certificate_size: {}", certificate_size);
let certificate = data.get_to(certificate_size)?.to_vec();
add_space!(8);
print_hexe("certificate", &certificate);
let signature_algorithm_id = data.read_u32()?;
let algo = Algorithms::from(signature_algorithm_id);
add_space!(8);
print_string!(
"signature_algorithm_id: {} {}",
signature_algorithm_id,
algo
);
let flags = data.read_u32()?;
add_space!(8);
print_string!("flags: {}", flags);
let signature_size = data.read_size()?;
add_space!(8);
print_string!("signature_size: {}", signature_size);
let signature = data.get_to(signature_size)?.to_vec();
add_space!(8);
print_hexe("signature", &signature);
levels.push(Level {
size: level_size,
level: SignedDataLevels {
certificate,
signature_algorithm_id: algo,
},
flags,
signature_algorithm_id,
signature,
});
}
Ok(ProofOfRotation { levels })
}
pub fn proof_of_rotation(&self) -> Result<Option<ProofOfRotation>, String> {
if let Some(Signer {
signed_data:
SignedData {
additional_attributes: attributes,
..
},
..
}) = self.signers.signers_data.first()
{
for attribute in attributes.additional_attributes_data.iter() {
if attribute.id == PROOF_OF_ROTATION_BLOCK_ID {
return Ok(Some(Self::parse_proof_of_rotation(&mut MyReader::new(
&attribute.data,
))?));
}
}
}
Ok(None)
}
pub fn to_u8(&self) -> Vec<u8> {
let content = [self.id.to_le_bytes().to_vec(), self.signers.to_u8()].concat();
let padding = self
.size
.checked_sub(content.len())
.map_or_else(std::vec::Vec::new, |calculated_size| {
vec![0; calculated_size]
});
[(self.size as u64).to_le_bytes().to_vec(), content, padding].concat()
}
}