Browse Source

All hail borsh

pull/2/head
Magic_RB 2 years ago
parent
commit
780054f887
  1. 4
      .idea/netstar.iml
  2. 5
      Cargo.toml
  3. 9
      build.rs
  4. 1
      crypto/src/boringtun/mod.rs
  5. 4
      crypto/src/ephemeral_blob.rs
  6. 3
      crypto/src/id_hash.rs
  7. 4
      crypto/src/nonce.rs
  8. 5
      crypto/src/shared_key.rs
  9. 4
      crypto/src/shared_secret.rs
  10. 13
      src/error.rs
  11. 4
      src/main.rs
  12. 13
      src/netstar/control.rs
  13. 199
      src/netstar/controller.rs
  14. 1
      src/netstar/mod.rs
  15. 392
      src/netstar/packet.rs
  16. 6
      src/netstar/peer.rs
  17. 30
      src/netstar/worker.rs

4
.idea/netstar.iml

@ -10,7 +10,11 @@
<sourceFolder url="file://$MODULE_DIR$/chacha20poly1305/chacha20poly1305/examples" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/chacha20poly1305/chacha20poly1305/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/chacha20poly1305/chacha20poly1305/benches" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/crypto/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/bytes/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/bytes/target" />
<excludeFolder url="file://$MODULE_DIR$/chacha20poly1305/chacha20poly1305/target" />
<excludeFolder url="file://$MODULE_DIR$/crypto/target" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />

5
Cargo.toml

@ -12,11 +12,8 @@ crossbeam-channel = "0.4.*"
rayon = "1.3.*"
rand = "0.7.*"
bytemuck = "1.2.*"
capnp = "0.12.*"
borsh = { git = "https://github.com/MagicRB/borsh/" }
crypto = { path = "crypto" }
[build-dependencies]
capnpc = "0.12.*"
[profile.release]
debug = true

9
build.rs

@ -1,8 +1 @@
extern crate capnpc;
fn main() {
::capnpc::CompilerCommand::new()
.file("packet.capnp")
.run()
.expect("compiling schema");
}
fn main() {}

1
crypto/src/boringtun/mod.rs

@ -42,6 +42,7 @@ where
arr
}
#[derive(Debug, Clone)]
pub struct ChaCha20Poly1305 {
key: [u32; 8],
}

4
crypto/src/ephemeral_blob.rs

