Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Alpha Ring Support #14

Merged
merged 9 commits into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
868 changes: 316 additions & 552 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,5 @@ This tool was a quick early pandemic project to learn rust, and has similar idea
[codecov]: https://img.shields.io/codecov/c/github/landhb/portal?style=flat-square
[codecov-url]: https://codecov.io/gh/landhb/portal

[build]: https://img.shields.io/github/workflow/status/landhb/portal/Build/master?style=flat-square
[build]: https://img.shields.io/github/actions/workflow/status/landhb/portal/build.yml?branch=main&style=flat-square
[build-url]: https://github.com/landhb/portal/actions?query=workflow%3ABuild
8 changes: 3 additions & 5 deletions client/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "portal-client"
version = "0.4.0"
version = "0.5.0"
authors = ["landhb <landhb@github>"]
edition = "2018"
description = """
Expand All @@ -25,8 +25,7 @@ bench = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
portal-lib = {path ="../lib",version = "0.4.0"}
anyhow = "1.0.32"
portal-lib = {path ="../lib",version = "0.5.0"}
dialoguer = "0.10.0"
indicatif = "0.16.2"
colored = "2.0.0"
Expand All @@ -36,6 +35,5 @@ dns-lookup = "1.0.4"
directories = "3.0.1"
lazy_static = "1.4.0"
rand = "0.7.3"
async-std = "1.6.5"
prettytable-rs = "^0.10"
structopt = { version = "0.3", default-features = false }
structopt = { version = "0.3", default-features = false }
1 change: 0 additions & 1 deletion client/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
extern crate portal_lib as portal;

use anyhow::Result;
use colored::*;
use dns_lookup::lookup_host;
use indicatif::{MultiProgress, ProgressBar, ProgressDrawTarget, ProgressStyle};
Expand Down
14 changes: 6 additions & 8 deletions client/src/receive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,12 @@ pub fn recv_all(client: &mut TcpStream, download_directory: PathBuf) -> Result<(
pb.tick();

// Receive the file
let _metadata = portal
.recv_file(
client,
Path::new(&download_directory),
Some(&metadata),
Some(progress),
)
.ok();
let _metadata = portal.recv_file(
client,
Path::new(&download_directory),
Some(&metadata),
Some(progress),
)?;

pb.finish();
}
Expand Down
4 changes: 2 additions & 2 deletions client/src/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ fn add_all(info: &mut TransferInfo, dir: PathBuf) -> Result<(), Box<dyn Error>>

// Collect all entries
let entries = std::fs::read_dir(dir)?
.filter_map(|res| res.as_ref().map_or(None, |e| check_file(e)))
.filter_map(|res| res.as_ref().map_or(None, check_file))
.collect::<Vec<PathBuf>>();

// Add them individually
Expand Down Expand Up @@ -110,7 +110,7 @@ pub fn send_all(client: &mut TcpStream, files: Vec<PathBuf>) -> Result<(), Box<d
};

// Begin the transfer
let _sent = portal.send_file(client, &fullpath, Some(progress)).ok();
let _sent = portal.send_file(client, fullpath, Some(progress))?;

pb.finish();
}
Expand Down
6 changes: 3 additions & 3 deletions lib/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "portal-lib"
version = "0.4.0"
version = "0.5.0"
authors = ["landhb <landhb@github>"]
edition = "2018"
description = """
Expand All @@ -20,7 +20,7 @@ license = "Apache-2.0 OR MIT"
[features]
default = ["rustcrypto-backend"]
rustcrypto-backend = ["chacha20poly1305"]
#ring-backend = ["ring"]
ring-backend = ["ring"]

[lib]
bench = false
Expand All @@ -44,7 +44,7 @@ hex = "0.4.2"
rand = "0.7.3"
hkdf = "0.9.0"
chacha20poly1305 = {version="0.9.0",features=["heapless"], optional=true}
#ring = {git="https://github.com/briansmith/ring", rev="2896a014de94d670a6913156c9f31d8de8a2323b", optional = true}
ring = {version = "0.17", optional = true}

# ---------------------------------------------------
# Dependencies only used for running tests
Expand Down
2 changes: 1 addition & 1 deletion lib/src/errors.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use thiserror::Error;

