-#![feature(test)]
#![feature(try_from)]
extern crate x25519_dalek;
Ok(s)
}
-fn interpret_packet_extra<'a, T>(pkt: &'a NetworkPacket) -> Result<(&'a T, &'a [u8]), OssuaryError> {
+fn interpret_packet_extra<'a, T>(pkt: &'a NetworkPacket)
+ -> Result<(&'a T, &'a [u8]), OssuaryError> {
let s: &T = slice_as_struct(&pkt.data)?;
Ok((s, &pkt.data[::std::mem::size_of::<T>()..]))
}
-fn read_packet<T,U>(conn: &mut ConnectionContext, mut stream: T) ->Result<(NetworkPacket, usize), OssuaryError>
+fn read_packet<T,U>(conn: &mut ConnectionContext,
+ mut stream: T) ->Result<(NetworkPacket, usize), OssuaryError>
where T: std::ops::DerefMut<Target = U>,
U: std::io::Read {
let header_size = ::std::mem::size_of::<PacketHeader>();
Ok(written)
}
-pub fn crypto_send_handshake<T,U>(conn: &mut ConnectionContext, mut buf: T) -> Result<usize, OssuaryError>
+pub fn crypto_send_handshake<T,U>(conn: &mut ConnectionContext,
+ mut buf: T) -> Result<usize, OssuaryError>
where T: std::ops::DerefMut<Target = U>,
U: std::io::Write {
// Try to send any unsent buffered data
Ok(written)
}
-pub fn crypto_recv_handshake<T,U>(conn: &mut ConnectionContext, buf: T) -> Result<usize, OssuaryError>
+pub fn crypto_recv_handshake<T,U>(conn: &mut ConnectionContext,
+ buf: T) -> Result<usize, OssuaryError>
where T: std::ops::DerefMut<Target = U>,
U: std::io::Read {
let mut bytes_read: usize = 0;
&aad, &ciphertext, &tag, &mut plaintext)?;
let pubkey = &plaintext[0..32];
let sig = &plaintext[32..];
- if conn.authorized_keys.iter().filter(|k| &pubkey == k).count() > 0 {
+ if conn.authorized_keys.iter().filter(
+ |k| &pubkey == k).count() > 0 {
let public = match PublicKey::from_bytes(pubkey) {
Ok(p) => p,
Err(_) => {
_ => { error = true; }
}
},
- ConnectionState::ServerSendPubKey => {
- error = true;
- }, // nop
- ConnectionState::ServerSendChallenge => {
- error = true;
- }, // nop
- ConnectionState::ClientNew => {
- error = true;
- }, // nop
ConnectionState::ClientWaitKey(_t) => {
match pkt.kind() {
PacketType::PublicKeyNonce => {
}
}
},
- ConnectionState::ClientSendAck => {
- error = true;
- }, // nop
ConnectionState::ClientWaitAck(_t) => {
match pkt.kind() {
PacketType::PubKeyAck => {
},
}
},
- ConnectionState::ClientSendAuth => {
- error = true;
- }, // nop
- ConnectionState::Failed(_) => {
- error = true;
- }, // nop
+ ConnectionState::ServerSendPubKey |
+ ConnectionState::ServerSendChallenge |
+ ConnectionState::ClientNew |
+ ConnectionState::ClientSendAck |
+ ConnectionState::ClientSendAuth |
ConnectionState::Encrypted => {
+ // no-op
+ },
+ ConnectionState::Failed(_) => {
error = true;
- }, // nop
+ },
}
if error {
conn.reset_state(None);
}
}
-pub fn crypto_send_data<T,U>(conn: &mut ConnectionContext, in_buf: &[u8], mut out_buf: T) -> Result<usize, OssuaryError>
+pub fn crypto_send_data<T,U>(conn: &mut ConnectionContext,
+ in_buf: &[u8],
+ mut out_buf: T) -> Result<usize, OssuaryError>
where T: std::ops::DerefMut<Target = U>,
U: std::io::Write {
// Try to send any unsent buffered data
match conn.state {
ConnectionState::Encrypted => {},
_ => {
- return Err(OssuaryError::InvalidPacket("Encrypted channel not established.".into()));
+ return Err(OssuaryError::InvalidPacket(
+ "Encrypted channel not established.".into()));
}
}
let aad = [];
Ok(written)
}
-pub fn crypto_recv_data<T,U,R,V>(conn: &mut ConnectionContext, in_buf: T, mut out_buf: R) -> Result<(usize, usize), OssuaryError>
+pub fn crypto_recv_data<T,U,R,V>(conn: &mut ConnectionContext,
+ in_buf: T,
+ mut out_buf: R) -> Result<(usize, usize), OssuaryError>
where T: std::ops::DerefMut<Target = U>,
U: std::io::Read,
R: std::ops::DerefMut<Target = V>,
match conn.state {
ConnectionState::Encrypted => {},
_ => {
- return Err(OssuaryError::InvalidPacket("Encrypted channel not established.".into()));
+ return Err(OssuaryError::InvalidPacket(
+ "Encrypted channel not established.".into()));
}
}
}
},
_ => {
- return Err(OssuaryError::InvalidPacket("Received non-encrypted data on encrypted channel.".into()));
+ return Err(OssuaryError::InvalidPacket(
+ "Received non-encrypted data on encrypted channel.".into()));
},
}
},
Ok((bytes_read, bytes_written))
}
-pub fn crypto_flush<R,V>(conn: &mut ConnectionContext, mut out_buf: R) -> Result<usize, OssuaryError>
+pub fn crypto_flush<R,V>(conn: &mut ConnectionContext,
+ mut out_buf: R) -> Result<usize, OssuaryError>
where R: std::ops::DerefMut<Target = V>,
V: std::io::Write {
return write_stored_packet(conn, &mut out_buf);
#[cfg(test)]
mod tests {
- extern crate test;
- use test::Bencher;
- use std::thread;
- use std::net::{TcpListener, TcpStream};
use crate::*;
#[test]
let _ = conn.set_authorized_keys(keys.iter().map(|x| x.as_slice())).unwrap();
}
- #[bench]
- fn bench_test(b: &mut Bencher) {
- let server_thread = thread::spawn(move || {
- let listener = TcpListener::bind("127.0.0.1:9987").unwrap();
- let mut server_stream = listener.incoming().next().unwrap().unwrap();
- let mut server_conn = ConnectionContext::new(ConnectionType::UnauthenticatedServer);
- while crypto_handshake_done(&server_conn).unwrap() == false {
- if crypto_send_handshake(&mut server_conn, &mut server_stream).is_ok() {
- loop {
- match crypto_recv_handshake(&mut server_conn, &mut server_stream) {
- Ok(_) => break,
- Err(OssuaryError::WouldBlock(_)) => {},
- _ => panic!("Handshake failed"),
- }
- }
- }
- }
- println!("server handshook");
- let mut plaintext = vec!();
- let mut bytes: u64 = 0;
- let start = std::time::SystemTime::now();
- loop {
- //std::thread::sleep(std::time::Duration::from_millis(100));
- match crypto_recv_data(&mut server_conn,
- &mut server_stream,
- &mut plaintext) {
- Ok((read, _written)) => bytes += read as u64,
- Err(OssuaryError::WouldBlock(_)) => continue,
- Err(e) => {
- println!("err: {:?}", e);
- panic!("Recv failed")
- },
- }
- if plaintext == [0xde, 0xde, 0xbe, 0xbe] {
- println!("finished");
- if let Ok(dur) = start.elapsed() {
- let t = dur.as_secs() as f64
- + dur.subsec_nanos() as f64 * 1e-9;
- println!("Benchmark done (recv): {} bytes in {:.2} s", bytes, t);
- println!("{:.2} MB/s", bytes as f64 / 1024.0 / 1024.0 / t);
- }
- break;
- }
- plaintext.clear();
- }
- });
-
- std::thread::sleep(std::time::Duration::from_millis(500));
- let mut client_stream = TcpStream::connect("127.0.0.1:9987").unwrap();
- client_stream.set_nonblocking(true).unwrap();
- let mut client_conn = ConnectionContext::new(ConnectionType::Client);
- while crypto_handshake_done(&client_conn).unwrap() == false {
- if crypto_send_handshake(&mut client_conn, &mut client_stream).is_ok() {
- loop {
- match crypto_recv_handshake(&mut client_conn, &mut client_stream) {
- Ok(_) => break,
- Err(OssuaryError::WouldBlock(_)) => {},
- Err(e) => {
- println!("err: {:?}", e);
- panic!("Handshake failed")
- },
- }
- }
- }
- }
- println!("client handshook");
- let mut client_stream = std::io::BufWriter::new(client_stream);
- let mut bytes: u64 = 0;
- let start = std::time::SystemTime::now();
- let mut plaintext: &[u8] = &[0xaa; 16384];
- b.iter(|| {
- match crypto_send_data(&mut client_conn,
- &mut plaintext,
- &mut client_stream) {
- Ok(b) => bytes += b as u64,
- Err(OssuaryError::WouldBlock(_)) => {},
- _ => panic!("send error"),
- }
- });
- if let Ok(dur) = start.elapsed() {
- let t = dur.as_secs() as f64
- + dur.subsec_nanos() as f64 * 1e-9;
- println!("Benchmark done (xmit): {} bytes in {:.2} s", bytes, t);
- println!("{:.2} MB/s", bytes as f64 / 1024.0 / 1024.0 / t);
- }
- let mut plaintext: &[u8] = &[0xde, 0xde, 0xbe, 0xbe];
- loop {
- match crypto_send_data(&mut client_conn, &mut plaintext, &mut client_stream) {
- Ok(w) => {
- println!("wrote finish: {}", w);
- break;
- },
- Err(OssuaryError::WouldBlock(_)) => {},
- _ => panic!("Send failed"),
- }
- }
- loop {
- match crypto_flush(&mut client_conn, &mut client_stream) {
- Ok(w) => {
- if w == 0 {
- break;
- }
- println!("flushed: {}", w);
- },
- _ => panic!("Flush failed"),
- }
- }
-
- let mut client_stream: Option<std::io::BufWriter<_>> = Some(client_stream);
- loop {
- client_stream = match client_stream {
- None => break,
- Some(s) => match s.into_inner() {
- Ok(_) => None,
- Err(e) => {
- match e.error().kind() {
- std::io::ErrorKind::WouldBlock => {
- Some(e.into_inner())
- },
- _ => panic!("error: {:?}", e.error()),
- }
- },
- }
- };
- }
- println!("flushed");
- //drop(client_stream); // flush the buffer
- let _ = server_thread.join();
- }
}
+use ossuary::clib::{
+ ossuary_create_connection,
+ ossuary_destroy_connection,
+ ossuary_set_secret_key,
+ ossuary_set_authorized_keys,
+ ossuary_send_handshake,
+ ossuary_recv_handshake,
+ ossuary_handshake_done,
+ ossuary_send_data,
+ ossuary_recv_data,
+};
+
+use std::thread;
+use std::net::{TcpListener, TcpStream};
+
+use std::io::{Write};
+use std::io::BufRead;
+
+fn server() -> Result<(), std::io::Error> {
+ let listener = TcpListener::bind("127.0.0.1:9989").unwrap();
+ for stream in listener.incoming() {
+ let mut stream: TcpStream = stream.unwrap();
+ let mut reader = std::io::BufReader::new(stream.try_clone().unwrap());
+ let mut conn = ossuary_create_connection(1);
+ let key: &[u8; 32] = &[0xbe, 0x1c, 0xa0, 0x74, 0xf4, 0xa5, 0x8b, 0xbb,
+ 0xd2, 0x62, 0xa7, 0xf9, 0x52, 0x3b, 0x6f, 0xb0,
+ 0xbb, 0x9e, 0x86, 0x62, 0x28, 0x7c, 0x33, 0x89,
+ 0xa2, 0xe1, 0x63, 0xdc, 0x55, 0xde, 0x28, 0x1f];
+ let keys: &[*const u8; 1] = &[key as *const u8];
+ ossuary_set_authorized_keys(conn, keys as *const *const u8, keys.len() as u8);
+
+ let out_buf: [u8; 512] = [0; 512];
+
+ while ossuary_handshake_done(conn) == 0 {
+ let mut out_len = out_buf.len() as u16;
+ let more = ossuary_send_handshake(conn, (&out_buf) as *const u8 as *mut u8, &mut out_len);
+ let _ = stream.write_all(&out_buf[0..out_len as usize]).unwrap();
+
+ if more >= 0 {
+ let in_buf = reader.fill_buf().unwrap();
+ let mut in_len = in_buf.len() as u16;
+ if in_len > 0 {
+ let len = ossuary_recv_handshake(conn, in_buf as *const [u8] as *const u8, &mut in_len);
+ reader.consume(len as usize);
+ }
+ }
+ }
+
+ let mut plaintext: [u8; 256] = [0; 256];
+ plaintext[0..13].copy_from_slice("from server 1".as_bytes());
+ let mut out_len: u16 = out_buf.len() as u16;
+ let sz = ossuary_send_data(
+ conn,
+ (&plaintext) as *const u8 as *mut u8, 13 as u16,
+ (&out_buf) as *const u8 as *mut u8,
+ &mut out_len);
+ let _ = stream.write_all(&out_buf[0..sz as usize]).unwrap();
+
+ plaintext[0..13].copy_from_slice("from server 2".as_bytes());
+ let mut out_len: u16 = out_buf.len() as u16;
+ let sz = ossuary_send_data(
+ conn,
+ (&plaintext) as *const u8 as *mut u8, 13 as u16,
+ (&out_buf) as *const u8 as *mut u8,
+ &mut out_len);
+ let _ = stream.write_all(&out_buf[0..sz as usize]).unwrap();
+
+ let in_buf = reader.fill_buf().unwrap();
+ if in_buf.len() > 0 {
+ let mut out_len = out_buf.len() as u16;
+ let mut in_len = in_buf.len() as u16;
+ let len = ossuary_recv_data(
+ conn,
+ (in_buf) as *const [u8] as *mut u8, &mut in_len,
+ (&out_buf) as *const u8 as *mut u8, &mut out_len);
+ if len != -1 {
+ println!("CLIB READ: {:?}",
+ std::str::from_utf8(&out_buf[0..out_len as usize]).unwrap());
+ reader.consume(len as usize);
+ }
+ }
+
+ ossuary_destroy_connection(&mut conn);
+ break;
+ }
+ Ok(())
+}
+
+fn client() -> Result<(), std::io::Error> {
+ let mut stream = TcpStream::connect("127.0.0.1:9989").unwrap();
+ let mut conn = ossuary_create_connection(0);
+ let key: &[u8; 32] = &[0x10, 0x86, 0x6e, 0xc4, 0x8a, 0x11, 0xf3, 0xc5,
+ 0x6d, 0x77, 0xa6, 0x4b, 0x2f, 0x54, 0xaa, 0x06,
+ 0x6c, 0x0c, 0xb4, 0x75, 0xd8, 0xc8, 0x7d, 0x35,
+ 0xb4, 0x91, 0xee, 0xd6, 0xac, 0x0b, 0xde, 0xbc];
+ ossuary_set_secret_key(conn, key as *const u8);
+
+ let out_buf: [u8; 512] = [0; 512];
+
+ let mut reader = std::io::BufReader::new(stream.try_clone().unwrap());
+ while ossuary_handshake_done(conn) == 0 {
+ let mut out_len = out_buf.len() as u16;
+ let more = ossuary_send_handshake(conn, (&out_buf) as *const u8 as *mut u8, &mut out_len);
+ let _ = stream.write_all(&out_buf[0.. out_len as usize]).unwrap();
+
+ if more >= 0 {
+ let in_buf = reader.fill_buf().unwrap();
+ let mut in_len = in_buf.len() as u16;
+ let len = ossuary_recv_handshake(conn, in_buf as *const [u8] as *const u8, &mut in_len);
+ reader.consume(len as usize);
+ }
+ }
+
+ let out_buf: [u8; 256] = [0; 256];
+ let mut plaintext: [u8; 256] = [0; 256];
+ plaintext[0..11].copy_from_slice("from client".as_bytes());
+ let mut out_len: u16 = out_buf.len() as u16;
+ let sz = ossuary_send_data(
+ conn,
+ (&plaintext) as *const u8 as *mut u8, 11 as u16,
+ (&out_buf) as *const u8 as *mut u8,
+ &mut out_len);
+ let _ = stream.write_all(&out_buf[0..sz as usize]).unwrap();
+
+ let mut stream = std::io::BufReader::new(stream);
+ let mut count = 0;
+ loop {
+ let in_buf = stream.fill_buf().unwrap();
+ if in_buf.len() == 0 || count == 2 {
+ break;
+ }
+ let mut out_len = out_buf.len() as u16;
+ let mut in_len = in_buf.len() as u16;
+ let len = ossuary_recv_data(
+ conn,
+ in_buf as *const [u8] as *mut u8, &mut in_len,
+ (&out_buf) as *const u8 as *mut u8, &mut out_len);
+ if len == -1 {
+ break;
+ }
+ if len > 0 {
+ println!("CLIB READ: {:?}",
+ std::str::from_utf8(&out_buf[0..out_len as usize]).unwrap());
+ stream.consume(len as usize);
+ count += 1;
+ }
+ }
+
+ ossuary_destroy_connection(&mut conn);
+ Ok(())
+}
+
+#[test]
+fn test_clib() {
+ let server = thread::spawn(move || { let _ = server(); });
+ std::thread::sleep(std::time::Duration::from_millis(500));
+ let child = thread::spawn(move || { let _ = client(); });
+ let _ = child.join();
+ let _ = server.join();
+}