use std::io::{self, Read, Seek, SeekFrom, Write, sink};
use ed25519_dalek::SIGNATURE_LENGTH as ED25519_SIGNATURE_LENGTH;
use sha2::{Digest, Sha512};
use crate::{
EMPTY_TAIL_OPTS_SERIALIZATION, MLADeserialize as _, MLASerialize as _, Opts,
crypto::{
MaybeSeededRNG,
hash::{HashWrapperReader, HashWrapperWriter},
hybrid_signature::{
HybridMultiRecipientSigningKeys, ML_DSA87_SIGNATURE_SIZE, MLASignature,
deserialize_signatures,
},
mlakey::{MLASignatureVerificationPublicKey, MLASigningPrivateKey},
},
errors::{ConfigError, Error},
helpers::{InnerReaderTrait, InnerWriterTrait},
layers::{
encrypt::{
ENCRYPTION_LAYER_MAGIC, EncryptionPersistentConfig, read_encryption_header_after_magic,
},
strip_head_tail::StripHeadTailReader,
traits::{InnerWriterType, LayerReader, LayerTruncatedReader, LayerWriter},
},
read_layer_magic,
};
pub const SIGNATURE_LAYER_MAGIC: &[u8] = b"SIGMLAAA";
pub(crate) struct SignatureLayerWriter<'a, W: 'a + InnerWriterTrait> {
inner: InnerWriterType<'a, W>,
signature_config: SignatureConfig,
hash: Sha512,
}
impl<'a, W: 'a + InnerWriterTrait> SignatureLayerWriter<'a, W> {
pub fn new(
inner: InnerWriterType<'a, W>,
signature_config: SignatureConfig,
mut hash: Sha512,
) -> Result<Self, Error> {
let mut inner = HashWrapperWriter::new(inner, &mut hash);
inner.write_all(SIGNATURE_LAYER_MAGIC)?;
let _ = Opts.dump(&mut inner)?;
let inner = inner.into_inner();
Ok(Self {
inner,
signature_config,
hash,
})
}
}
impl<'a, W: 'a + InnerWriterTrait> Write for SignatureLayerWriter<'a, W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.hash.update(buf);
self.inner.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.inner.flush()
}
}
impl<'a, W: 'a + InnerWriterTrait> LayerWriter<'a, W> for SignatureLayerWriter<'a, W> {
fn finalize(self: Box<Self>) -> Result<W, Error> {
let mut out = Box::new(self.inner).finalize()?;
out.write_all(EMPTY_TAIL_OPTS_SERIALIZATION)?;
let signature_data_content_size: usize = self
.signature_config
.signature_keys
.keys
.len()
.checked_mul(
2usize
.checked_add(ED25519_SIGNATURE_LENGTH)
.ok_or(Error::SerializationError)?
.checked_add(2)
.ok_or(Error::SerializationError)?
.checked_add(ML_DSA87_SIGNATURE_SIZE)
.ok_or(Error::SerializationError)?,
)
.ok_or(Error::SerializationError)?;
let signature_data_content_size =
u64::try_from(signature_data_content_size).map_err(|_| Error::SerializationError)?;
signature_data_content_size.serialize(&mut out)?;
let mut rng = self.signature_config.rng.get_rng()?;
for key in self.signature_config.signature_keys.keys {
let ed25519_signature = key.sign_ed25519(&self.hash.clone());
ed25519_signature.serialize(&mut out)?;
let mldsa87_signature = key.sign_mldsa87(self.hash.clone(), &mut rng)?;
mldsa87_signature.serialize(&mut out)?;
}
signature_data_content_size
.checked_add(8)
.ok_or(Error::SerializationError)?
.serialize(&mut out)?;
Ok(out)
}
}
pub(crate) struct SignatureConfig {
signature_keys: HybridMultiRecipientSigningKeys,
pub(crate) rng: MaybeSeededRNG,
}
impl SignatureConfig {
pub(crate) fn new(signing_private_keys: &[MLASigningPrivateKey]) -> Result<Self, ConfigError> {
if signing_private_keys.is_empty() {
return Err(ConfigError::PrivateKeyNotSet);
}
let signature_keys = HybridMultiRecipientSigningKeys {
keys: signing_private_keys.to_vec(),
};
Ok(Self {
signature_keys,
rng: MaybeSeededRNG::default(),
})
}
}
pub(crate) struct SignatureReaderConfig {
signature_verification_keys: Vec<MLASignatureVerificationPublicKey>,
pub(crate) signature_check: bool,
}
impl SignatureReaderConfig {
pub(crate) fn set_public_keys(&mut self, keys: &[MLASignatureVerificationPublicKey]) {
self.signature_verification_keys = keys.to_vec();
}
}
impl Default for SignatureReaderConfig {
fn default() -> Self {
Self {
signature_verification_keys: Vec::default(),
signature_check: true,
}
}
}
pub(crate) struct SignatureLayerReader<'a, R: 'a + InnerReaderTrait>(StripHeadTailReader<'a, R>);
impl<'a, R: 'a + InnerReaderTrait> SignatureLayerReader<'a, R> {
pub(crate) fn new_skip_magic(
mut inner: Box<dyn 'a + LayerReader<'a, R>>,
signature_reader_config: &SignatureReaderConfig,
archive_header_hash: Sha512,
) -> Result<
(
Self,
Vec<MLASignatureVerificationPublicKey>,
Option<EncryptionPersistentConfig>,
),
Error,
> {
let mut signed_hash = archive_header_hash;
inner.initialize()?;
let mut src = HashWrapperReader::<_, Sha512>::new(inner, &mut signed_hash);
let _ = Opts::from_reader(&mut src)?; let mut src = src.into_inner();
let sig_inner_layer_position = src.stream_position()?;
src.seek(SeekFrom::End(-8))?;
let signature_data_serialized_vec_length = u64::deserialize(&mut src)?;
let signature_data_offset_from_end = 8u64 .checked_add(signature_data_serialized_vec_length) .ok_or(Error::DeserializationError)?;
let i64_signature_data_offset_from_end = 0i64
.checked_sub_unsigned(signature_data_offset_from_end)
.ok_or(Error::DeserializationError)?;
src.seek(SeekFrom::End(i64_signature_data_offset_from_end))?;
let signature_data = Vec::<u8>::deserialize(&mut src)?;
let signature_options_length_offset_from_end = signature_data_offset_from_end
.checked_add(8) .ok_or(Error::DeserializationError)?;
let i64_signature_options_length_offset_from_end = 0i64
.checked_sub_unsigned(signature_options_length_offset_from_end)
.ok_or(Error::DeserializationError)?;
src.seek(SeekFrom::End(i64_signature_options_length_offset_from_end))?;
let signature_options_length = u64::deserialize(&mut src)?;
let sig_layer_tail_len = signature_options_length_offset_from_end
.checked_add(signature_options_length)
.ok_or(Error::DeserializationError)?;
let inner_len = src.seek(SeekFrom::End(0))?;
src.seek(SeekFrom::Start(sig_inner_layer_position))?;
let mut src = StripHeadTailReader::new(
src,
sig_inner_layer_position,
sig_layer_tail_len,
inner_len,
0,
)?;
let mut keys_with_valid_signatures = Vec::new();
let mut read_persistent_encryption_config = None;
if signature_reader_config.signature_check {
let mut hashing_src = HashWrapperReader::new(src, &mut signed_hash);
let next_layer_magic = read_layer_magic(&mut hashing_src)?;
if &next_layer_magic == ENCRYPTION_LAYER_MAGIC {
read_persistent_encryption_config =
Some(read_encryption_header_after_magic(&mut hashing_src)?.0);
}
io::copy(&mut hashing_src, &mut sink())?;
src = hashing_src.into_inner();
src.rewind()?;
let mut keys_ref_with_valid_signatures = Vec::new();
let signatures = deserialize_signatures(&signature_data)?;
for key in &signature_reader_config.signature_verification_keys {
let verified_signatures = signatures
.iter()
.filter(|sig| key.verify(signed_hash.clone(), sig))
.collect::<Vec<_>>();
let traditional_signature_verified = verified_signatures
.iter()
.any(|sig| matches!(sig, MLASignature::MLAEd25519(_)));
let post_quantum_signature_verified = verified_signatures
.iter()
.any(|sig| matches!(sig, MLASignature::MLAMlDsa87(_)));
if traditional_signature_verified && post_quantum_signature_verified {
keys_ref_with_valid_signatures.push(key);
}
}
if keys_ref_with_valid_signatures.is_empty() {
return Err(Error::NoValidSignatureFound);
}
keys_with_valid_signatures.extend(keys_ref_with_valid_signatures.into_iter().cloned());
}
Ok((
Self(src),
keys_with_valid_signatures,
read_persistent_encryption_config,
))
}
}
impl<'a, R: 'a + InnerReaderTrait> Read for SignatureLayerReader<'a, R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.0.read(buf)
}
}
impl<'a, R: 'a + InnerReaderTrait> Seek for SignatureLayerReader<'a, R> {
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
self.0.seek(pos)
}
}
impl<'a, R: 'a + InnerReaderTrait> LayerReader<'a, R> for SignatureLayerReader<'a, R> {
fn into_raw(self: Box<Self>) -> R {
Box::new(self.0).into_raw()
}
fn initialize(&mut self) -> Result<(), Error> {
Ok(())
}
}
pub(crate) struct SignatureLayerTruncatedReader<'a, R: Read> {
inner: Box<dyn 'a + LayerTruncatedReader<'a, R>>,
}
impl<'a, R: 'a + Read> SignatureLayerTruncatedReader<'a, R> {
pub(crate) fn new_skip_magic(
mut inner: Box<dyn 'a + LayerTruncatedReader<'a, R>>,
) -> Result<Self, Error> {
let _ = Opts::from_reader(&mut inner)?; Ok(Self { inner })
}
}
impl<'a, R: 'a + Read> LayerTruncatedReader<'a, R> for SignatureLayerTruncatedReader<'a, R> {}
impl<R: Read> Read for SignatureLayerTruncatedReader<'_, R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.inner.read(buf)
}
}