#[derive(Error, Debug, PartialEq)]
#[derive(Error, Debug, PartialEq, Eq)]
pub enum PortalError {
#[error("Value doesn't exist")]
NoneError,
Expand Down
26 changes: 13 additions & 13 deletions lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ pub const NO_PROGRESS_CALLBACK: Option<fn(usize)> = None::<fn(usize)>;
/**
* The primary interface into the library.
*/
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Eq, Debug)]
pub struct Portal {
// Information to correlate
// connections on the relay
Expand Down Expand Up @@ -100,11 +100,11 @@ impl Portal {
let mut hasher = Sha256::new();
hasher.update(&id);
let id_bytes = hasher.finalize();
let id_hash = hex::encode(&id_bytes);
let id_hash = hex::encode(id_bytes);

// Initialize the state
let (s1, outbound_msg) = Spake2::<Ed25519Group>::start_symmetric(
&Password::new(&password.as_bytes()),
&Password::new(password.as_bytes()),
&Identity::new(&id_bytes),
);

Expand Down Expand Up @@ -336,7 +336,7 @@ impl Portal {
.ok_or(BadFileName)?;

// Map the file into memory
let mut mmap = self.map_readable_file(&path)?;
let mut mmap = self.map_readable_file(path)?;

// Create the metatada object
let metadata = Metadata {
Expand All @@ -358,9 +358,9 @@ impl Portal {

// Increment and optionally invoke callback
total_sent += chunk.len();
callback.as_ref().map(|c| {
if let Some(c) = callback.as_ref() {
c(total_sent);
});
}
}
Ok(total_sent)
}
Expand Down Expand Up @@ -430,13 +430,13 @@ impl Portal {
let mut total = 0;
for chunk in mmap[..].chunks_mut(CHUNK_SIZE) {
// Receive the entire chunk in-place
Protocol::read_encrypted_zero_copy(peer, &key, chunk)?;
Protocol::read_encrypted_zero_copy(peer, key, chunk)?;

// Increment and optionally invoke callback
total += chunk.len();
display.as_ref().map(|c| {
if let Some(c) = display.as_ref() {
c(total);
});
}
}

// Check for incomplete transfers
Expand All @@ -447,19 +447,19 @@ impl Portal {
}

/// Helper: mmap's a file into memory for reading
fn map_readable_file<'a>(&'a self, f: &PathBuf) -> Result<MmapMut, Box<dyn Error>> {
fn map_readable_file(&self, f: &PathBuf) -> Result<MmapMut, Box<dyn Error>> {
let file = File::open(f)?;
let mmap = unsafe { MmapOptions::new().map_copy(&file)? };
Ok(mmap)
}

/// Helper: mmap's a file into memory for writing
fn map_writeable_file<'a>(&'a self, f: &PathBuf, size: u64) -> Result<MmapMut, Box<dyn Error>> {
fn map_writeable_file(&self, f: &PathBuf, size: u64) -> Result<MmapMut, Box<dyn Error>> {
let file = OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(&f)?;
.open(f)?;

file.set_len(size)?;
let mmap = unsafe { MmapOptions::new().map_mut(&file)? };
Expand All @@ -469,7 +469,7 @@ impl Portal {
/// Returns a copy of the Portal::Direction associated with
/// this Portal request
pub fn get_direction(&self) -> Direction {
self.direction.clone()
self.direction
}

/// Sets the Portal::Direction associated with this Poral request
Expand Down
30 changes: 18 additions & 12 deletions lib/src/protocol/encrypted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@ const TAG_SIZE: usize = 16;
/// An abstraction around a nonce sequence. Safely
/// ensures there is no nonce re-use during a session
/// with a single key.
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Eq, Debug)]
pub struct NonceSequence([u8; TAG_SIZE]);

/// All encrypted messages must have associated state data (nonce, tag)
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Default)]
#[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, Default)]
pub struct EncryptedMessage {
/// Provides storage for chacha20poly1305::Nonce
pub nonce: [u8; NONCE_SIZE],
Expand All @@ -45,14 +45,16 @@ impl EncryptedMessage {
data: &mut [u8],
) -> Result<Self, Box<dyn Error>> {
// Init state to send
let mut state = Self::default();
let mut state = Self {
nonce: nseq.next_unique()?,
..Default::default()
};

// Obtain the next nonce
state.nonce = nseq.next()?;
let nonce = Nonce::from_slice(&state.nonce);

// Obtain the cipher from the key
let cha_key = Key::from_slice(&key[..]);
let cha_key = Key::from_slice(key);
let cipher = ChaCha20Poly1305::new(cha_key);

// Set the length
Expand All @@ -71,7 +73,7 @@ impl EncryptedMessage {
/// Decrypt the provided data in-place
pub fn decrypt(&mut self, key: &[u8], data: &mut [u8]) -> Result<usize, Box<dyn Error>> {
// Obtain the cipher from the key
let cha_key = Key::from_slice(&key[..]);
let cha_key = Key::from_slice(key);
let cipher = ChaCha20Poly1305::new(cha_key);

// The nonce & tag are self contained
Expand All @@ -80,7 +82,7 @@ impl EncryptedMessage {

// Decrypt the data in place
cipher
.decrypt_in_place_detached(&nonce, b"", data, &tag)
.decrypt_in_place_detached(nonce, b"", data, tag)
.or(Err(DecryptError))?;

Ok(data.len())
Expand Down Expand Up @@ -139,18 +141,22 @@ impl EncryptedMessage {
}
}

impl Default for NonceSequence {
fn default() -> Self {
Self::new()
}
}

impl NonceSequence {
/// Initialize the sequence by generating a random 128bit nonce
pub fn new() -> Self {
let mut rng = rand::thread_rng();
Self {
0: rng.gen::<[u8; 16]>(),
}
Self(rng.gen::<[u8; 16]>())
}

/// Advance the sequence by incrementing the internal state
/// and returning the current state. Similar nonces in TLS 1.3
pub fn next(&mut self) -> Result<[u8; NONCE_SIZE], Box<dyn Error>> {
pub fn next_unique(&mut self) -> Result<[u8; NONCE_SIZE], Box<dyn Error>> {
// Save the old value
let old = self.0;

Expand All @@ -159,6 +165,6 @@ impl NonceSequence {
self.0 = new.wrapping_add(1).wrapping_shl(32).to_be_bytes();

// Return the old value as a nonce
old[..NONCE_SIZE].try_into().or(Err(CryptoError.into()))
Ok(old[..NONCE_SIZE].try_into().or(Err(CryptoError))?)
}
}
19 changes: 10 additions & 9 deletions lib/src/protocol/exchange.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ use serde::{Deserialize, Serialize};

/// A data format exchanged by each peer to derive
/// the shared session key
#[derive(PartialEq, Debug, Copy, Clone)]
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub struct PortalKeyExchange([u8; 33]);

/// A data format exchanged by each peer to confirm
/// that they have each derived the same key
#[derive(PartialEq, Debug, Copy, Clone)]
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
pub struct PortalConfirmation(pub [u8; 42]);

/// Provide a serde visitor to serialize/deserialize larger arrays
Expand All @@ -35,8 +35,8 @@ where
A: SeqAccess<'de>,
{
let mut arr = [T::default(); N];
for i in 0..N {
arr[i] = seq
for (i, item) in arr.iter_mut().enumerate().take(N) {
*item = seq
.next_element()?
.ok_or_else(|| Error::invalid_length(i, &self))?;
}
Expand All @@ -55,7 +55,7 @@ impl<'de> Deserialize<'de> for PortalKeyExchange {
let res =
deserializer.deserialize_tuple(std::mem::size_of::<PortalKeyExchange>(), visitor)?;

Ok(Self { 0: res })
Ok(Self(res))
}
}

Expand All @@ -72,6 +72,7 @@ impl Serialize for PortalKeyExchange {
}
}

#[allow(clippy::from_over_into)]
impl<'a> Into<&'a [u8]> for &'a PortalKeyExchange {
fn into(self) -> &'a [u8] {
&self.0
Expand All @@ -81,10 +82,10 @@ impl<'a> Into<&'a [u8]> for &'a PortalKeyExchange {
impl TryFrom<Vec<u8>> for PortalKeyExchange {
type Error = &'static str;
fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> {
Ok(Self {
0: v.try_into()
Ok(Self(
v.try_into()
.or(Err("Cannot convert into PortalKeyExchange"))?,
})
))
}
}

Expand All @@ -99,7 +100,7 @@ impl<'de> Deserialize<'de> for PortalConfirmation {
let res =
deserializer.deserialize_tuple(std::mem::size_of::<PortalConfirmation>(), visitor)?;

Ok(Self { 0: res })
Ok(Self(res))
}
}

Expand Down
Loading
Loading