X-Git-Url: http://git.euphorik.ch/?p=crypto_lab1.git;a=blobdiff_plain;f=lab1_rust%2Fsrc%2Foracle_machine.rs;fp=lab1_rust%2Fsrc%2Foracle_machine.rs;h=2feb31b4f1c3f98b532763273073e8d6dd5b4237;hp=68aef942f5dce22319f208fedd72cce39f0f03da;hb=ed4d8f3e7e028bf645089edb775af84e6c3f7bd4;hpb=ecdec5bf7022018eadf4a38b01890bbb3ab79c89 diff --git a/lab1_rust/src/oracle_machine.rs b/lab1_rust/src/oracle_machine.rs index 68aef94..2feb31b 100644 --- a/lab1_rust/src/oracle_machine.rs +++ b/lab1_rust/src/oracle_machine.rs @@ -1,19 +1,97 @@ use std::io; use std::io::{ TcpStream }; +use std::iter::{ range_inclusive }; +use std::slice::bytes::copy_memory; +use packet; +use packet::{ Packet, Error }; use end_point::EndPoint; -/// Try to decypher a cyphered data block by using an oracle on the provided address and port. +/// Try to decypher a cyphered data block by using the previous xor operand and an oracle on the provided address and port. /// May prints some message on the stdout. -pub fn decypher(address: &str, port: u16, cypherblock: [u8, ..16]) -> Option> { - let end_point = EndPoint::new( +pub fn decypher(address: &str, port: u16, original_xor_operand: &[u8, ..16], cypherblock: &[u8, ..16], variant: packet::Variant) -> Option> { + let mut end_point = EndPoint::new( match TcpStream::connect(address, port) { Ok(s) => s, _ => { - println!("Unable to connect to the oracle on {}:{}", address, port); + println!("Unable to connect to the oracle on [{}]:{}", address, port); return None } - } + }, + variant, ); - None -} + let mut final_packet = [0u8, ..2 + 1 + 8 + 32 + 10]; + final_packet[1] = 1 + 8 + 32 + 10; // Data length. + copy_memory(final_packet.slice_mut(2 + 1 + 8 + 16, 2 + 1 + 8 + 32), cypherblock); + + let mut decypher_block = [0u8, ..16]; // The result. + let mut x_prime_block = [0u8, ..16]; // The cypher block ('cypherblock') after AES and before XOR. + let mut current_timestamp = 0u64; + let mut first_byte = 0u8; // Used to save the first byte for the first iteration. + + #[inline(always)] + fn forged_xor_operand(packet: &mut [u8]) -> &mut [u8] { packet.slice_mut(2 + 1 + 8, 2 + 1 + 8 + 16) } + + // For each bytes. + let mut byte = 15; + 'main_loop: loop { + let mut get_mac_mismatch_error = false; // For the first byte we need to insure there is only one AUTH error (one valid padding). + + for v in range_inclusive(0u8, 255) { // For each values of the current byte. + + // Compute and write timestamp. + current_timestamp += 2; + { + let mut timestamp_writer = io::BufWriter::new(final_packet.slice_mut(2 + 1, 2 + 1 + 8)); + let _ = timestamp_writer.write_be_u64(current_timestamp - 1); + } + + forged_xor_operand(&mut final_packet)[byte] = v; + + match end_point.send_raw_with_result(final_packet) { + Ok(Ok(Packet { t: Error(packet::AuthError), .. })) => { + + // If we already got a MAC mismatch for the first byte then the second byte is incremented and the loop is replayed. + if byte == 15 && get_mac_mismatch_error { + forged_xor_operand(&mut final_packet)[14] += 1; + continue 'main_loop; + } + + get_mac_mismatch_error = true; + + let padding_value = 16 - byte; + x_prime_block[byte] = v ^ (padding_value as u8); + decypher_block[byte] = x_prime_block[byte] ^ original_xor_operand[byte]; + + // We set the processed bytes of the forged XOR operand to have the next padding value. + for i in range(16 - padding_value, 16) { + forged_xor_operand(&mut final_packet)[i] = x_prime_block[i] ^ ((padding_value as u8) + 1); + } + + // Special case for the first byte: we have to test all the values. + if byte == 15 { + first_byte = forged_xor_operand(&mut final_packet)[15]; + } else { + break; + } + }, + Ok(Ok(Packet { t: Error(packet::CryptError), .. })) => (), // Ignored case: the padding is wrong. + other => { + println!("Unexcepted response, aborting. {}", other); + return None + } + } + } + + if byte == 15 { + forged_xor_operand(&mut final_packet)[15] = first_byte; + } + + // It was the last byte. + if byte == 0 { break; } + + byte -= 1; + } + + Some(decypher_block.to_vec()) +} \ No newline at end of file