use binrw::prelude::*;
use std::{error::Error, io::Cursor};
use crate::{crypto, packets::smb2::header::Header};
#[derive(Debug)]
pub struct MessageSigner {
signing_algo: Box<dyn crypto::SigningAlgo>,
}
impl MessageSigner {
pub fn new(signing_algo: Box<dyn crypto::SigningAlgo>) -> MessageSigner {
MessageSigner { signing_algo }
}
pub fn verify_signature(
&mut self,
header: &mut Header,
raw_data: &Vec<u8>,
) -> Result<(), Box<dyn Error>> {
let calculated_signature = self.calculate_signature(header, raw_data)?;
if calculated_signature != header.signature {
return Err("Signature verification failed".into());
}
log::debug!(
"Signature verification passed (signature={}).",
header.signature
);
Ok(())
}
pub fn sign_message(
&mut self,
header: &mut Header,
raw_data: &mut Vec<u8>,
) -> Result<(), Box<dyn Error>> {
debug_assert!(raw_data.len() >= Header::STRUCT_SIZE);
header.signature = self.calculate_signature(header, raw_data)?;
let mut header_writer = Cursor::new(&mut raw_data[0..Header::STRUCT_SIZE]);
header.write(&mut header_writer)?;
log::debug!(
"Message #{} signed (signature={}).",
header.message_id,
header.signature
);
Ok(())
}
fn calculate_signature(
&mut self,
header: &mut Header,
raw_data: &Vec<u8>,
) -> Result<u128, Box<dyn Error>> {
let signture_backup = header.signature;
header.signature = 0;
let mut header_bytes = Cursor::new([0; Header::STRUCT_SIZE]);
header.write(&mut header_bytes)?;
header.signature = signture_backup;
self.signing_algo.start(&header);
self.signing_algo.update(&header_bytes.into_inner());
let message_body = &raw_data[Header::STRUCT_SIZE..];
self.signing_algo.update(message_body);
Ok(self.signing_algo.finalize())
}
}