* Oracle machine finished.
[crypto_lab1.git] / lab1_rust / src / oracle_machine.rs
1 use std::io;
2 use std::io::{ TcpStream };
3 use std::iter::{ range_inclusive };
4 use std::slice::bytes::copy_memory;
5 use packet;
6 use packet::{ Packet, Error };
7 use end_point::EndPoint;
8
9 /// Try to decypher a cyphered data block by using the previous xor operand and an oracle on the provided address and port.
10 /// May prints some message on the stdout.
11 pub fn decypher(address: &str, port: u16, original_xor_operand: &[u8, ..16], cypherblock: &[u8, ..16], variant: packet::Variant) -> Option<Vec<u8>> {
12 let mut end_point = EndPoint::new(
13 match TcpStream::connect(address, port) {
14 Ok(s) => s,
15 _ => {
16 println!("Unable to connect to the oracle on [{}]:{}", address, port);
17 return None
18 }
19 },
20 variant,
21 );
22
23 let mut final_packet = [0u8, ..2 + 1 + 8 + 32 + 10];
24 final_packet[1] = 1 + 8 + 32 + 10; // Data length.
25 copy_memory(final_packet.slice_mut(2 + 1 + 8 + 16, 2 + 1 + 8 + 32), cypherblock);
26
27 let mut decypher_block = [0u8, ..16]; // The result.
28 let mut x_prime_block = [0u8, ..16]; // The cypher block ('cypherblock') after AES and before XOR.
29 let mut current_timestamp = 0u64;
30 let mut first_byte = 0u8; // Used to save the first byte for the first iteration.
31
32 #[inline(always)]
33 fn forged_xor_operand(packet: &mut [u8]) -> &mut [u8] { packet.slice_mut(2 + 1 + 8, 2 + 1 + 8 + 16) }
34
35 // For each bytes.
36 let mut byte = 15;
37 'main_loop: loop {
38 let mut get_mac_mismatch_error = false; // For the first byte we need to insure there is only one AUTH error (one valid padding).
39
40 for v in range_inclusive(0u8, 255) { // For each values of the current byte.
41
42 // Compute and write timestamp.
43 current_timestamp += 2;
44 {
45 let mut timestamp_writer = io::BufWriter::new(final_packet.slice_mut(2 + 1, 2 + 1 + 8));
46 let _ = timestamp_writer.write_be_u64(current_timestamp - 1);
47 }
48
49 forged_xor_operand(&mut final_packet)[byte] = v;
50
51 match end_point.send_raw_with_result(final_packet) {
52 Ok(Ok(Packet { t: Error(packet::AuthError), .. })) => {
53
54 // If we already got a MAC mismatch for the first byte then the second byte is incremented and the loop is replayed.
55 if byte == 15 && get_mac_mismatch_error {
56 forged_xor_operand(&mut final_packet)[14] += 1;
57 continue 'main_loop;
58 }
59
60 get_mac_mismatch_error = true;
61
62 let padding_value = 16 - byte;
63 x_prime_block[byte] = v ^ (padding_value as u8);
64 decypher_block[byte] = x_prime_block[byte] ^ original_xor_operand[byte];
65
66 // We set the processed bytes of the forged XOR operand to have the next padding value.
67 for i in range(16 - padding_value, 16) {
68 forged_xor_operand(&mut final_packet)[i] = x_prime_block[i] ^ ((padding_value as u8) + 1);
69 }
70
71 // Special case for the first byte: we have to test all the values.
72 if byte == 15 {
73 first_byte = forged_xor_operand(&mut final_packet)[15];
74 } else {
75 break;
76 }
77 },
78 Ok(Ok(Packet { t: Error(packet::CryptError), .. })) => (), // Ignored case: the padding is wrong.
79 other => {
80 println!("Unexcepted response, aborting. {}", other);
81 return None
82 }
83 }
84 }
85
86 if byte == 15 {
87 forged_xor_operand(&mut final_packet)[15] = first_byte;
88 }
89
90 // It was the last byte.
91 if byte == 0 { break; }
92
93 byte -= 1;
94 }
95
96 Some(decypher_block.to_vec())
97 }