name = "lab1_rust"
version = "0.0.2"
dependencies = [
- "openssl 0.0.1 (git+https://github.com/sfackler/rust-openssl.git?ref=1f1c30dd3a577b301bb85bf95f964227f84d73fd#1f1c30dd3a577b301bb85bf95f964227f84d73fd)",
+ "openssl 0.0.1 (git+https://github.com/sfackler/rust-openssl.git)",
+]
+
+[[package]]
+name = "libressl-pnacl-sys"
+version = "2.0.1"
+source = "git+https://github.com/DiamondLovesYou/libressl-pnacl-sys.git#9a42eeb52070ae0aa4f666d36198899e1e54cda5"
+dependencies = [
+ "pnacl-build-helper 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "openssl"
version = "0.0.1"
-source = "git+https://github.com/sfackler/rust-openssl.git?ref=1f1c30dd3a577b301bb85bf95f964227f84d73fd#1f1c30dd3a577b301bb85bf95f964227f84d73fd"
+source = "git+https://github.com/sfackler/rust-openssl.git#33af6a0b7a1037945181db96cf4f6915457a3df6"
+dependencies = [
+ "libressl-pnacl-sys 2.0.1 (git+https://github.com/DiamondLovesYou/libressl-pnacl-sys.git)",
+ "openssl-sys 0.0.1 (git+https://github.com/sfackler/rust-openssl.git)",
+]
+
+[[package]]
+name = "openssl-sys"
+version = "0.0.1"
+source = "git+https://github.com/sfackler/rust-openssl.git#33af6a0b7a1037945181db96cf4f6915457a3df6"
+dependencies = [
+ "pkg-config 0.0.1 (git+https://github.com/alexcrichton/pkg-config-rs)",
+]
+
+[[package]]
+name = "pkg-config"
+version = "0.0.1"
+source = "git+https://github.com/alexcrichton/pkg-config-rs#d24a08d87d63df8dc9526c503944415b86719220"
+
+[[package]]
+name = "pnacl-build-helper"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
[dependencies.openssl]
git = "https://github.com/sfackler/rust-openssl.git"
-rev = "1f1c30dd3a577b301bb85bf95f964227f84d73fd"
+#git = "https://github.com/vhbit/rust-openssl.git"
+
+#rev = "1f1c30dd3a577b301bb85bf95f964227f84d73fd"
use openssl::crypto::symm;
// These aren't the keys you're looking for.
-static KEY_A: &'static [u8] = [125, 31, 131, 118, 143, 180, 252, 53, 211, 217, 79, 240, 128, 91, 252, 87, 104, 236, 145, 198, 163, 203, 161, 12, 53, 56, 218, 40, 221, 95, 171, 140];
-static KEY_C: &'static [u8] = [75, 226, 88, 31, 223, 216, 182, 216, 178, 58, 59, 193, 245, 80, 254, 128, 125, 246, 246, 224, 194, 190, 123, 123, 10, 131, 217, 183, 112, 157, 166, 102];
+const KEY_A: &'static [u8] = &[125, 31, 131, 118, 143, 180, 252, 53, 211, 217, 79, 240, 128, 91, 252, 87, 104, 236, 145, 198, 163, 203, 161, 12, 53, 56, 218, 40, 221, 95, 171, 140];
+const KEY_C: &'static [u8] = &[75, 226, 88, 31, 223, 216, 182, 216, 178, 58, 59, 193, 245, 80, 254, 128, 125, 246, 246, 224, 194, 190, 123, 123, 10, 131, 217, 183, 112, 157, 166, 102];
/// Only returns the first ten bytes from HMAC-SHA256.
pub fn compute_mac(data: &[u8]) -> [u8, ..10] {
use std::io::{ MemWriter, Acceptor, Listener, TcpStream, IoResult, IoError, EndOfFile };
use std::io::net::tcp::{ TcpAcceptor, TcpListener };
use packet;
-use packet::{ Packet, Command, Answer, Error, ReadingResult, PacketType };
+use packet::{ Packet, ReadingResult, PacketType };
+use packet::PacketType::{ Command, Answer, Error };
// Default timeout when waiting data on a stream (for instance: 'TcpStream::read').
static DEFAULT_TIMEOUT: Option<u64> = Some(500); // [ms].
match end_point.read() {
Ok(packet@Packet { t: Command(..), .. }) => {
end_point.print("Server", format!("Valid command received: {}", packet));
- let answer = Answer(Packet::random_packet_data([]));
+ let answer = Answer(Packet::random_packet_data(&[]));
match end_point.send(answer.clone()) {
Ok(_) =>
end_point.print("Server", format!("Answer sent: {}", answer)),
}
},
// Socket has been closed.
- Err(packet::IOReadError(IoError { kind: EndOfFile, .. })) => {
+ Err(packet::ReadingError::IO(IoError { kind: EndOfFile, .. })) => {
end_point.print("Server", format!("Connection closed: EOF"));
return
},
fn raw_packet(timestamp: u64) -> Vec<u8> {
let mut m = MemWriter::new();
- match (Packet { t: Command(Packet::random_packet_data([42])), timestamp: timestamp }).write(&mut m, packet::Weak) {
+ match (Packet { t: Command(Packet::random_packet_data(&[42])), timestamp: timestamp }).write(&mut m, packet::Variant::Weak) {
Err(_) => vec!(),
_ => m.unwrap()
}
// 1)
|client: &mut Client| -> bool {
println!("Sending a valid packet...");
- client.send(Command(Packet::random_packet_data([42])))
+ client.send(Command(Packet::random_packet_data(&[42])))
},
// 2)
|client: &mut Client| -> bool {
let mut raw_packet = raw_packet(client.end_point.current_timestamp);
raw_packet[2] = 0xEE; // Alter the type.
match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
- Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
+ Ok(Err(packet::ReadingError::IO( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
other => {
println!("Error: {}", other);
false
client.end_point.current_timestamp += 1;
let raw_packet = raw_packet(0);
match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
- Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
+ Ok(Err(packet::ReadingError::IO( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
other => {
println!("Error: {}", other);
false
raw_packet[13] = 0xBE;
raw_packet[14] = 0xEF;
match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
- Ok(Ok(Packet { t: Error(packet::AuthError), .. })) => true,
+ Ok(Ok(Packet { t: Error(packet::ErrorType::Auth), .. })) => true,
other => {
println!("Error: {}", other);
false
println!("Sending a packet with too small data...");
let command = Command(Packet::new_packet_data(0, Vec::from_elem(6, 0x00)));
match client.end_point.send_with_result(command) {
- Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
+ Ok(Err(packet::ReadingError::IO( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
other => {
println!("Error: {}", other);
false
println!("Sending a packet with too large data...");
let command = Command(Packet::new_packet_data(0, Vec::from_elem(40, 0x00)));
match client.end_point.send_with_result(command) {
- Ok(Err(packet::IOReadError( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
+ Ok(Err(packet::ReadingError::IO( IoError { kind: io::TimedOut, .. }))) => true, // OK: the server should not send any packet.
other => {
println!("Error: {}", other);
false
println!("Sending a packet with wrong padding (all 0)...");
client.end_point.current_timestamp += 1;
let mut m = MemWriter::new();
- let raw_packet = match (Packet { t: Command(Packet::random_packet_data([42])), timestamp: client.end_point.current_timestamp }).write_with_padding_fun(&mut m, packet::Weak, |_, _| -> u8 { 0 }) {
+ let raw_packet = match (Packet { t: Command(Packet::random_packet_data(&[42])), timestamp: client.end_point.current_timestamp }).write_with_padding_fun(&mut m, packet::Variant::Weak, |_, _| -> u8 { 0 }) {
Err(_) => vec!(),
_ => m.unwrap()
};
match client.end_point.send_raw_with_result(raw_packet.as_slice()) {
- Ok(Ok(Packet { t: Error(packet::CryptError), .. })) => true,
+ Ok(Ok(Packet { t: Error(packet::ErrorType::Crypt), .. })) => true,
other => {
println!("Error: {}", other);
false
self.socket.set_timeout(DEFAULT_TIMEOUT);
self.current_timestamp += 1;
match (Packet { t: p, timestamp: self.current_timestamp }).write(&mut self.socket, self.variant) {
- Err(packet::WriteIOError(e)) => Err(e),
+ Err(packet::WritingError::IO(e)) => Err(e),
_ => Ok(())
}
}
Ok(packet) => {
if packet.timestamp <= self.current_timestamp {
println!("Error, timestamp mismatch, current timestamp: {}, packet received: {}", self.current_timestamp, packet);
- Err(packet::InvalidTimestampError)
+ Err(packet::ReadingError::InvalidTimestamp)
} else {
self.current_timestamp = packet.timestamp + 1;
Ok(packet)
}
},
- e @ Err(packet::PaddingError) => {
+ e @ Err(packet::ReadingError::Padding) => {
self.current_timestamp += 1;
- send_error(self, packet::CryptError);
+ send_error(self, packet::ErrorType::Crypt);
e
},
- e @ Err(packet::MACMismatchError) => {
+ e @ Err(packet::ReadingError::MACMismatch) => {
self.current_timestamp += 1;
- send_error(self, packet::AuthError);
+ send_error(self, packet::ErrorType::Auth);
e
},
other =>
*/
match oracle_machine::decipher(address, PORT, &xor_operand, &cipher_block, variant) {
- Some(ref deciphered) if deciphered.as_slice() == expected_plain_block => {
+ Some(ref deciphered) if deciphered.as_slice() == &expected_plain_block => {
println!("The oracle machine has found the plain block!:");
println!(" Expected block: {}", expected_plain_block.to_vec());
println!(" Decrypted block: {}", deciphered)
let args = os::args();
if args.iter().any(|a| a.as_slice() == "--help" || a.as_slice() == "-h") {
- return Help
+ return Mode::Help
}
if args.len() <= 1 {
- ServerAlone
+ Mode::ServerAlone
} else {
match args[1].as_slice() {
- "genkey" => GenKey,
- "tests" => Tests,
- "oracle-weak" => OracleWeak,
- "oracle-fixed" => OracleFixed,
- _ => ServerAlone,
+ "genkey" => Mode::GenKey,
+ "tests" => Mode::Tests,
+ "oracle-weak" => Mode::OracleWeak,
+ "oracle-fixed" => Mode::OracleFixed,
+ _ => Mode::ServerAlone,
}
}
}
let mode = mode();
match mode {
- Help => print_usage(),
- GenKey =>
+ Mode::Help => print_usage(),
+ Mode::GenKey =>
match crypto::generate_key(256 / 8) {
Ok(key) => println!("key: {}", key),
Err(e) => println!("Unable to generate a key. Error: {}", e)
let address = "::1";
println!("Starting server on [{}]:{}...", address, PORT);
- match Server::new(address, PORT, match mode { OracleFixed => packet::Fixed, _ => packet::Weak }) {
+ match Server::new(address, PORT, match mode { Mode::OracleFixed => packet::Variant::Fixed, _ => packet::Variant::Weak }) {
Ok(mut server) => {
println!("Server started");
match mode {
- Tests => Client::start_tests(address, PORT, packet::Weak),
- OracleWeak => do_oracle_attack(address, packet::Weak),
- OracleFixed => do_oracle_attack(address, packet::Fixed),
+ Mode::Tests => Client::start_tests(address, PORT, packet::Variant::Weak),
+ Mode::OracleWeak => do_oracle_attack(address, packet::Variant::Weak),
+ Mode::OracleFixed => do_oracle_attack(address, packet::Variant::Fixed),
_ => {
println!("Press any key to quit");
io::stdin().read_line().ok().expect("Failed to read line");
use std::iter::range_inclusive;
use std::slice::bytes::copy_memory;
use packet;
-use packet::{ Packet, Error };
+use packet::Packet;
+use packet::PacketType::Error;
use end_point::EndPoint;
/// Tries to decipher a ciphered data block by using the previous XOR operand and an oracle on the provided address and port.
forged_xor_operand(&mut final_packet)[byte] = v;
- match end_point.send_raw_with_result(final_packet) {
- Ok(Ok(p @ Packet { t: Error(packet::AuthError), .. })) => {
+ 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
break;
}
},
- Ok(Ok(Packet { t: Error(packet::CryptError), .. })) => (), // Ignored case: the padding is wrong.
+ Ok(Ok(Packet { t: Error(packet::ErrorType::Crypt), .. })) => (), // Ignored case: the padding is wrong.
other => {
println!("Unexcepted response, aborting. {}", other);
return None
use std::rand::{ Rng, StdRng, SeedableRng, distributions };
use std::rand::distributions::IndependentSample;
use serialize::hex::{ ToHex };
+use self::PacketType::{ Command, Answer, Error };
use crypto;
pub enum Variant {
// There are all the errors that may occur when reading an encrypted and authenticated packet.
#[deriving(Show)]
pub enum ReadingError {
- IOReadError(io::IoError),
- UnknownPacketTypeError, // If the first byte is unknown.
- UnconsistentEncryptedSizeError,
- UnconsistentDataSizeError, // The data size is not valid.
- UnconsistentMACSizeError, // The MAC hasn't the correct size.
- MACMismatchError, // The uncrypted received data doesn't match to the received MAC.
- PaddingError, // Padding format error.
- DataError, // The data are invalid.
- InvalidTimestampError
+ IO(io::IoError),
+ UnknownPacketType, // If the first byte is unknown.
+ UnconsistentEncryptedSize,
+ UnconsistentDataSize, // The data size is not valid.
+ UnconsistentMACSize, // The MAC hasn't the correct size.
+ MACMismatch, // The uncrypted received data doesn't match to the received MAC.
+ Padding, // Padding format error.
+ Data, // The data are invalid.
+ InvalidTimestamp
}
-// A macro to return a 'IOReadError' in case of error.
+// A macro to return a 'Err(ReadingError::IO(..))' in case of error.
macro_rules! try_read_io(
- ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(IOReadError(e)) })
+ ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(ReadingError::IO(e)) })
)
// There are all the errors that may occur when encrypting, authenticating and writing a packet.
#[deriving(Show)]
pub enum WritingError {
- WriteIOError(io::IoError),
- EncryptError,
+ IO(io::IoError),
+ Encrypt,
}
-// A macro to return a 'IOWritingError' in case of error.
+// A macro to return a 'Err(WritingError::IO(..))' in case of error.
macro_rules! try_write_io(
- ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(WriteIOError(e)) })
+ ($e:expr) => (match $e { Ok(e) => e, Err(e) => return Err(WritingError::IO(e)) })
)
pub type ReadingResult = Result<Packet, ReadingError>;
#[deriving(Show, Clone)]
pub enum ErrorType {
- CryptError,
- AuthError
+ Crypt,
+ Auth
}
#[deriving(Clone)]
}
// Computes the MAC. It depends of the choosen variant.
- let mac = crypto::compute_mac(data.slice_to(match variant { Weak => data_size, _ => data.len() }));
+ let mac = crypto::compute_mac(data.slice_to(match variant { 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)
+ _ => return Err(WritingError::Encrypt)
};
// Writes packet length.
match self.t {
Command(_) => 0x00,
Answer(_) => 0xFF,
- Error(CryptError) => 0x0A,
- Error(AuthError) => 0x0B
+ Error(ErrorType::Crypt) => 0x0A,
+ Error(ErrorType::Auth) => 0x0B
}
));
try_write_io!(output.write(encrypted_data.as_slice()));
// Writes the MAC.
- try_write_io!(output.write(mac));
+ try_write_io!(output.write(&mac));
Ok(())
}
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);
- return Err(UnknownPacketTypeError)
+ return Err(ReadingError::UnknownPacketType)
}
let timestamp = try_read_io!(input.read_be_u64());
let mut encrypted_data = Vec::from_elem(data_size as uint - FIXED_PACKET_SIZE, 0u8);
if try_read_io!(input.read(encrypted_data.as_mut_slice_())) != encrypted_data.len() {
- return Err(UnconsistentEncryptedSizeError)
+ return Err(ReadingError::UnconsistentEncryptedSize)
}
let mut data = match crypto::decrypt(encrypted_data.as_slice(), iv_from_timestamp(timestamp).as_slice()) {
Some(d) => d,
- _ => return Err(UnconsistentEncryptedSizeError)
+ _ => return Err(ReadingError::UnconsistentEncryptedSize)
};
// Reads the MAC.
let mut mac_read = [0u8, ..10];
- if try_read_io!(input.read(mac_read)) != mac_read.len() {
- return Err(UnconsistentMACSizeError)
+ if try_read_io!(input.read(&mut mac_read)) != mac_read.len() {
+ return Err(ReadingError::UnconsistentMACSize)
}
- match variant { Fixed if mac_read != crypto::compute_mac(data.as_slice()) => return Err(MACMismatchError), _ => () };
+ match variant { Variant::Fixed if mac_read != crypto::compute_mac(data.as_slice()) => return Err(ReadingError::MACMismatch), _ => () };
// 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() || padding_size == 0 || data.slice_from(data.len() - padding_size as uint).iter().any(|b| *b != padding_size) {
- return Err(PaddingError)
+ return Err(ReadingError::Padding)
}
let data_length = data.len() - padding_size as uint;
data.truncate(data_length);
},
None =>
- return Err(PaddingError)
+ return Err(ReadingError::Padding)
}
}
- match variant { Weak if mac_read != crypto::compute_mac(data.as_slice()) => return Err(MACMismatchError), _ => () };
+ match variant { Variant::Weak if mac_read != crypto::compute_mac(data.as_slice()) => return Err(ReadingError::MACMismatch), _ => () };
Ok(Packet {
t: match packet_type {
// Command or answer.
0x00 | 0xFF => {
if data.len() < MIN_PAYLOAD_SIZE + 1 || data.len() > MAX_PAYLOAD_SIZE + 1 {
- return Err(UnconsistentDataSizeError)
+ return Err(ReadingError::UnconsistentDataSize)
}
let pd = PacketData { id: data[0], payload: data.tail().to_vec() }; // match data.as_slice() { [id, payload..] => PacketData { id: id, payload: payload.to_vec() } };
match packet_type { 0x00 => Command(pd), _ => Answer(pd) }
// Error.
_ => {
if data.len() != 16 {
- return Err(UnconsistentDataSizeError)
+ return Err(ReadingError::UnconsistentDataSize)
} else if data != Vec::from_elem(16, 0) {
- return Err(DataError)
+ return Err(ReadingError::Data)
}
- match packet_type { 0x0A => Error(CryptError), _ => Error(AuthError) }
+ match packet_type { 0x0A => Error(ErrorType::Crypt), _ => Error(ErrorType::Auth) }
}
},
timestamp: timestamp