+ // Sees 'packet::Packet' documentation for a complete description about the binary packet structure.
+ let mut final_packet = [0u8, ..2 + 1 + 8 + 32 + 10];
+ final_packet[1] = (final_packet.len() as u8) - 2; // Data length.
+ copy_memory(final_packet.slice_mut(2 + 1 + 8 + 16, 2 + 1 + 8 + 32), cipher_block);
+
+ let mut decipher_block = [0u8, ..16]; // The result.
+ let mut x_prime_block = [0u8, ..16]; // The cipher block ('cipher_block') 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.
+
+ // Computes and writes 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(p @ Packet { t: Error(packet::ErrorType::Auth), .. })) => {
+ println!("We received a MAC Error: {}", p);
+
+ // If we already got a MAC mismatch for the first byte then
+ // the second byte is incremented and the main loop is replayed for the first byte.
+ 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);
+ decipher_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 (2, 3, 4, etc..).
+ 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 to avoid a valid padding
+ // which is not [.., 0x01], for instance [.., 0x02, 0x02]. It's a very rare case but not impossible.
+ if byte == 15 {
+ first_byte = forged_xor_operand(&mut final_packet)[15];
+ } else {
+ break;
+ }
+ },
+ Ok(Ok(Packet { t: Error(packet::ErrorType::Crypt), .. })) => (), // 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(decipher_block.to_vec())
+}
\ No newline at end of file