X-Git-Url: http://git.euphorik.ch/?a=blobdiff_plain;f=lab1_rust%2Fsrc%2Fpacket.rs;h=8b02ccdf0e46d52dc772f0803aa504cdec5f4d70;hb=fe03a7f9df6b8f4cf03e2399aeb68a7dc2605a67;hp=73eecea9ad1cb7948f7bd83948296fdd00ee92dc;hpb=ecdec5bf7022018eadf4a38b01890bbb3ab79c89;p=crypto_lab1.git diff --git a/lab1_rust/src/packet.rs b/lab1_rust/src/packet.rs index 73eecea..8b02ccd 100644 --- a/lab1_rust/src/packet.rs +++ b/lab1_rust/src/packet.rs @@ -5,6 +5,11 @@ use std::rand::distributions::IndependentSample; use serialize::hex::{ ToHex }; use crypto; +pub enum Variant { + Weak, // The MAC is computed on data without padding. + Fixed // The MAC is computed on data and padding. +} + // There are all the errors that may occur when reading an encrypted and authenticated packet. #[deriving(Show)] pub enum ReadingError { @@ -78,7 +83,9 @@ pub enum PacketType { /// P: Padding from 1 to 16, |I|C...C|P...P| size must be a multiple of 16 /// |0000000000000000| for error packet (16 bytes length) /// MMMMMMMMMM: first 10 bytes (most significant) of the HMAC-SHA256 of: -/// |I|C...C| for command and answer packet +/// for command and answer packet: +/// |I|C...C| for weak variant +/// |I|C...C|P...P|for fixed variant /// |0000000000000000| for error packet #[deriving(Show)] pub struct Packet { @@ -114,15 +121,15 @@ impl Packet { PacketData { id: id, payload: payload } } - pub fn write(&self, output: &mut io::Writer) -> WritingResult { - self.write_with_padding_fun(output, |_, padding_length: uint| -> u8 { + pub fn write(&self, output: &mut io::Writer, variant: Variant) -> WritingResult { + self.write_with_padding_fun(output, variant, |_, padding_length: uint| -> u8 { padding_length as u8 }) } /// 'padd_fun' is function defining the padding. The first argument is the index of the current byte, starting at 0. /// The second argument is the padding length. - pub fn write_with_padding_fun(&self, output: &mut io::Writer, padd_fun: |uint, uint| -> u8) -> WritingResult { + pub fn write_with_padding_fun(&self, output: &mut io::Writer, variant: Variant, padd_fun: |uint, uint| -> u8) -> WritingResult { fn packet_data(p: &PacketData) -> Vec { let mut d = Vec::new(); d.push(p.id); @@ -137,8 +144,7 @@ impl Packet { Error(_) => Vec::from_elem(16, 0) // Padding as data: 16 * 0. }; - // Compute the MAC - let mac = crypto::compute_mac(data.as_slice()); + let data_size = data.len(); // Padding. match self.t { @@ -152,16 +158,19 @@ impl Packet { _ => () } - // Encrypt. + // Computes the MAC. It depends of the choosen variant. + let mac = crypto::compute_mac(data.slice_to(match variant { Weak => data_size, _ => data.len() })); + + // Encrypts. let encrypted_data = match crypto::encrypt(data.as_slice(), iv_from_timestamp(self.timestamp).as_slice()) { Some(d) => d, _ => return Err(EncryptError) }; - // Write packet length. + // Writes packet length. try_write_io!(output.write_be_u16((encrypted_data.len() + FIXED_PACKET_SIZE) as u16)); - // Write packet type. + // Writes packet type. try_write_io!(output.write_u8( match self.t { Command(_) => 0x00, @@ -171,26 +180,26 @@ impl Packet { } )); - // Write timestamp. + // Writes timestamp. try_write_io!(output.write_be_u64(self.timestamp)); - // Write encrypted data. + // Writes encrypted data. try_write_io!(output.write(encrypted_data.as_slice())); - // Write the MAC. + // Writes the MAC. try_write_io!(output.write(mac)); Ok(()) } - pub fn read(input: &mut io::Reader) -> ReadingResult { + pub fn read(input: &mut io::Reader, variant: Variant) -> ReadingResult { fn consume(input: &mut io::Reader, nb_byte: uint) { let _ = input.read_exact(nb_byte); } let data_size = try_read_io!(input.read_be_u16()); - // Read and check the packet type. + // Reads and checks the packet type. let packet_type = try_read_io!(input.read_u8()); if ![0x00, 0xFF, 0x0A, 0x0B].iter().any(|p| *p == packet_type) { consume(input, data_size as uint - 1); @@ -208,12 +217,19 @@ impl Packet { _ => return Err(UnconsistentEncryptedSizeError) }; - // Control the size and the content of the padding then remove it. + // Reads the MAC. + let mut mac_read = [0u8, ..10]; + if try_read_io!(input.read(mac_read)) != mac_read.len() { + return Err(UnconsistentMACSizeError) + } + + match variant { Fixed if mac_read != crypto::compute_mac(data.as_slice()) => return Err(MACMismatchError), _ => () }; + + // Controls the size and the content of the padding then removes it. if packet_type == 0x00 || packet_type == 0xFF { match data.last() { Some(&padding_size) => { - if padding_size as uint > data.len() || !data.slice_from(data.len() - padding_size as uint).iter().any(|b| *b == padding_size) { - consume(input, 10); + if padding_size as uint > data.len() || padding_size == 0 || data.slice_from(data.len() - padding_size as uint).iter().any(|b| *b != padding_size) { return Err(PaddingError) } let data_length = data.len() - padding_size as uint; @@ -224,15 +240,7 @@ impl Packet { } } - // Read an verify the MAC. - let mut mac_read = [0u8, ..10]; - if try_read_io!(input.read(mac_read)) != mac_read.len() { - return Err(UnconsistentMACSizeError) - } - let mac_data = crypto::compute_mac(data.as_slice()); - if mac_read != mac_data { - return Err(MACMismatchError) - } + match variant { Weak if mac_read != crypto::compute_mac(data.as_slice()) => return Err(MACMismatchError), _ => () }; Ok(Packet { t: match packet_type { @@ -259,7 +267,7 @@ impl Packet { } } -// Build an initialization vector: 64 * 0u8 + timestamp (128 bits). +// Builds an initialization vector: 64 * 0u8 + timestamp (128 bits). fn iv_from_timestamp(timestamp: u64) -> Vec { let mut iv = io::MemWriter::with_capacity(16); let _ = iv.write_be_u64(0u64);