@ -1,4 +1,6 @@
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
use borsh::{BorshDeserialize, BorshSerialize};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, BorshSerialize, BorshDeserialize)]
pub struct EphemeralBlob(pub [u8; 32]);
impl AsRef<[u8]> for EphemeralBlob {

3
crypto/src/id_hash.rs

@ -1,9 +1,10 @@
use crate::{PublicKey, SharedSecret};
use borsh::{BorshDeserialize, BorshSerialize};
use sha3::Digest;
use std::convert::TryInto;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, BorshSerialize, BorshDeserialize)]
pub struct IdHash(pub [u8; 32]);
impl AsRef<[u8]> for IdHash {

4
crypto/src/nonce.rs

@ -1,4 +1,6 @@
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
use borsh::{BorshDeserialize, BorshSerialize};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, BorshSerialize, BorshDeserialize)]
pub struct Nonce(pub [u8; 24]);
impl AsRef<[u8]> for Nonce {

5
crypto/src/shared_key.rs

@ -1,9 +1,10 @@
use borsh::{BorshDeserialize, BorshSerialize};
use sha3::Digest;
use std::convert::TryInto;
use crate::{EphemeralBlob, PrivateKey, PublicKey, SharedSecret};
use std::convert::TryInto;
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, BorshSerialize, BorshDeserialize)]
pub struct SharedKey(pub [u8; 32]);
impl AsRef<[u8]> for SharedKey {

4
crypto/src/shared_secret.rs

@ -1,4 +1,6 @@
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
use borsh::{BorshDeserialize, BorshSerialize};
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, BorshSerialize, BorshDeserialize)]
pub struct SharedSecret(pub [u8; 32]);
impl AsRef<[u8]> for SharedSecret {

13
src/error.rs

@ -1,5 +1,6 @@
use rayon::ThreadPoolBuildError;
use std::{
array::TryFromSliceError,
fmt::{Display, Formatter},
io::Error as ioError,
};
@ -11,7 +12,10 @@ pub enum Error {
InvalidAddress,
ConnectionNotReady,
SendControlResponse,
TryFromSlice(TryFromSliceError),
UnknownPeer,
DeserializationFailure,
SerializationFailure,
}
impl Display for Error {
@ -25,6 +29,9 @@ impl Display for Error {
Error::ConnectionNotReady => f.write_str("Connection is not ready"),
Error::SendControlResponse => f.write_str("Error while trying to respond to command"),
Error::UnknownPeer => f.write_str("Unknown peer"),
Error::TryFromSlice(error) => f.write_fmt(format_args!("TryFromSliceError")),
Error::DeserializationFailure => f.write_str("Deserialization failure"),
Error::SerializationFailure => f.write_str("Serialization failure"),
}
}
}
@ -41,8 +48,8 @@ impl From<ioError> for Error {
}
}
impl From<crossbeam_channel::SendError<crate::netstar::control::Response>> for Error {
fn from(_: crossbeam_channel::SendError<crate::netstar::control::Response>) -> Self {
Self::SendControlResponse
impl From<TryFromSliceError> for Error {
fn from(error: TryFromSliceError) -> Self {
Self::TryFromSlice(error)
}
}

4
src/main.rs

@ -1,7 +1,3 @@
pub mod packet_capnp {
include!(concat!(env!("OUT_DIR"), "/packet_capnp.rs"));
}
pub mod error;
pub mod netstar;

13
src/netstar/control.rs

@ -1,11 +1,7 @@
use std::time::Duration;
use crate::netstar::{PrivateKey, PublicKey};
use crate::{
error::Error,
netstar::{peer::Peer, IdHash},
};
use crate::{error::Error, netstar::peer::Peer};
use crypto::{IdHash, PrivateKey, PublicKey};
pub enum Command {
Exit,
@ -15,7 +11,10 @@ pub enum Command {
GetPeer(IdHash),
RemovePeer(IdHash),
ListPeers,
Packet(IdHash, Vec<u8>),
Packet {
id_hash_b: IdHash,
plaintext: Vec<u8>,
},
SetHandshakeTimer(Duration),
}

199
src/netstar/controller.rs

@ -1,3 +1,4 @@
use borsh::ser::BorshSerialize;
use crossbeam_channel::{bounded, Receiver, Sender};
use rayon::{ThreadPool, ThreadPoolBuilder};
use std::{
@ -11,16 +12,21 @@ use std::{
use crate::{
error::Error,
netstar::peer::Peer,
netstar::{control, worker},
netstar::{control, packet, worker},
};
use crypto::{IdHash, PrivateKey, PublicKey};
use crate::netstar::packet::PacketType;
use crate::netstar::peer::PeerState;
use crate::netstar::worker::Work;
use crypto::{IdHash, Nonce, PrivateKey, PublicKey, XChaCha20Poly1305};
use std::marker::PhantomData;
fn socket_loop(
socket: Arc<RwLock<UdpSocket>>,
exit_status: Arc<RwLock<bool>>,
socket_tx: Sender<(SocketAddr, Vec<u8>)>,
mut vec_pool: Arc<RwLock<Vec<Vec<u8>>>>,
mut buffer_pool: Arc<RwLock<Vec<Vec<u8>>>>,
) {
socket
.read()
@ -29,13 +35,13 @@ fn socket_loop(
.unwrap();
while *exit_status.read().unwrap() {
let mut vec = match vec_pool.write().unwrap().pop() {
Some(vec) => vec,
let mut buffer = match buffer_pool.write().unwrap().pop() {
Some(buffer) => buffer,
None => Vec::with_capacity(2048),
};
if let Ok((size, source)) = socket.read().unwrap().recv_from(vec.as_mut_slice()) {
socket_tx.send((source, vec)).unwrap();
if let Ok((size, source)) = socket.read().unwrap().recv_from(buffer.as_mut()) {
socket_tx.send((source, buffer)).unwrap();
}
}
}
@ -47,7 +53,7 @@ pub struct Controller {
socket_rx: Receiver<(SocketAddr, Vec<u8>)>,
worker_rx: Receiver<worker::Work>,
worker_tx: Sender<worker::Work>,
vec_pool: Arc<RwLock<Vec<Vec<u8>>>>,
buffer_pool: Arc<RwLock<Vec<Vec<u8>>>>,
socket: Arc<RwLock<UdpSocket>>,
handshake_timer: Duration,
thread_pool: ThreadPool,
@ -68,23 +74,23 @@ impl Controller {
let (worker_tx, worker_rx) = bounded(256);
let exit_status = Arc::new(RwLock::new(false));
let socket = Arc::new(RwLock::new(UdpSocket::bind(address)?));
let vec_pool = Arc::new(RwLock::new(
let buffer_pool = Arc::new(RwLock::new(
(0..128).map(|_| Vec::with_capacity(2048)).collect(),
));
{
let socket = socket.clone();
let exit_status = exit_status.clone();
let vec_pool = vec_pool.clone();
let buffer_pool = buffer_pool.clone();
thread::spawn(|| socket_loop(socket, exit_status, socket_tx, vec_pool));
thread::spawn(|| socket_loop(socket, exit_status, socket_tx, buffer_pool));
}
Ok(Self {
thread_pool,
control_tx,
control_rx,
vec_pool,
buffer_pool,
socket_rx,
worker_rx,
worker_tx,
@ -121,7 +127,7 @@ impl Controller {
};
}
self.control_tx.send(control::Response::Exited)?;
self.control_tx.send(control::Response::Exited).unwrap();
Ok(())
}
@ -135,36 +141,46 @@ impl Controller {
.unwrap(),
control::Command::GetPublicKey => self
.control_tx
.send(control::Response::PublicKey(self.public_key_a.clone()))?,
.send(control::Response::PublicKey(self.public_key_a.clone()))
.unwrap(),
control::Command::SetPeer(id_hash, peer) => {
self.peers.write().unwrap().insert(id_hash, peer);
self.control_tx.send(control::Response::Ok)?;
self.control_tx.send(control::Response::Ok).unwrap();
}
control::Command::GetPeer(id_hash) => match self.peers.read().unwrap().get(&id_hash) {
Some(peer) => self
.control_tx
.send(control::Response::Peer(peer.clone()))?,
.send(control::Response::Peer(peer.clone()))
.unwrap(),
None => self
.control_tx
.send(control::Response::Error(Error::UnknownPeer))?,
.send(control::Response::Error(Error::UnknownPeer))
.unwrap(),
},
control::Command::RemovePeer(id_hash) => {
match self.peers.write().unwrap().remove(&id_hash) {
Some(peer) => self.control_tx.send(control::Response::Ok)?,
Some(peer) => self.control_tx.send(control::Response::Ok).unwrap(),
None => self
.control_tx
.send(control::Response::Error(Error::UnknownPeer))?,
.send(control::Response::Error(Error::UnknownPeer))
.unwrap(),
}
}
control::Command::ListPeers => self.control_tx.send(control::Response::Peers(
self.peers
.read()
.unwrap()
.values()
.map(|peer| peer.clone())
.collect(),
))?,
control::Command::Packet(id_hash, vec) => {}
control::Command::ListPeers => self
.control_tx
.send(control::Response::Peers(
self.peers
.read()
.unwrap()
.values()
.map(|peer| peer.clone())
.collect(),
))
.unwrap(),
control::Command::Packet {
id_hash_b,
plaintext,
} => {}
control::Command::SetHandshakeTimer(handshake_timer) => {
self.handshake_timer = handshake_timer
}
@ -173,20 +189,133 @@ impl Controller {
Ok(())
}
fn socket_handler(&mut self, source: SocketAddr, vec: Vec<u8>) -> Result<(), Error> {
self.vec_pool.write().unwrap().push(vec);
fn socket_handler(&mut self, endpoint: SocketAddr, mut buffer: Vec<u8>) -> Result<(), Error> {
Ok(())
}
fn work_handler(&mut self, work: worker::Work) -> Result<(), Error> {
match work {
worker::Work::Decrypted { vec } => {}
worker::Work::Encrypted { vec } => {}
worker::Work::Serialized { vec } => {}
worker::Work::Deserialized { vec } => {}
Work::Decrypted {
plaintext,
ciphertext,
endpoint,
} => {}
Work::Encrypted {
plaintext,
ciphertext,
endpoint,
id_hash_b,
} => {}
Work::Serialized {
out_buffer,
id_hash_b,
endpoint,
} => {}
Work::Deserialized {
endpoint,
vec,
packet,
} => {}
}
Ok(())
}
fn serialize(&mut self, packet: packet::Packet, mut out_buffer: Vec<u8>, endpoint: SocketAddr) {
let worker_tx = self.worker_tx.clone();
let mut buffer_pool = self.buffer_pool.clone();
self.thread_pool.spawn(move || {
packet.serialize(&mut out_buffer);
worker_tx
.send(Work::Serialized {
out_buffer,
id_hash_b: packet.id_hash,
endpoint,
})
.unwrap(); // @TODO error handling
});
}
fn deserialize(&self, endpoint: SocketAddr, mut vec: Vec<u8>) {
// let worker_tx = self.worker_tx.clone();
//
// self.thread_pool.spawn(move || {
// if let Ok(packet) = packet::Packet::deserialize(&mut vec) {
// // @TODO error handling
// worker_tx
// .send(Work::Deserialized {
// endpoint,
// vec,
// packet,
// })
// .unwrap();
// }
// });
}
fn encrypt(
&self,
xchacha20poly1305: XChaCha20Poly1305,
plaintext: Vec<u8>,
mut ciphertext: Vec<u8>,
endpoint: SocketAddr,
id_hash_b: IdHash,
) {
let worker_tx = self.worker_tx.clone();
self.thread_pool.spawn(move || {
let nonce = Nonce::new(&mut rand::thread_rng());
if plaintext.len() + 16 <= ciphertext.capacity() {
xchacha20poly1305.encrypt(
nonce,
nonce.as_ref(),
plaintext.as_slice(),
ciphertext.as_mut_slice(),
);
worker_tx
.send(Work::Encrypted {
ciphertext,
plaintext,
endpoint,
id_hash_b,
})
.unwrap();
}
})
}
fn decrypt(
&self,
xchacha20poly1305: XChaCha20Poly1305,
mut plaintext: Vec<u8>,
ciphertext: Vec<u8>,
endpoint: SocketAddr,
) {
let worker_tx = self.worker_tx.clone();
self.thread_pool.spawn(move || {
let nonce = Nonce::new(&mut rand::thread_rng());
if ciphertext.len() - 16 <= plaintext.capacity() {
xchacha20poly1305.decrypt(
nonce,
nonce.as_ref(),
plaintext.as_mut_slice(),
ciphertext.as_slice(),
);
worker_tx
.send(Work::Decrypted {
ciphertext,
plaintext,
endpoint,
})
.unwrap();
}
})
}
}

1
src/netstar/mod.rs

@ -14,6 +14,7 @@ use crypto::{EphemeralBlob, IdHash, Nonce, PrivateKey, PublicKey, SharedSecret};
use crate::{error::Error, netstar::peer::Peer};
pub(super) mod control;
pub(super) mod packet;
pub(super) mod peer;
pub(super) mod worker;

392
src/netstar/packet.rs

@ -1,14 +1,14 @@
use std::convert::TryInto;
use borsh::{BorshDeserialize, BorshSerialize};
use crate::{error::Error, packet_capnp::packet};
use crate::error::Error;
use capnp::{serialize, serialize_packed};
use crypto::{EphemeralBlob, IdHash, Nonce, PublicKey};
#[repr(C)]
#[derive(Debug, Eq, PartialEq)]
#[derive(Debug, BorshSerialize, BorshDeserialize)]
pub enum PacketType {
Handshake {
ephemeral_blob: [u8; 32],
ephemeral_blob: EphemeralBlob,
respond: bool,
},
RsaRequest,
@ -17,251 +17,349 @@ pub enum PacketType {
public_key: [u8; 32],
},
ExtendedHandshake {
ephemeral_blob: [u8; 32],
ephemeral_blob: EphemeralBlob,
encrypted_payload: [[u8; 16]; 32],
respond: bool,
},
GetCapabilities,
Capabilities {
capabilities: u32,
},
Data {
nonce: [u8; 24],
encrypted_payload: Vec<u8>,
nonce: Nonce,
encrypted_payload: Box<[u8]>, // @TODO I still don't like this
},
}
#[repr(C)]
#[derive(Debug, Eq, PartialEq)]
pub struct Packet {
pub id_hash: [u8; 32],
pub data: PacketType,
}
impl PartialEq for PacketType {
fn eq(&self, other: &Self) -> bool {
match self {
PacketType::Handshake {
ephemeral_blob,
respond,
} => {
let ephemeral_blob_self = ephemeral_blob;
let respond_self = respond;
if let PacketType::Handshake {
ephemeral_blob,
respond,
} = other
{
ephemeral_blob == ephemeral_blob_self && respond == respond_self
} else {
false
}
}
PacketType::RsaRequest => {
if let PacketType::RsaRequest = other {
true
} else {
false
}
}
PacketType::RsaInfo {
rsa_key,
public_key,
} => {
let rsa_key_self = rsa_key;
let public_key_self = public_key;
if let PacketType::RsaInfo {
rsa_key,
public_key,
} = other
{
rsa_key == rsa_key_self && public_key == public_key_self
} else {
false
}
}
PacketType::ExtendedHandshake {
ephemeral_blob,
encrypted_payload,
respond,
} => {
let ephemeral_blob_self = ephemeral_blob;
let encrypted_payload_self = encrypted_payload;
let respond_self = respond;
if let PacketType::ExtendedHandshake {
ephemeral_blob,
encrypted_payload,
respond,
} = other
{
ephemeral_blob == ephemeral_blob_self
&& encrypted_payload == encrypted_payload_self
&& respond == respond_self
} else {
false
}
}
PacketType::GetCapabilities => {
if let PacketType::GetCapabilities = other {
true
} else {
false
}
}
PacketType::Capabilities { capabilities } => {
let capabilities_self = capabilities;
impl Packet {
pub fn serialize(&self) -> Vec<u8> {
let mut message = ::capnp::message::Builder::new_default();
{
let mut packet = message.init_root::<packet::Builder>();
packet.set_id_hash(&self.id_hash[..]);
{
let mut packet_type = packet.init_packet_type();
match &self.data {
PacketType::Handshake {
ephemeral_blob,
respond,
} => {
let mut handshake = packet_type.init_handshake();
handshake.set_ephemeral_blob(&ephemeral_blob[..]);
handshake.set_respond(*respond);
}
PacketType::RsaRequest => {
packet_type.set_rsa_request(());
}
PacketType::RsaInfo {
rsa_key,
public_key,
} => {
let mut rsa_info = packet_type.init_rsa_info();
rsa_info.set_rsa_key(bytemuck::cast_slice(&rsa_key[..]));
rsa_info.set_public_key(&public_key[..]);
}
PacketType::ExtendedHandshake {
ephemeral_blob,
encrypted_payload,
} => {
let mut extended_handshake = packet_type.init_extended_handshake();
extended_handshake.set_ephemeral_blob(&ephemeral_blob[..]);
extended_handshake
.set_encrypted_payload(bytemuck::cast_slice(&encrypted_payload[..]));
}
PacketType::GetCapabilities => {
packet_type.set_get_capabilities(());
}
PacketType::Capabilities { capabilities } => {
packet_type.set_capabilities(*capabilities);
}
PacketType::Data {
nonce,
encrypted_payload,
} => {
let mut data = packet_type.init_data();
data.set_nonce(&nonce[..]);
data.set_encrypted_payload(encrypted_payload.as_slice());
}
if let PacketType::Capabilities { capabilities } = other {
capabilities == capabilities_self
} else {
false
}
}
PacketType::Data {
nonce,
encrypted_payload,
} => {
let nonce_self = nonce;
let encrypted_payload_self = encrypted_payload;
if let PacketType::Data {
nonce,
encrypted_payload,
} = other
{
nonce == nonce_self && encrypted_payload == encrypted_payload_self
} else {
false
}
}
}
serialize::write_message_to_words(&message)
}
pub fn deserialize(buffer: &mut Vec<u8>) -> Result<Self, Error> {
let message =
serialize::read_message(buffer.as_slice(), capnp::message::ReaderOptions::new())?;
let packet = message.get_root::<packet::Reader>()?;
fn ne(&self, other: &Self) -> bool {
match self {
PacketType::Handshake {
ephemeral_blob,
respond,
} => {
let ephemeral_blob_self = ephemeral_blob;
let respond_self = respond;
if let PacketType::Handshake {
ephemeral_blob,
respond,
} = other
{
ephemeral_blob != ephemeral_blob_self || respond != respond_self
} else {
true
}
}
PacketType::RsaRequest => {
if let PacketType::RsaRequest = other {
false
} else {
true
}
}
PacketType::RsaInfo {
rsa_key,
public_key,
} => {
let rsa_key_self = rsa_key;
let public_key_self = public_key;
if let PacketType::RsaInfo {
rsa_key,
public_key,
} = other
{
rsa_key != rsa_key_self || public_key != public_key_self
} else {
true
}
}
PacketType::ExtendedHandshake {
ephemeral_blob,
encrypted_payload,
respond,
} => {
let ephemeral_blob_self = ephemeral_blob;
let encrypted_payload_self = encrypted_payload;
let respond_self = respond;
if let PacketType::ExtendedHandshake {
ephemeral_blob,
encrypted_payload,
respond,
} = other
{
ephemeral_blob != ephemeral_blob_self
|| encrypted_payload != encrypted_payload_self
|| respond != respond_self
} else {
true
}
}
PacketType::GetCapabilities => {
if let PacketType::GetCapabilities = other {
false
} else {
true
}
}
PacketType::Capabilities { capabilities } => {
let capabilities_self = capabilities;
match packet.get_packet_type().which() {
Ok(packet::packet_type::Handshake(fields)) => Ok(Self {
id_hash: packet.get_id_hash()?.try_into()?,
data: PacketType::Handshake {
ephemeral_blob: fields.get_ephemeral_blob()?.try_into()?,
respond: fields.get_respond(),
},
}),
Ok(packet::packet_type::RsaRequest(_)) => Ok(Self {
id_hash: packet.get_id_hash()?.try_into()?,
data: PacketType::RsaRequest,
}),
Ok(packet::packet_type::RsaInfo(fields)) => Ok(Self {
id_hash: packet.get_id_hash()?.try_into()?,
data: PacketType::RsaInfo {
rsa_key: bytemuck::cast_slice(fields.get_rsa_key()?).try_into()?,
public_key: fields.get_public_key()?.try_into()?,
},
}),
Ok(packet::packet_type::ExtendedHandshake(fields)) => Ok(Self {
id_hash: packet.get_id_hash()?.try_into()?,
data: PacketType::ExtendedHandshake {
ephemeral_blob: fields.get_ephemeral_blob()?.try_into()?,
encrypted_payload: bytemuck::cast_slice(fields.get_encrypted_payload()?)
.try_into()?,
},
}),
Ok(packet::packet_type::GetCapabilities(_)) => Ok(Self {
id_hash: packet.get_id_hash()?.try_into()?,
data: PacketType::GetCapabilities,
}),
Ok(packet::packet_type::Capabilities(capabilities)) => Ok(Self {
id_hash: packet.get_id_hash()?.try_into()?,
data: PacketType::Capabilities { capabilities },
}),
Ok(packet::packet_type::Data(fields)) => Ok(Self {
id_hash: packet.get_id_hash()?.try_into()?,
data: PacketType::Data {
nonce: fields.get_nonce()?.try_into()?,
encrypted_payload: fields.get_encrypted_payload()?.into(),
},
}),
Err(_) => Err(Error::DeserializationFailure),
if let PacketType::Capabilities { capabilities } = other {
capabilities != capabilities_self
} else {
true
}
}
PacketType::Data {
nonce,
encrypted_payload,
} => {
let nonce_self = nonce;
let encrypted_payload_self = encrypted_payload;
if let PacketType::Data {
nonce,
encrypted_payload,
} = other
{
nonce != nonce_self || encrypted_payload != encrypted_payload_self
} else {
true
}
}
}
}
}
impl Eq for PacketType {}
#[repr(C)]
#[derive(Debug, Eq, PartialEq, BorshDeserialize, BorshSerialize)]
pub struct Packet {
pub id_hash: IdHash,
pub data: PacketType,
}
#[cfg(test)]
mod tests {
use crate::netstar::packet::*;
use crypto::{EphemeralBlob, IdHash, Nonce};
#[test]
fn roundtrip() {
{
let packet = Packet {
id_hash: [125u8; 32],
id_hash: IdHash([125u8; 32]),
data: PacketType::Handshake {
ephemeral_blob: [145u8; 32],
ephemeral_blob: EphemeralBlob([145u8; 32]),
respond: true,
},
};
let mut buffer = Vec::with_capacity(2048);
let mut buffer = packet.serialize();
packet.serialize(&mut buffer);
let roundtrip_packet = Packet::deserialize(&mut buffer).unwrap();
let roundtrip_packet = Packet::deserialize(&mut buffer.as_slice()).unwrap();
assert_eq!(packet, roundtrip_packet);
}
{
let packet = Packet {
id_hash: [198u8; 32],
id_hash: IdHash([198u8; 32]),
data: PacketType::RsaRequest,
};
let mut buffer = Vec::with_capacity(2048);
let mut buffer = packet.serialize();
packet.serialize(&mut buffer);
let roundtrip_packet = Packet::deserialize(&mut buffer).unwrap();
let roundtrip_packet = Packet::deserialize(&mut buffer.as_slice()).unwrap();
assert_eq!(packet, roundtrip_packet);
}
{
let packet = Packet {
id_hash: [198u8; 32],
id_hash: IdHash([198u8; 32]),
data: PacketType::RsaInfo {
rsa_key: [[142u8; 16]; 32],
public_key: [14u8; 32],
},
};
let mut buffer = Vec::with_capacity(2048);
let mut buffer = packet.serialize();
packet.serialize(&mut buffer);
let roundtrip_packet = Packet::deserialize(&mut buffer).unwrap();
let roundtrip_packet = Packet::deserialize(&mut buffer.as_slice()).unwrap();
assert_eq!(packet, roundtrip_packet);
}
{
let packet = Packet {
id_hash: [198u8; 32],
id_hash: IdHash([198u8; 32]),
data: PacketType::ExtendedHandshake {
ephemeral_blob: [124u8; 32],
ephemeral_blob: EphemeralBlob([124u8; 32]),
encrypted_payload: [[47u8; 16]; 32],
respond: true,
},
};
let mut buffer = Vec::with_capacity(2048);
let mut buffer = packet.serialize();
packet.serialize(&mut buffer);
let roundtrip_packet = Packet::deserialize(&mut buffer).unwrap();
let roundtrip_packet = Packet::deserialize(&mut buffer.as_slice()).unwrap();
assert_eq!(packet, roundtrip_packet);
}
{
let packet = Packet {
id_hash: [198u8; 32],
id_hash: IdHash([198u8; 32]),
data: PacketType::GetCapabilities,
};
let mut buffer = Vec::with_capacity(2048);
let mut buffer = packet.serialize();
packet.serialize(&mut buffer);
let roundtrip_packet = Packet::deserialize(&mut buffer).unwrap();
let roundtrip_packet = Packet::deserialize(&mut buffer.as_slice()).unwrap();
assert_eq!(packet, roundtrip_packet);
}
{
let packet = Packet {
id_hash: [198u8; 32],
id_hash: IdHash([198u8; 32]),
data: PacketType::Capabilities {
capabilities: 5646879,
},
};
let mut buffer = Vec::with_capacity(2048);
let mut buffer = packet.serialize();
packet.serialize(&mut buffer);
let roundtrip_packet = Packet::deserialize(&mut buffer).unwrap();
let roundtrip_packet = Packet::deserialize(&mut buffer.as_slice()).unwrap();
assert_eq!(packet, roundtrip_packet);
}
{
let packet = Packet {
id_hash: [198u8; 32],
id_hash: IdHash([198u8; 32]),
data: PacketType::Data {
nonce: [24u8; 24],
encrypted_payload: Vec::new(),
nonce: Nonce([24u8; 24]),
encrypted_payload: Box::new([58u8, 45u8]) as Box<[u8]>,
},
};
let mut buffer = Vec::with_capacity(2048);
let mut buffer = packet.serialize();
packet.serialize(&mut buffer);
let roundtrip_packet = Packet::deserialize(&mut buffer).unwrap();
let roundtrip_packet = Packet::deserialize(&mut buffer.as_slice()).unwrap();
assert_eq!(packet, roundtrip_packet);
}

6
src/netstar/peer.rs

@ -1,5 +1,7 @@
use crate::error::Error;
use crypto::{EphemeralBlob, IdHash, PrivateKey, PublicKey, SharedKey, SharedSecret};
use crypto::{
EphemeralBlob, IdHash, PrivateKey, PublicKey, SharedKey, SharedSecret, XChaCha20Poly1305,
};
use rand::{CryptoRng, RngCore};
use std::fmt::Debug;
@ -15,6 +17,7 @@ pub enum PeerState {
endpoint: SocketAddr,
ephemeral_blob_b: EphemeralBlob,
shared_key: SharedKey,
xchacha20poly1305: XChaCha20Poly1305,
},
}
@ -249,6 +252,7 @@ impl Peer {
endpoint,
ephemeral_blob_b,
shared_key,
xchacha20poly1305: XChaCha20Poly1305::new(private_key_a),
};
Ok(())

30
src/netstar/worker.rs

@ -1,6 +1,28 @@
use std::net::SocketAddr;
use crate::netstar::packet::Packet;
use crypto::IdHash;
pub enum Work {
Decrypted { vec: Vec<u8> },
Encrypted { vec: Vec<u8> },
Serialized { vec: Vec<u8> },
Deserialized { vec: Vec<u8> },
Decrypted {
plaintext: Vec<u8>,
ciphertext: Vec<u8>,
endpoint: SocketAddr,
},
Encrypted {
plaintext: Vec<u8>,
ciphertext: Vec<u8>,
endpoint: SocketAddr,
id_hash_b: IdHash,
},
Serialized {
out_buffer: Vec<u8>,
id_hash_b: IdHash,
endpoint: SocketAddr,
},
Deserialized {
vec: Vec<u8>,
packet: Packet,
endpoint: SocketAddr,
},
}

Loading…
Cancel
Save